From 5c0a007972cad1e7108d6a19d50f346dc508ee85 Mon Sep 17 00:00:00 2001 From: alexander-sei Date: Fri, 7 Aug 2026 15:02:41 +0200 Subject: [PATCH 1/4] chore(docs): retire the legacy SeiJS docs site Remove the in-repo Mintlify stack and route MCP documentation search and links through docs.sei.io. Co-authored-by: Cursor --- .changeset/remove-docs-integrations.md | 5 + README.md | 9 +- docs/contributing.mdx | 165 - docs/create-sei/quick-start.mdx | 75 - docs/create-sei/templates.mdx | 60 - docs/create-sei/welcome.mdx | 29 - docs/docs.json | 177 - docs/favicon.ico | Bin 15406 -> 0 bytes docs/introduction.mdx | 108 - docs/ledger/introduction.mdx | 200 - docs/llms-full.txt | 193 - docs/llms.txt | 33 - docs/mcp-server/context.mdx | 29 - docs/mcp-server/environment-variables.mdx | 291 - docs/mcp-server/introduction.mdx | 162 - docs/mcp-server/prompts.mdx | 50 - docs/mcp-server/quickstart.mdx | 253 - docs/mcp-server/tools.mdx | 158 - docs/mcp-server/transports.mdx | 166 - docs/mcp-server/troubleshooting.mdx | 231 - docs/overview.mdx | 140 - docs/precompiles/introduction.mdx | 34 - docs/precompiles/precompiles/address.mdx | 459 -- docs/precompiles/precompiles/bank.mdx | 347 -- docs/precompiles/precompiles/distribution.mdx | 628 -- docs/precompiles/precompiles/governance.mdx | 470 -- docs/precompiles/precompiles/ibc.mdx | 708 --- docs/precompiles/precompiles/json.mdx | 712 --- docs/precompiles/precompiles/oracle.mdx | 352 -- docs/precompiles/precompiles/pointer.mdx | 818 --- docs/precompiles/precompiles/pointerview.mdx | 834 --- docs/precompiles/precompiles/staking.mdx | 470 -- docs/precompiles/precompiles/wasm.mdx | 789 --- docs/precompiles/quick-start.mdx | 208 - docs/sei-global-wallet/connectkit.mdx | 337 -- docs/sei-global-wallet/dynamic-nextjs.mdx | 528 -- docs/sei-global-wallet/introduction.mdx | 96 - docs/sei-global-wallet/quickstart.mdx | 153 - docs/sei-global-wallet/rainbowkit.mdx | 230 - docs/sei-global-wallet/wagmi-dynamic.mdx | 413 -- docs/sei-global-wallet/web3-react.mdx | 415 -- docs/x402/clients/fetch.mdx | 163 - docs/x402/facilitators/example.mdx | 281 - docs/x402/facilitators/introduction.mdx | 121 - docs/x402/introduction.mdx | 65 - docs/x402/overview.mdx | 79 - docs/x402/packages/x402-axios.mdx | 103 - docs/x402/packages/x402-express.mdx | 164 - docs/x402/packages/x402-fetch.mdx | 98 - docs/x402/packages/x402-hono.mdx | 139 - docs/x402/packages/x402-next.mdx | 214 - docs/x402/packages/x402.mdx | 58 - docs/x402/quickstart.mdx | 244 - package.json | 12 +- packages/create-sei/README.md | 9 +- .../next-template/src/app/resources/page.tsx | 63 +- .../src/app/resources/resources.ts | 7 - packages/ledger/README.md | 9 +- packages/mcp-server/.npmignore | 3 - packages/mcp-server/README.md | 7 +- packages/mcp-server/package.json | 1 - packages/mcp-server/src/docs/server.ts | 115 +- packages/mcp-server/src/mintlify/config.ts | 4 - packages/mcp-server/src/mintlify/index.ts | 1 - packages/mcp-server/src/mintlify/search.ts | 89 - packages/mcp-server/src/mintlify/types.ts | 28 - packages/mcp-server/src/mintlify/utils.ts | 9 - packages/mcp-server/src/server/server.ts | 15 +- .../mcp-server/src/tests/core/tools.test.ts | 222 - .../mcp-server/src/tests/docs/server.test.ts | 73 + .../src/tests/server/server.test.ts | 48 +- packages/precompiles/README.md | 9 +- packages/sei-global-wallet/README.md | 9 +- pnpm-lock.yaml | 5283 +---------------- 74 files changed, 213 insertions(+), 19067 deletions(-) create mode 100644 .changeset/remove-docs-integrations.md delete mode 100644 docs/contributing.mdx delete mode 100644 docs/create-sei/quick-start.mdx delete mode 100644 docs/create-sei/templates.mdx delete mode 100644 docs/create-sei/welcome.mdx delete mode 100644 docs/docs.json delete mode 100644 docs/favicon.ico delete mode 100644 docs/introduction.mdx delete mode 100644 docs/ledger/introduction.mdx delete mode 100644 docs/llms-full.txt delete mode 100644 docs/llms.txt delete mode 100644 docs/mcp-server/context.mdx delete mode 100644 docs/mcp-server/environment-variables.mdx delete mode 100644 docs/mcp-server/introduction.mdx delete mode 100644 docs/mcp-server/prompts.mdx delete mode 100644 docs/mcp-server/quickstart.mdx delete mode 100644 docs/mcp-server/tools.mdx delete mode 100644 docs/mcp-server/transports.mdx delete mode 100644 docs/mcp-server/troubleshooting.mdx delete mode 100644 docs/overview.mdx delete mode 100644 docs/precompiles/introduction.mdx delete mode 100644 docs/precompiles/precompiles/address.mdx delete mode 100644 docs/precompiles/precompiles/bank.mdx delete mode 100644 docs/precompiles/precompiles/distribution.mdx delete mode 100644 docs/precompiles/precompiles/governance.mdx delete mode 100644 docs/precompiles/precompiles/ibc.mdx delete mode 100644 docs/precompiles/precompiles/json.mdx delete mode 100644 docs/precompiles/precompiles/oracle.mdx delete mode 100644 docs/precompiles/precompiles/pointer.mdx delete mode 100644 docs/precompiles/precompiles/pointerview.mdx delete mode 100644 docs/precompiles/precompiles/staking.mdx delete mode 100644 docs/precompiles/precompiles/wasm.mdx delete mode 100644 docs/precompiles/quick-start.mdx delete mode 100644 docs/sei-global-wallet/connectkit.mdx delete mode 100644 docs/sei-global-wallet/dynamic-nextjs.mdx delete mode 100644 docs/sei-global-wallet/introduction.mdx delete mode 100644 docs/sei-global-wallet/quickstart.mdx delete mode 100644 docs/sei-global-wallet/rainbowkit.mdx delete mode 100644 docs/sei-global-wallet/wagmi-dynamic.mdx delete mode 100644 docs/sei-global-wallet/web3-react.mdx delete mode 100644 docs/x402/clients/fetch.mdx delete mode 100644 docs/x402/facilitators/example.mdx delete mode 100644 docs/x402/facilitators/introduction.mdx delete mode 100644 docs/x402/introduction.mdx delete mode 100644 docs/x402/overview.mdx delete mode 100644 docs/x402/packages/x402-axios.mdx delete mode 100644 docs/x402/packages/x402-express.mdx delete mode 100644 docs/x402/packages/x402-fetch.mdx delete mode 100644 docs/x402/packages/x402-hono.mdx delete mode 100644 docs/x402/packages/x402-next.mdx delete mode 100644 docs/x402/packages/x402.mdx delete mode 100644 docs/x402/quickstart.mdx delete mode 100644 packages/mcp-server/src/mintlify/config.ts delete mode 100644 packages/mcp-server/src/mintlify/index.ts delete mode 100644 packages/mcp-server/src/mintlify/search.ts delete mode 100644 packages/mcp-server/src/mintlify/types.ts delete mode 100644 packages/mcp-server/src/mintlify/utils.ts create mode 100644 packages/mcp-server/src/tests/docs/server.test.ts diff --git a/.changeset/remove-docs-integrations.md b/.changeset/remove-docs-integrations.md new file mode 100644 index 000000000..1818e01ef --- /dev/null +++ b/.changeset/remove-docs-integrations.md @@ -0,0 +1,5 @@ +--- +'@sei-js/mcp-server': minor +--- + +Replace the legacy SeiJS-specific Mintlify/Trieve search with the official docs.sei.io MCP endpoint. diff --git a/README.md b/README.md index 84616c074..cb5a6c75f 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,9 @@ SeiJS is a monorepo that contains multiple NPM libraries for writing applications that interact with Sei. -## Documentation - -Please check [our documentation](https://sei-js.docs.sei.io) for notes on how to get up and running. - ## Packages -SeiJS consists of smaller NPM packages within the @sei-js namespace. For more detailed documentation on each package, -please refer to the table below. +SeiJS consists of smaller NPM packages within the @sei-js namespace. See the package READMEs below for usage details. | Package | Description | |---------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------| @@ -39,4 +34,4 @@ The correct Yarn version will be automatically used thanks to the `packageManage ### Building -To build all packages and docs, run `pnpm install` then `pnpm build:all` +To build all packages, run `pnpm install` then `pnpm build:all` diff --git a/docs/contributing.mdx b/docs/contributing.mdx deleted file mode 100644 index 816125af1..000000000 --- a/docs/contributing.mdx +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: Contributing -description: Contributing to @sei-js - Complete guide to local development setup, testing, and pull request process -icon: "hand-heart" ---- - -## Getting Started - -Welcome to the @sei-js contributor community! This guide will help you set up your local development environment and contribute to the project. - -### Prerequisites - -Before you begin, ensure you have: - -- **nvm** (Node Version Manager) -- **Yarn** (4.7.0) - -### Local Development Setup - - - - 1. Fork the [@sei-js repository](https://github.com/sei-protocol/sei-js) on GitHub - 2. Clone your fork locally: - - ```bash - git clone git@github.com:sei-protocol/sei-js.git - cd sei-js - ``` - - - This creates your own copy of the repository that you can modify freely. - - - - - Switch to the project's required Node.js version: - - ```bash - nvm use - ``` - - - This will use Node.js v20 as specified in the project's `.nvmrc` file. - - - - You should see a message confirming you're now using the correct Node.js version. - - - - - Install all dependencies and link packages: - - ```bash - yarn install - ``` - - - This installs dependencies for all packages in the monorepo and sets up workspace linking. - - - - - Build all packages in the correct order: - - ```bash - pnpm build:all - ``` - - - This ensures all packages are built and ready for development. - - - - - Verify everything is working: - - ```bash - # Run all tests - yarn test:all - - # Run tests with coverage report - yarn test:coverage - ``` - - - All tests should pass and you should see coverage reports for each package. - - - - Coverage reports help ensure your changes don't reduce test coverage. Look for coverage percentages in the output. - - - - - Start the documentation server to verify everything is set up correctly: - - ```bash - yarn docs - ``` - - - This will start the documentation server at `http://localhost:3000` - - - - The documentation should open in your browser and display without errors. - - - - -## Project Structure - -Understanding the monorepo structure will help you navigate and contribute effectively: - -``` -sei-js/ -├── packages/ -│ ├── create-sei/ # CLI scaffolding tool -│ ├── precompiles/ # EVM precompile contracts and integrations -│ ├── ledger/ # Ledger hardware wallet support -│ ├── registry/ # Chain and asset registry -│ ├── sei-global-wallet/ # Global wallet provider -│ └── mcp-server/ # MCP server for AI integration -├── docs/ # Documentation site -└── ... -``` - -## Development Workflow - -### Code Quality and Standards - -We use **Biome** for code formatting and linting. Configure your IDE to use Biome for the best development experience: - -```bash -# Check your code -yarn biome check - -# Auto-fix formatting and linting issues -yarn biome check --apply -``` - - -Configure your IDE to use the project's Biome configuration for automatic formatting and linting as you code. - - -### Running Tests - -Run tests to ensure your changes work correctly: - -```bash -# Run all tests -yarn test:all - -# Run tests with coverage report -yarn test:coverage -``` - - -Always aim for **100% code coverage** in your contributions. Add comprehensive tests for any new functionality or bug fixes. - - -## Making Changes - -That's it! You're ready to start contributing to @sei-js. Make your changes, test them thoroughly with the commands above, and submit your pull request when ready. diff --git a/docs/create-sei/quick-start.mdx b/docs/create-sei/quick-start.mdx deleted file mode 100644 index 8b1836ed2..000000000 --- a/docs/create-sei/quick-start.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: 'Quick Start' -description: 'Get started with @sei-js/create-sei in minutes' -icon: "play" ---- - -## Installation - -You don't need to install `@sei-js/create-sei` globally. Use it directly with npx or pnpm: - - - -```bash npx -npx @sei-js/create-sei app -name my-sei-app -``` - -```bash pnpm -pnpm create @sei-js/create-sei app -name my-sei-app -``` - - - -## Interactive Setup - -The CLI provides an interactive wizard to guide you through project setup: - - - - Execute the create-sei command with your project name: - ```bash - npx @sei-js/create-sei app - ``` - - - - - `cd my-sei-app` - - `yarn install` - - `yarn dev` - - - - - The CLI automatically configures: - - TypeScript configuration - - Up to date NextJS - - Tailwind CSS styling - - Biome formatting - - Mantine UI components - - Git initialization - - - -### CLI Options - -- `app`: Create a new Sei dApp - - `--name`: Project name (must be valid package name) - - `--extension`: Add one of the optional extensions to your project - -- `list-extensions`: List the available extensions - - -**Template Combinations**: The CLI creates different project templates based on your flag combinations. See all available combinations on the [Templates page](/create-sei/templates). - - -## What Happens Next - -After running the CLI, you'll have a fully configured Sei dApp ready for development: - -- **Project Structure Created** - Organized file structure with components, hooks, and utilities properly scaffolded. - -- **Wallet Integration Ready** - Pre-configured wallet connections and connection hooks ready to use. - -- **Development Tools Configured** - TypeScript, Biome, Mantine UI, and Tailwind CSS automatically configured with sensible defaults and ready for immediate development. - -- **Sei Network Integration** - Built-in Sei network configuration and contract interaction examples to help you start building on Sei right away. \ No newline at end of file diff --git a/docs/create-sei/templates.mdx b/docs/create-sei/templates.mdx deleted file mode 100644 index ef73ee51a..000000000 --- a/docs/create-sei/templates.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: "Templates" -description: "Choose from a collection of templates to quickly scaffold your Sei dApps. Each template comes pre-configured with wallet connection, network setup, and essential development tools." -icon: "grid-2" ---- - - -**New to @sei-js/create-sei?** Check out our [Quick Start guide](/create-sei/quick-start) for step-by-step instructions on getting started. This page is a reference for all available template combinations. - - -## Default Template - - - Production-ready Next.js application with Wagmi for type-safe Ethereum wallet connections and blockchain interactions. Includes built-in support for MetaMask, WalletConnect, Coinbase Wallet, and other popular wallets. Best for full-stack dApps requiring server-side rendering, SEO optimization, and robust wallet integration. - -
- - **Tech Stack:** `Next.js 14` `Wagmi v2` `Viem` `TanStack Query` `Tailwind CSS` - - ```bash - npx @sei-js/create-sei app --name my-sei-app - ``` -
- ---- - -## Extensions - -Enhance your templates with additional functionality using extensions: - - - - View all available extensions that can be added to your project: - - ```bash - npx @sei-js/create-sei list-extensions - ``` - - - - Add Sei precompile contract integration with examples for querying native blockchain data like token supply, staking info, and governance proposals. Perfect for dApps that need to interact with Sei's built-in smart contracts. - -
- - **Features:** Bank precompile, Staking precompile, Governance precompile examples - - ```bash - npx @sei-js/create-sei app --name my-sei-precompile-app --extension precompiles - ``` -
-
diff --git a/docs/create-sei/welcome.mdx b/docs/create-sei/welcome.mdx deleted file mode 100644 index 203d72984..000000000 --- a/docs/create-sei/welcome.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: 'Introduction' -description: 'CLI tool for scaffolding Sei applications' -icon: "hammer" ---- - -## Overview - -`@sei-js/create-sei` is a CLI tool that scaffolds production-ready Sei dApps in seconds. Quickly spin up templates with Next.js/Vite, modern wallet integration, and TypeScript support. - -```bash -npx @sei-js/create-sei app --name my-sei-app -``` - - - - Modern Ethereum-compatible development with Wagmi/Viem or Ethers.js - - - Next.js for full-stack apps, Vite for lightweight builds - - - TypeScript, Tailwind CSS, Mantine, Biome, and wallet connections included - - - -## What's Included - -Every project includes wallet connections, contract interactions, TypeScript, Tailwind CSS, Biome for formatting, and responsive layouts. No additional setup required. \ No newline at end of file diff --git a/docs/docs.json b/docs/docs.json deleted file mode 100644 index 4463fc077..000000000 --- a/docs/docs.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "$schema": "https://mintlify.com/docs.json", - "name": "SeiJS Documentation", - "theme": "mint", - "logo": { - "dark": "https://cdn.sei.io/sei.svg", - "light": "https://cdn.sei.io/sei.svg" - }, - "description": "Official TypeScript SDK for building decentralized applications on Sei Network. Complete @sei-js toolkit for EVM development, wallet integration, and blockchain interactions.", - "favicon": "/favicon.ico", - "colors": { - "primary": "#9E1F19", - "light": "#B52A2A", - "dark": "#780000" - }, - "contextual": { - "options": ["copy", "chatgpt", "claude"] - }, - "navigation": { - "global": { - "anchors": [ - { - "anchor": "Sei Documentation", - "icon": "book-open-cover", - "href": "https://docs.sei.io" - }, - { - "anchor": "Sei App", - "icon": "grid-2", - "href": "https://app.sei.io" - }, - { - "anchor": "GitHub", - "icon": "github", - "href": "https://github.com/sei-protocol/sei-js" - } - ] - }, - "dropdowns": [ - { - "dropdown": "Getting Started", - "icon": "rocket", - "pages": [ - { - "group": "Introduction", - "pages": ["introduction", "overview"] - }, - { - "group": "Local Development", - "pages": ["contributing"] - } - ] - }, - { - "dropdown": "@sei-js/mcp-server", - "description": "Teach your LLM about Sei", - "icon": "robot", - "pages": [ - { - "group": "About", - "pages": ["mcp-server/introduction", "mcp-server/transports"] - }, - { - "group": "Setup", - "pages": ["mcp-server/quickstart", "mcp-server/environment-variables", "mcp-server/troubleshooting"] - }, - { - "group": "Capabilities", - "pages": ["mcp-server/tools", "mcp-server/prompts", "mcp-server/context"] - } - ] - }, - { - "dropdown": "@sei-js/create-sei", - "description": "Boilerplate frontend dApps", - "icon": "hammer", - "pages": [ - { - "group": "Getting Started", - "pages": ["create-sei/welcome", "create-sei/quick-start", "create-sei/templates"] - } - ] - }, - { - "dropdown": "@sei-js/sei-global-wallet", - "description": "User friendly wallet connect", - "icon": "wallet", - "pages": [ - { - "group": "Getting Started", - "pages": ["sei-global-wallet/introduction", "sei-global-wallet/quickstart"] - }, - { - "group": "Integrations", - "pages": [ - "sei-global-wallet/rainbowkit", - "sei-global-wallet/connectkit", - "sei-global-wallet/web3-react", - "sei-global-wallet/wagmi-dynamic", - "sei-global-wallet/dynamic-nextjs" - ] - } - ] - }, - { - "dropdown": "@sei-js/precompiles", - "description": "Native functions from the EVM", - "icon": "microchip", - "pages": [ - { - "group": "Getting Started", - "pages": ["precompiles/introduction", "precompiles/quick-start"] - }, - { - "group": "Precompiles", - "pages": [ - "precompiles/precompiles/address", - "precompiles/precompiles/bank", - "precompiles/precompiles/distribution", - "precompiles/precompiles/governance", - "precompiles/precompiles/ibc", - "precompiles/precompiles/json", - "precompiles/precompiles/oracle", - "precompiles/precompiles/pointer", - "precompiles/precompiles/pointerview", - "precompiles/precompiles/staking", - "precompiles/precompiles/wasm" - ] - } - ] - }, - { - "dropdown": "@sei-js/ledger", - "description": "Hardware wallet connection", - "icon": "shield", - "pages": ["ledger/introduction"] - }, - { - "dropdown": "x402", - "description": "HTTP micro payments", - "icon": "credit-card", - "pages": [ - { - "group": "Introduction", - "pages": ["x402/introduction", "x402/overview", "x402/quickstart"] - }, - { - "group": "Facilitators", - "pages": ["x402/facilitators/introduction", "x402/facilitators/example"] - }, - { - "group": "Client Integration", - "pages": ["x402/clients/fetch"] - }, - { - "group": "Packages", - "pages": [ - "x402/packages/x402", - "x402/packages/x402-fetch", - "x402/packages/x402-axios", - "x402/packages/x402-express", - "x402/packages/x402-hono", - "x402/packages/x402-next" - ] - } - ] - } - ] - }, - "footer": { - "socials": { - "x": "https://x.com/SeiNetwork", - "github": "https://github.com/sei-protocol/sei-js", - "linkedin": "https://www.linkedin.com/company/sei-protocol" - } - } -} diff --git a/docs/favicon.ico b/docs/favicon.ico deleted file mode 100644 index fd7dbaea279e567231960d8ada2b89a628087471..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15406 zcmeHOc~l$cwTGsCNwYUeTPJN3XHVS3K^jT3Nn((Mgai^=5CSA&;`XKOOOu=~FR#ft zZr#%*P1>{xHnsuV*x)6`2HO}g1Y-)kAxckhfw5?DBPn)Cj7 z)j5|L&5XXe_xtX5zx(}umzbE?nA>9Rzdr_!Q)7Pm^_Un{Oiawwsp9wNz7-R*7_P;| z1@Au-6SL#nF)`17mg?JqfH}x@SkH~cDfq4n)fddKZW0w*%gBLmVV3$ri_<>$? za@vg=Nz@#EQ^y<}(=ms59dnr1u{{?P*uHvbYYWE?T;bG5Ms%7Ze>auxChZ5O+%?7%gH!ufkZ2JE1O3xYCp-1)VzO4yNZ$QuX&yud=(M-24vM_Cbh>782 zv8@#C{-@pU(%al_{x%cck!@nT((xXCHyHXJh4ZgTzqc~ml@@B-n1$NTCo|0@4)xw= zP(KUZ_F@vI2VMsfNN7vVl(_xA4hS zBS=%gLTw#}_Tadkw@^EHGu6x|Q9F4P)xsw+ZC9l>&CH&6Q>nUMo9biUMs6ClQd{z@ zbW^;Q-AP%=rr)QKjhB*1p-pIaE1yj7XtJ`qerTqfd$CP3-O}nHYcm{VO&Lh4XcHeB z6Ej<|&qg=OtWc3=>%L$LHXe?d6gilwLR0!j)T#*EAUc@%j zh!w+b<(hX~^ctC)UiV^}vg|FFV)aF6ci2U4cpB}_Bo-EC$O`#P`QkHPvWUWK9_2En zM_w`~Q?){e-?80Sh4Tk&j{FEB#=DQ$aWoj8FgSN3TEr zpq@M7(P@v(hnTY?L3{jog68-IPIKaXf_CUAry1J9X@~xyi~qz5^Yq?-^?kwL$C@=q zr|H%G3w7!vpK(lofMff3j_nskJ-~AzIRfV>#{!_+CpzuPzZ#8afAD4XKpPS@J@4z- z!Gx&48`bb^^J1{W5p9TUt&CyL9*Yo{b)xo6cNj0$h z&Knqv`}^RXDEoN>d+3Bw+v|CS;Dvb?*{+osx-(Hb@CN91A>2>BJgi-Zbh=|tMm{_7 z+@WuIP>PY#Jqx=(5n}p~f$roDbXUO0?(a5ohrV#W7;rskGTWAmYf%!lYs{ifAnXbbo zP1oD*Y2E)Z@ww~2kGC&H-SU!!ZoXoMb1(eN5~lp`SpVvy2M*piX2H=2pRRo1hcD^PE-FW=~PK zWhK$gBO#qI-vY5PyMO1PYCCL@bJ$e1LHU@6T;_Z#v*mRw(ROFhM?wd8OzCYlc3Xm# zZrm^RRk)wRV+Xm^v6T4jwD?0lHig~w7UXd(dery6pf+7mXi zCL#2~NlqN9O%J9rjcc%Xs>Xls9vM%QJ# z=#MiqxrT=(zLJ3aMx57}Lxw+)_kG>YZhp%~)?XBIKUMu$D&1J=)-=IRBmBYq5XTX8 z8jI{J=%fDdQ`eulr8eivD>0&>cLm{$gKOS1Y%8nuy&e0H*PH(U28_)@cw z$E$)qF679fpWEmy?U_uuE`weFi2149+s)?c+uhoV$J3~_uep?Kdn0mY%$q?l$6XKk z?fT0uYQryI3GR=gyg$}O)sl9yrbo)FC;B+*1aq$}UAbn7izvP7R<8cUtyq03O;I{5 zeqiajozqtkX4IQRh3s# zm6g0GRd57Rp-6fDM&3zpnw6nknIq=oVxEt=zKd81@==78UIQKBdo-Qa@GjNbVW+D6 zvQxG88uU>>>L={0$gxX>y@8~YU0F4j#@1-uTzBUX*Mm1WK8)Y>=QRGG~~tu?!;%AbKRZEz{d zuHo2;h-XmKCvY5|O6j#9> z>OM(NJi<6k@hF$qfF2_tqaMYwu1s>p^vGwToo8|@9&)QzuLl3Vl0lZgI`J7Vx$NF7 zd0|JUxSs+&3iu3pA@5ZzZg_>u9~TqRPM@OW*-Ucj^w(g{PG~E3CcEgKADK!Ym>t}2 zOZV|R&UKEPJuXH`_j8D%=e+WQ6R@}AMZvvYKI|PAwtC6JFU+6)(~IxQP!`Yg5KGUc z6H6~=DoU!dnB|X2?cdDNuUeq+$>$&U%I1L%D6n@0@yhcLdX)uAXk*+OAhqddmp+=M zD5{ml4#yAuDT7$j=c7tE#0jKlzv$>w%zM@^&)e;do5OqK=JH-yo*=OIz2YYpEXz?Y zaK20~nC4>_J?kYG8GS^-2U)Vhv(nhXei-+}Am~qv0$D^+mETx=UEX{nJ!Z1+-jhw_ zy#ssYi@vyAUKG?v)X68CH{z4cAMwiO2O|4P8ar{^3eWfz3x9#@*p1$GqkBHZ2hYwR za_42sKRn}$`!E0kx}aRIlh9Xj^8z@2*^2x>y`m|3_(pBt%DtSpqWfpc=Q==_4?&kL z+49^0I6s?B%sG=SpVRA? ZC$b0u?)qInCTHf8a()R!7XK^D55N%8j$X9`rKr`2U zFefsZ1|Q(Kq33kE6IKH^_&Yr}v_=>I>26*8&|re*#MuPx$%N@8^aTX0M!=5{Lz1MQPf!D%6vB}tOet(ny!sf}J9q(X*#~&e?@gv7Ft2Yu zp5Cl|h&$+XhrVah_Wh4u(|0m~IUEr1dc^F5*pq}maezSy60##~4=30&(I(NJ1kJHg zofhoi2EBT~HNHwatj2?n8#Fy@_3WW5B4%|E@FKvh1l|F;hamqT*dyAMfOs0+8_==+ zS9R>b8Nm6D=+#G$!S{23Wetb0z6tnRg8Jw`b@9iG^!k3tJw#mnX8U=v=Ny1>nl!zI zz;RqdoJ+*sBJsBaf<1Z`>;f?`hY?r$M6c~%qSp?1jOwF=!7%i^S$}kzfg7OU`YQ&_ zkt(p|LiF+KABMTr3AmW?tD4`)&6u>kOM$PsBH?zC*j*4$1WfGExkOFhO0%{{#&JC4 zL(%*hxdr|X6E~1#0Imoyy{p1_Nxp~JC)*d$sgE9qv2ahjDeP&o-Va~5azhU#X%4)f z$aI|(a6hIC`Wi7v0f!7EvIqN(@jX8?lQ)Yq^RYVJ;P(ug{=e$kp0nbdlCWIS{|tbU zCbGvK32SlVGmPme>h_nWO_EzAt2@7C*6e%R#CD%HP@Ms=BVeSv$4u&jhZ5rtx+ijN zH-4LV7cpsL`~YCReMj|d@2H3c_l_j02f88NId8WAG0s@jyORJr>`#vGoW%k58SVXu zJEW+)U$SVr{@bkG{}*%of&WZ__%!)^LmxtHQNR}`$u}{^?SIUq>+u6F`fF3dVVBi9 z1o?e5|BI$oOiT*f_Nay3U5i+064Uxmi)PQCfy;Uz`qScifE?qE-htS2lD5-gQty8? zNqgWYh!-N3Jz1M#TQ{$>)DHH&m2La2ncj6(#CvxFU)Xv+S-m@t1B_F8?pBUAZr@X8 zO=p#n-utPM-g60#7lB_L1pk|Zxc05IB|SSC{%q6io}SFKoEC9n3I9aSbLVJ^dUvr^ z+w%BC{9I~t;t}707_CL!)ncUDVSeo96X|xuk%M^ho-y#z3M<$7+(cYyVq4O8#L3KD z4`q(;E#QE+magN`Xso>pc-kVsmw^KgV$1>;jMyo1!p+w#%&w19G_7eS!Jo$Ca>Jr>5F5r+m|S`Yyj9|0S-Su`C#Hgg@{kM4)SfrH*A7)O)# zz^{Ps=mwtSYLe#AFU04?H`_E#EaIAoxmqL{hrJ^Hx_t~V>N6=!%NCn<*RSllR+XFE zHN|b(@j!}U>!YdaW&_NhcK}0ghxv06aM*yre+!uGEbv2EY5 z(c5ML26=59&K|^&1$zYSA8imNS+wN};I`+W2H-Ss6z7xamTNFhfgn#2#JWWuUz$&d zEek?NVDUkI0LCR?qW26ZF?%j0v3o9pO_xpd-Vx+3f*eMK5AHc<(ROBGymK(yzXKTR zM!=i_?~TOh8-l#S1pXj|iz7B34IfAUL!T3UFFcF3M>F)F0OuYSxeCN@L4dEAXpfcJJZdEy zK8JdZgEo3=ot@oTWM_8e+n61zt@O5CDb&_MsIj;b_Cc^=(zzs#(L{T|4=-EQ?Zq~2 zt1Ow_U5>HuI^PS#sS#>rww<=Bcm9_xh{=jkk&m@# zcf6Rww(NkpB-Hjqay%Al=U586^UqGr=47bJISgFSsKoVPy$jef0-R5aovu;cC_fP2 zHU6)etiIPyZ+i=BjXn|M!uYv_b_M5B0DNu`crV2VK(*bwC3Ss%E#7s?Bw)Yl$zrf56yaXB*Q~=`F2LlLT`|jpJ^ldn&ti zsmK9K<28OxS()Zt<469+-|$^7a^rLtQ}e!q{|4+;U@$!*{_y?{Kmk zJPuVA)SFd~ikuDdHdO)O051R+SOj*wFk8&=!#|8T!|@Pv!02}3ZyoWQ=v1nq4*YFI z^toV6$NDvaD-5quc6NJxMDvrKLS9ySx0~GXhC^9#!l7IbJQVUzksK6qh?T=mYU6e% zRn78zbp0lK0ba+kbux9ycCzj;#PU%wj(-em5ejnX63>W7(I()DKgwWNKH^Z7KZqP7 z&I4gC2>xCAO{b>pVK-eK?JPydpyc*mGeAMgP0?5anZ(ukF^pT?o3rz zkr4MjfZD>7smkhr$Yn}=CUTl#UQ<|~f;9!Hs=8}VbzN2lU6$oith(k>d^C!6jBtJ# zc~|&82FE}opD6H(67MP;!4^eOf;_Cq=aqx4<-;yj#nCi+L#dmo$jQ`fobI+%P4St^ z9`y_m3*24c}U2=dzCb69%|V={T1!101O__>>^^+@p{lUYi8h~lFX#|<1MkG6>R1Z`53 zjAp1-HT&q&r=<9SoT*1y`VrLZLLGoOK4Du#{{#C(-wXL)={2b7Jq|IWDV?gwON024 zPOkfPI?K(`mZ@Ccm_e_UNxBD*z=5xQ5^5caV2p;v`hrN`8&~@ffLiAP4_W?>n=Dtm4W;*C z&W7tP59>C@e~eWgZRPXn^txBUzO4}ZMua+zkncfF1jYrb;&rT7iqyr!6u*#36n`S} zv&hkc1UY}GL%y1&D)|%S2v84x-6z&9!#Py)0r3AtLK4?P$>K`!5`SXiAYFC3M4YLTl(dq9YyvtH$rx3bjp;J-Mo|Kvbz zQl_dTGfTNVKSQx>U50Y`azT@W)W_)g^gGs%)fh#A!o_dfR!B^Nx3l1`{Kc{N+LRM`JU)9q%j;hK=GEO^65 zEI2v71_5g}#2ON?>8h6~DDbO_Z^^H*9>%XIe$_)1olKV%1+bPwig_8t(kq$Dk|jPx z>9a8~jyJ1swCDWO|9V%ps^B%hZ2noS^T-N`RDXiU1y_B8X=4V|reI7B|Nhp`a2#@!1v&748ArYFe;Q&P zM!0T8v}sbNPTW84$N3@j_4N7QnW0?rL%*uvr(kPGmb@Ss z8^l@`tVIe*DDEx3=9Mqqo}pblu1@RLEfDt=Ig0t5Pd<0OUpDuW59(Y{q8hcF%=MAZI>^*>&y0TM;B z2Ye3erG%O((f`mMsO171=b!h>3p)JD!r#2CSq$~LUv8a<)boqZUo+?4K2w$Z64>#2 zjy(4xs2e(%4Yq(iqkf^5=>zaFl!-M>a|7_dNl;%k_n+WzdtlxynxS0q@=V3NC;rvB z`b9cNyD#KiFjsTp7CfCp&P|-5nDgcg<%cCNEAqDHDCQo@QO-RM*9K=0dHY``@-}A^ lxrNz^yr0h`^VNRUoX2g?F1iPOGg{mKzV`1P_`m3Z{{_Mg&BOoz diff --git a/docs/introduction.mdx b/docs/introduction.mdx deleted file mode 100644 index ed08e4f3e..000000000 --- a/docs/introduction.mdx +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: Welcome to @sei-js -description: A TypeScript SDK for building decentralized applications on Sei -icon: "rocket" ---- - -## Build on Sei - -@sei-js is the complete TypeScript SDK for building applications on Sei Network. Whether you're creating DeFi protocols, NFT marketplaces, or blockchain games, @sei-js provides everything you need to ship faster. - -**Works with your favorite tools:** Sei is fully EVM-compatible, so you can use Viem, Ethers.js, Foundry, Hardhat, and all your existing Ethereum development tools without any changes. @sei-js extends these tools with Sei-specific features like precompiled contracts and optimized wallet connections. - - - - Build your first Sei app in under 10 minutes - - - Help improve @sei-js and contribute to the project - - - -## Why @sei-js? - - - - Full type safety for every function, contract interaction, and API response. Catch errors at compile time. - - - Battle-tested components used by major applications in the Sei ecosystem. - - - Take advantage of Sei's fast finality, low gas fees, and native order matching. - - - -## Package ecosystem - - - - **Native blockchain function access** - - Access Sei's precompiled contracts directly from your EVM applications. - - ```bash - yarn add @sei-js/precompiles - ``` - - - - **Project scaffolding and templates** - - Bootstrap new Sei projects with pre-configured templates and tooling. - - ```bash - npx @sei-js/create-sei app - ``` - - - - **Universal wallet connections** - - Connect to any Sei-compatible wallet using the EIP-6963 standard. - - ```bash - yarn add @sei-js/sei-global-wallet - ``` - - - - **Hardware wallet integration** - - Secure transaction signing with Ledger hardware wallets. - - ```bash - yarn add @sei-js/ledger - ``` - - - - **LLM blockchain integration** - - Teach Claude, ChatGPT, or any LLM to interact with the Sei blockchain. - - ```bash - npm install -g @sei-js/mcp-server - ``` - - - - -🤖 **Teach Your LLM About Sei** - -Connect Claude, ChatGPT, or any LLM to the Sei blockchain with **@sei-js/mcp-server**. Your AI assistant can check balances, transfer tokens, deploy contracts, and guide users through the entire @sei-js ecosystem. - -[Get Started with MCP →](/mcp-server/introduction) - - -## Community & Support - -- [GitHub Discussions](https://github.com/sei-protocol/sei-js/discussions) - Ask questions and discuss features -- [Discord](https://discord.gg/sei) - Join the Sei developer community -- [Official Documentation](https://docs.sei.io) - Complete Sei protocol documentation - -## Report Issues - -- [GitHub Issues](https://github.com/sei-protocol/sei-js/issues) - Report bugs and request features -- Include reproduction steps and environment details -- Check existing issues before creating new ones diff --git a/docs/ledger/introduction.mdx b/docs/ledger/introduction.mdx deleted file mode 100644 index 7e4f770e2..000000000 --- a/docs/ledger/introduction.mdx +++ /dev/null @@ -1,200 +0,0 @@ ---- -title: '@sei-js/ledger' -description: 'TypeScript library for SEI Ledger app helper functions' -icon: "shield" ---- - -## Overview - -The `@sei-js/ledger` package provides TypeScript helper functions for integrating with the SEI Ledger hardware wallet app. It enables secure transaction signing and address derivation for Sei blockchain applications using Ledger devices. - -## Installation - - -```bash yarn -yarn add @sei-js/ledger -``` - -```bash npm -npm install @sei-js/ledger -``` - -```bash pnpm -pnpm add @sei-js/ledger -``` - - -## Core Functions - -### createTransportAndApp - -Creates a transport connection and app instance for communicating with the Ledger device. - -**Parameters:** -- None - -**Returns:** -- `Promise<{transport: Transport, app: SeiApp}>` - Object containing transport and app instances - - -```typescript Basic Usage -import { createTransportAndApp } from '@sei-js/ledger'; - -const { transport, app } = await createTransportAndApp(); -console.log(transport, app); -``` - - -### getAddresses - -Retrieves both EVM and Cosmos addresses from the Ledger device for a given derivation path. - -**Parameters:** -- `app` (SeiApp) - An instance of the Ledger Sei app -- `path` (string) - HD derivation path (e.g., "m/44'/60'/0'/0/0") - -**Returns:** -- `Promise<{evmAddress: string, nativeAddress: string}>` - Object containing both address types - - -```typescript Get Addresses -import { getAddresses } from '@sei-js/ledger'; - -const { evmAddress, nativeAddress } = await getAddresses(app, "m/44'/60'/0'/0/0"); -console.log(evmAddress, nativeAddress); -``` - - -### SeiLedgerOfflineAminoSigner - -A signer class that enables offline amino signing with Ledger devices, compatible with CosmJS. - -#### Constructor - -```typescript -new SeiLedgerOfflineAminoSigner(app: SeiApp, path: string) -``` - -**Parameters:** -- `app` (SeiApp) - An instance of the Ledger Sei app -- `path` (string) - HD derivation path (e.g., "m/44'/60'/0'/0/0") - - -```typescript Create Signer -import { SeiLedgerOfflineAminoSigner } from '@sei-js/ledger'; - -const ledgerSigner = new SeiLedgerOfflineAminoSigner(app, "m/44'/60'/0'/0/0"); -``` - - -#### getAccounts - -Retrieves account information from the Ledger device. - -**Returns:** -- `Promise` - Array of AccountData objects with address and public key - - -```typescript Get Accounts -const accounts = await ledgerSigner.getAccounts(); -console.log(accounts); -// { address: 'sei1...', pubkey: { type: 'tendermint/PubKeySecp256k1', value: '...' } } -``` - - -#### signAmino - -Signs a transaction document using the Ledger device. - -**Parameters:** -- `_signerAddress` (string) - The address of the signer (unused) -- `signDoc` (StdSignDoc) - The sign document to be signed - -**Returns:** -- `Promise` - Object containing the signed document and signature - - -```typescript Sign Transaction -import { StdSignDoc } from '@cosmjs/amino'; - -const signDoc: StdSignDoc = { /* your StdSignDoc object */ }; -const signResponse = await ledgerSigner.signAmino('sei123...', signDoc); -console.log(signResponse.signed, signResponse.signature); -``` - - -## Complete Example - -Here's a complete example showing how to use the ledger package to delegate tokens: - - -```typescript Complete Delegation Example -import { coins, SigningStargateClient, StdFee } from "@cosmjs/stargate"; -import { createTransportAndApp, getAddresses, SeiLedgerOfflineAminoSigner } from "@sei-js/ledger"; - -const testApp = async () => { - const validatorAddress = "seivaloper1sq7x0r2mf3gvwr2l9amtlye0yd3c6dqa4th95v"; - const rpcUrl = "https://rpc-testnet.sei-apis.com/"; - const memo = "Delegation"; - const path = "m/44'/60'/0'/0/0"; - - // Create connection to Ledger device - const { app } = await createTransportAndApp(); - - // Get addresses from Ledger - const { nativeAddress } = await getAddresses(app, path); - - // Create signer instance - const ledgerSigner = new SeiLedgerOfflineAminoSigner(app, path); - - // Connect to Sei network - const signingStargateClient = await SigningStargateClient.connectWithSigner( - rpcUrl, - ledgerSigner - ); - - // Create delegation message - const msgDelegate = { - typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", - value: { - delegatorAddress: nativeAddress.address, - validatorAddress: validatorAddress, - amount: coins(500, "usei"), - }, - }; - - // Set transaction fee - const fee: StdFee = { - amount: [{ denom: "usei", amount: "20000" }], - gas: "200000", - }; - - // Sign and broadcast transaction - const result = await signingStargateClient.signAndBroadcast( - nativeAddress.address, - [msgDelegate], - fee, - memo - ); - - console.log("Broadcast result:", result); -}; - -testApp(); -``` - - -## Security Notes - - -- Ensure your Ledger device is genuine and purchased from official sources -- Always verify transaction details on your Ledger device screen before confirming -- Keep your Ledger device firmware updated -- Store your recovery phrase securely and never share it - - -## Hardware Requirements - -- Ledger Nano S Plus, Nano X, or compatible device -- SEI app installed on the Ledger device -- USB or Bluetooth connection to your computer diff --git a/docs/llms-full.txt b/docs/llms-full.txt deleted file mode 100644 index 3b1e5fab6..000000000 --- a/docs/llms-full.txt +++ /dev/null @@ -1,193 +0,0 @@ -# SeiJS Documentation - -Official JavaScript SDK for building decentralized applications on Sei Network. Includes tools for EVM integration, boilerplate applications, wallet connections, and precompile contract interfaces. - -## Overview - -SeiJS is a comprehensive JavaScript SDK for interacting with the Sei blockchain. It provides tools for both Cosmos SDK and EVM integration, allowing developers to build decentralized applications on Sei Network. - -## Getting Started - -### Installation - -```bash -npm install @sei-js/precompiles @sei-js/cosmos -``` - -For specific functionality, install the relevant packages: - -## Key Packages - -### @sei-js/core -Core functionality for Sei blockchain interactions. Provides the foundation for connecting to Sei networks and performing basic operations. - -### @sei-js/precompiles -Native blockchain function integrations through precompile contracts. These contracts provide direct access to Sei's unique blockchain features from EVM smart contracts. - -### @sei-js/cosmos -Cosmos SDK integration tools. Provides access to Sei's Cosmos SDK features, including staking, governance, and IBC transfers. - -### @sei-js/create-sei -Boilerplate applications and templates. Quickly scaffold new Sei applications with pre-configured setups. - -### @sei-js/ledger -Ledger hardware wallet integration. Securely connect to Ledger devices for signing transactions on Sei. - -### @sei-js/sei-global-wallet -Wallet connection tools. Simplifies connecting to various wallet providers for Sei applications. - -## Precompile Contracts - -Sei offers unique precompile contracts for blockchain interactions: - -### Address (0x1004) -Address association between EVM and Cosmos addresses. Allows mapping between the two address formats. - -### Bank (0x1001) -Token operations including transfers, balances, and supply queries. Access Sei's native token functionality from EVM. - -### Distribution (0x1007) -Reward distribution for staking and governance. Access staking rewards and community pool funds. - -### Governance (0x1006) -Voting and deposits for governance proposals. Participate in Sei governance from EVM contracts. - -### IBC (0x1009) -Cross-chain transfers using the Inter-Blockchain Communication protocol. Send tokens to other Cosmos chains. - -### JSON (0x1003) -JSON parsing utilities for smart contracts. Simplifies handling JSON data in EVM contracts. - -### Oracle (0x1008) -Price feeds and TWAPs for DeFi applications. Access reliable price data for various assets. - -### Pointer (0x100B) -Token pointer creation for cross-chain assets. Create and manage pointers to tokens on other chains. - -### Pointerview (0x100A) -Token pointer queries for viewing pointer information. Query details about token pointers. - -### Staking (0x1005) -Validator operations including delegation and unbonding. Participate in Sei's proof-of-stake system. - -### WASM (0x1002) -Smart contract interaction with CosmWasm contracts. Call CosmWasm contracts from EVM contracts. - -## Ethers.js Integration - -SeiJS provides full integration with Ethers.js for EVM interactions: - -```javascript -import { ethers } from 'ethers'; -import { getBankPrecompile } from '@sei-js/precompiles/ethers'; - -// Connect to Sei EVM -const provider = new ethers.JsonRpcProvider('https://evm-rpc.sei-apis.com'); -const signer = new ethers.Wallet(privateKey, provider); - -// Get Bank precompile contract -const bankContract = getBankPrecompile(signer); - -// Transfer tokens -await bankContract.send('sei1...', 'usei', '1000000'); -``` - -## Viem Integration - -SeiJS also supports Viem for modern EVM interactions: - -```javascript -import { createWalletClient, http } from 'viem'; -import { privateKeyToAccount } from 'viem/accounts'; -import { sei } from '@sei-js/precompiles/viem'; -import { bankAbi } from '@sei-js/precompiles/viem'; - -// Connect to Sei EVM -const account = privateKeyToAccount('0x...'); -const client = createWalletClient({ - account, - chain: sei, - transport: http() -}); - -// Call Bank precompile -const result = await client.writeContract({ - address: '0x0000000000000000000000000000000000001001', - abi: bankAbi, - functionName: 'send', - args: ['sei1...', 'usei', 1000000n] -}); -``` - -## Wallet Integration - -Connect to various wallets using the Sei Global Wallet: - -```javascript -import { SeiGlobalWallet } from '@sei-js/sei-global-wallet'; - -// Initialize wallet -const wallet = new SeiGlobalWallet(); - -// Connect to wallet -await wallet.connect(); - -// Get accounts -const accounts = await wallet.getAccounts(); - -// Sign transaction -const signedTx = await wallet.signTransaction(tx); -``` - -## Create-Sei Templates - -Quickly scaffold new applications: - -```bash -npx @sei-js/create-sei app -``` - -Choose from various templates: -- React + Viem -- Next.js + Ethers -- Vue + Viem -- Vanilla JS - -## Advanced Features - -### Confidential Transfers - -```javascript -import { getConfidentialTransfersPrecompile } from '@sei-js/precompiles/ethers'; - -const ctContract = getConfidentialTransfersPrecompile(signer); - -// Initialize account -await ctContract.initializeAccount(); - -// Make private transfer -await ctContract.transfer('recipient_public_key', 'usei', '1000000'); -``` - -### CosmWasm Integration - -```javascript -import { getWasmPrecompile } from '@sei-js/precompiles/ethers'; - -const wasmContract = getWasmPrecompile(signer); - -// Query CosmWasm contract -const result = await wasmContract.query('sei1...', '{"get_count":{}}'); - -// Execute CosmWasm contract -await wasmContract.execute('sei1...', '{"increment":{}}', []); -``` - -## Security Best Practices - -- Always use the latest version of SeiJS packages -- Validate all user inputs before sending to the blockchain -- Use hardware wallets for high-value operations -- Test thoroughly on testnet before deploying to mainnet -- Follow proper key management practices -- Implement proper error handling for all blockchain operations diff --git a/docs/llms.txt b/docs/llms.txt deleted file mode 100644 index a7ea6f19f..000000000 --- a/docs/llms.txt +++ /dev/null @@ -1,33 +0,0 @@ -# SeiJS Documentation - -Official JavaScript SDK for building decentralized applications on Sei Network. Includes tools for EVM integration, boilerplate applications, wallet connections, and precompile contract interfaces. - -## Overview - -SeiJS is a comprehensive JavaScript SDK for interacting with the Sei blockchain. It provides tools for both Cosmos SDK and EVM integration, allowing developers to build decentralized applications on Sei Network. - -## Key Packages - -- @sei-js/core - Core functionality for Sei blockchain interactions -- @sei-js/precompiles - Native blockchain function integrations through precompile contracts -- @sei-js/cosmos - Cosmos SDK integration tools -- @sei-js/create-sei - Boilerplate applications and templates -- @sei-js/ledger - Ledger hardware wallet integration -- @sei-js/registry - Asset registry for tokens and networks -- @sei-js/sei-global-wallet - Wallet connection tools - -## Precompile Contracts - -Sei offers unique precompile contracts for blockchain interactions: -- Address (0x1004) - Address association -- Bank (0x1001) - Token operations -- Confidential Transfers (0x1010) - Privacy features -- Distribution (0x1007) - Reward distribution -- Governance (0x1006) - Voting and deposits -- IBC (0x1009) - Cross-chain transfers -- JSON (0x1003) - JSON parsing utilities -- Oracle (0x1002) - Price feeds and TWAPs -- Pointer (0x100B) - Token pointer creation -- Pointerview (0x100A) - Token pointer queries -- Staking (0x1005) - Validator operations -- WASM (0x1002) - Smart contract interaction diff --git a/docs/mcp-server/context.mdx b/docs/mcp-server/context.mdx deleted file mode 100644 index 8abf1a293..000000000 --- a/docs/mcp-server/context.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Documentation Context" -description: "How the MCP server provides intelligent assistance through comprehensive documentation search" -icon: "book-open" ---- - -The Sei MCP Server includes intelligent documentation search that provides access to both the main Sei documentation and the entire @sei-js ecosystem documentation for context-aware responses and code generation. - -## Documentation Access - -The MCP server provides two search tools: - -### Main Sei Documentation (`search_docs`) -Search the official Sei documentation for: -- General chain information and network details -- Ecosystem providers and integrations -- User onboarding guides and tutorials -- Bridging and cross-chain operations -- DeFi protocols and marketplace information - -### Sei-JS Package Documentation (`search_sei_js_docs`) -Search and reference documentation for all @sei-js packages: - -- **@sei-js/precompiles** - Precompile contract reference and integration examples -- **@sei-js/sei-global-wallet** - EIP-6963 wallet standard implementation -- **@sei-js/mcp-server** - Model Context Protocol server for LLMs -- **@sei-js/registry** - Network configuration and asset information -- **@sei-js/create-sei** - Project scaffolding and templates -- **@sei-js/ledger** - Hardware wallet integration diff --git a/docs/mcp-server/environment-variables.mdx b/docs/mcp-server/environment-variables.mdx deleted file mode 100644 index fe316a1f1..000000000 --- a/docs/mcp-server/environment-variables.mdx +++ /dev/null @@ -1,291 +0,0 @@ ---- -title: "Environment Variables" -description: "Configure Sei MCP Server with environment variables for wallet access and custom RPC endpoints" -icon: "gear" ---- - -The Sei MCP Server supports configuration through environment variables, which can be set in your MCP configuration JSON or passed directly to the Node.js command. - -## Configuration Methods - - - - Add environment variables to your MCP server configuration: - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"], - "env": { - "WALLET_MODE": "private-key", - "PRIVATE_KEY": "0x123...", - "MAINNET_RPC_URL": "https://your-custom-rpc.com" - } - } - } - } - ``` - - - - Pass environment variables directly to the Node.js command: - - ```bash - # Streamable HTTP with custom path (recommended) - SERVER_TRANSPORT=streamable-http SERVER_PORT=8080 SERVER_PATH=/api/mcp npx @sei-js/mcp-server - - # Or export them first - export SERVER_TRANSPORT=streamable-http - export SERVER_PORT=8080 - export SERVER_PATH=/mcp - npx @sei-js/mcp-server - ``` - - For Claude CLI: - ```bash - # Add server to Claude CLI - claude mcp add sei-http npx @sei-js/mcp-server --env SERVER_TRANSPORT=streamable-http SERVER_PORT=8080 - - # Start Claude - claude - ``` - - - -## Available Variables - -### Wallet Configuration - -#### `WALLET_MODE` -- **Type**: `string` -- **Default**: `"disabled"` -- **Description**: Controls wallet functionality and transaction capabilities -- **Options**: - - `"disabled"` - Read-only mode, no transaction capabilities - - `"private-key"` - Enable wallet tools using private key - -#### `PRIVATE_KEY` -- **Type**: `string` -- **Default**: `-` -- **Description**: Private key for wallet operations (required when WALLET_MODE="private-key") -- **Format**: 0x-prefixed hex string (64 characters after 0x) - - -**Security Critical**: Never commit private keys to version control. Use a dedicated test wallet with minimal funds. - - -### Network Configuration - -#### `MAINNET_RPC_URL` -- **Type**: `string` -- **Default**: `"https://evm-rpc.sei-apis.com"` -- **Description**: Custom RPC endpoint for Sei mainnet -- **Use Case**: Private RPC providers, local nodes, or custom endpoints - -#### `TESTNET_RPC_URL` -- **Type**: `string` -- **Default**: `"https://evm-rpc-testnet.sei-apis.com"` -- **Description**: Custom RPC endpoint for Sei testnet (Atlantic-2) -- **Use Case**: Testing with custom infrastructure - -#### `DEVNET_RPC_URL` -- **Type**: `string` -- **Default**: `"https://evm-rpc-arctic-1.sei-apis.com"` -- **Description**: Custom RPC endpoint for Sei devnet -- **Use Case**: Development and experimental features - -### Server Configuration - -#### `SERVER_TRANSPORT` -- **Type**: `string` -- **Default**: `"stdio"` -- **Description**: Transport mode for the MCP server -- **Options**: - - `"stdio"` - Standard input/output (default for AI assistants) - - `"streamable-http"` - Streamable HTTP transport (recommended for web apps) - - `"http-sse"` - HTTP Server-Sent Events (deprecated) - -#### `SERVER_PORT` -- **Type**: `number` -- **Default**: `8080` -- **Description**: Port number for HTTP transports (http-sse, streamable-http) -- **Range**: 1-65535 - -#### `SERVER_HOST` -- **Type**: `string` -- **Default**: `"localhost"` -- **Description**: Host address for HTTP server -- **Use Case**: Bind to specific network interfaces - -#### `SERVER_PATH` -- **Type**: `string` -- **Default**: `"/mcp"` -- **Description**: Base path for HTTP endpoints -- **Format**: Must start with `/` (automatically normalized) - -### System Configuration - -#### `PATH` -- **Type**: `string` -- **Default**: System PATH -- **Description**: Override PATH to specify Node.js version -- **Use Case**: Troubleshooting Node.js version conflicts - -## Configuration Examples - - - - No environment variables needed for AI assistant integration: - - - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"] - } - } - } - ``` - - - ```bash - # Default STDIO mode (no environment variables needed) - npx @sei-js/mcp-server - - # Or with Claude CLI - claude mcp add sei npx @sei-js/mcp-server - ``` - - - - **Transport**: Standard input/output for Claude Desktop, Cursor, Windsurf - - - - Use streamable HTTP when you need API access over HTTP: - - - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"], - "env": { - "SERVER_TRANSPORT": "streamable-http", - "SERVER_PORT": "8080", - "SERVER_PATH": "/api/mcp", - "SERVER_HOST": "0.0.0.0" - } - } - } - } - ``` - - - ```bash - # Streamable HTTP with custom configuration - SERVER_TRANSPORT=streamable-http \ - SERVER_PORT=8080 \ - SERVER_PATH=/api/mcp \ - SERVER_HOST=0.0.0.0 \ - npx @sei-js/mcp-server - - # Or with Claude CLI - claude mcp add sei-http npx @sei-js/mcp-server \ - --env SERVER_TRANSPORT=streamable-http \ - --env SERVER_PORT=8080 \ - --env SERVER_PATH=/api/mcp - ``` - - - - **Use Case**: Web applications, custom integrations, API access - - - - HTTP Server-Sent Events transport - use streamable-http instead: - - - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"], - "env": { - "SERVER_TRANSPORT": "http-sse", - "SERVER_PORT": "3001", - "SERVER_PATH": "/mcp" - } - } - } - } - ``` - - - ```bash - # HTTP SSE (deprecated - use streamable-http instead) - SERVER_TRANSPORT=http-sse \ - SERVER_PORT=3001 \ - SERVER_PATH=/mcp \ - npx @sei-js/mcp-server - - # Or with Claude CLI - claude mcp add sei-sse npx @sei-js/mcp-server \ - --env SERVER_TRANSPORT=http-sse \ - --env SERVER_PORT=3001 - ``` - - - - **Status**: Deprecated - migrate to streamable-http for better performance - - - -## Security Best Practices - - - - Use a dedicated wallet for testing, not your main holdings - - - Keep only small amounts needed for testing transactions - - - Never commit private keys to version control or share them - - - Rotate test wallet keys periodically for security - - - -## Troubleshooting - -### Common Issues - -**Private Key Format** -- Must start with `0x` -- Must be exactly 66 characters (0x + 64 hex characters) -- Use lowercase hex characters - -**RPC Connection** -- Verify custom RPC URLs are accessible -- Check for rate limiting on custom endpoints -- Ensure RPC supports required methods - -**Environment Variables Not Loading** -- Restart your AI assistant after configuration changes -- Verify JSON syntax in MCP configuration -- Check for typos in variable names - - - Check our comprehensive troubleshooting guide for solutions to specific problems. - diff --git a/docs/mcp-server/introduction.mdx b/docs/mcp-server/introduction.mdx deleted file mode 100644 index 90ddb6724..000000000 --- a/docs/mcp-server/introduction.mdx +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: "Sei MCP Server" -description: "Enable LLM based tools to interact with and better understand Sei through natural language queries, using the Model Context Protocol" -icon: "robot" ---- - - - - Teach your LLMs how to do token transfers, smart contract interactions, read documentation, generate boilerplate code, and more. - - - Developers, Vibe Coders, DeFi users, NFT collectors, and anyone wanting to interact with Sei through natural language interfaces. - - - -## Quick Start - - - - **Read-only mode** - Perfect for blockchain queries, documentation lookup, and analysis without transaction capabilities. - - - **Safe by Default**: Wallet tools are disabled until you explicitly configure a private key. - - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"] - } - } - } - ``` - - **What you can do:** - - Query balances and transaction history - - Search Sei documentation - - Analyze blockchain data - - Generate boilerplate code - - Get network status and block info - - - - **Transaction capabilities** - Adds wallet tools for sending tokens, deploying contracts, and blockchain interactions. - - - **Security Critical**: Only use test wallets with minimal funds. Never commit private keys to version control. - - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"], - "env": { - "WALLET_MODE": "private-key", - "PRIVATE_KEY": "YOUR_PRIVATE_KEY" - } - } - } - } - ``` - - **Additional capabilities:** - - Send tokens and execute transactions - - Deploy and interact with smart contracts - - Manage NFT collections - - Stake and delegate tokens - - All read-only features included - - - - **Advanced setup** - Complete environment variable configuration for custom RPC endpoints, transport modes, and server settings. - - See the [Environment Variables](/mcp-server/environment-variables) documentation for all available options and detailed explanations. - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"], - "env": { - "WALLET_MODE": "private-key", - "PRIVATE_KEY": "YOUR_PRIVATE_KEY", - "SERVER_TRANSPORT": "streamable-http", - "SERVER_PORT": "8080", - "SERVER_PATH": "/mcp", - "MAINNET_RPC_URL": "https://evm-rpc.sei-apis.com", - "TESTNET_RPC_URL": "https://evm-rpc-testnet.sei-apis.com", - "DEVNET_RPC_URL": "https://evm-rpc-arctic-1.sei-apis.com" - } - } - } - } - ``` - - - ---- - -## What is MCP? - -The Model Context Protocol is an open standard that connects AI systems with custom prompts, tools and data sources (context). It enables things like: - -- **Real-time blockchain data access** - Get current balances, transaction history, and network status directly from Sei -- **Full execution and write operations** - Deploy contracts, execute transactions, and interact with smart contracts (with wallet configured) -- **Up-to-date documentation access** - Search both main Sei docs and Sei-JS package documentation for comprehensive guidance -- **Specialized blockchain capabilities** - Access Sei-specific features like precompiles and native token operations -- **Create boilerplate code** - Generate code for Sei projects using the latest patterns - -The Sei MCP Server leverages this protocol to bring all of this and more directly to your LLM enabled tools, allowing for natural language interactions with Sei. - -## Why Use Sei MCP Server? - - - - Interact with Sei blockchain using conversational commands like "What's my SEI balance?" or "Send 1 SEI to this address" instead of complex API calls. - - - - Get intelligent insights about transactions, contracts, and market data with built-in analysis capabilities powered by your AI assistant. - - - - Works seamlessly with Cursor IDE, Windsurf, Claude Desktop, and custom applications through standardized MCP integration. - - - - Access 29 blockchain tools covering token management, NFT operations, smart contract interactions, network monitoring, and documentation search. - - - -## Example Queries - -```text -"Get me the transactions in the latest block and tell me what they did." -"How do I query staking my delegations using Viem?" -"Generate a boilerplate dApp with Sei Global Wallet connection" -"What's my SEI balance?" -"Send 1 SEI to this address" -``` - -## Next Steps - - - - Follow our step-by-step installation guide for Claude Desktop, Cursor, Windsurf, and custom integrations. - - - Solutions to common setup and configuration issues - - diff --git a/docs/mcp-server/prompts.mdx b/docs/mcp-server/prompts.mdx deleted file mode 100644 index bc4fc567b..000000000 --- a/docs/mcp-server/prompts.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Pre-configured Prompts" -description: "Pre-configured prompts for common blockchain operations" -icon: "comments" ---- - -The Sei MCP Server includes pre-configured AI prompts for common blockchain tasks. Use these for quick access to frequent operations. - -## Pre-configured Prompts - -| Prompt | Purpose | Usage | -|--------|---------|-------| -| `my_wallet_address` | Get your wallet address | "What's my wallet address?" | -| `explore_block` | Analyze block data | "Explore the latest block" | -| `analyze_transaction` | Transaction details | "Analyze transaction 0xabc..." | -| `analyze_address` | Address analysis | "Analyze address 0x742d..." | - -## Common Usage Examples - -### Balance Queries -```text -"What's my SEI balance?" -"What's my USDC balance?" -"Show me all my token balances" -``` - -### Transfer Operations -```text -"Send 1 SEI to 0x742d35Cc6634C0532925a3b8D4C1C4e3153DC" -"Send 100 USDC to 0x742d..." -"Transfer NFT token 123 to 0x742d..." -``` - -### DeFi Operations -```text -"Approve 1000 USDC for Uniswap" -"Get info for token 0x3894..." -"Is 0x3894... a contract?" -``` - -### Blockchain Analysis -```text -"Show me Sei network information" -"Get latest block details" -"Analyze transaction 0xabc123..." -``` - - -Ask your AI assistant using natural language - it understands conversational commands and will map them to the appropriate MCP tools. - diff --git a/docs/mcp-server/quickstart.mdx b/docs/mcp-server/quickstart.mdx deleted file mode 100644 index 0e845ef8b..000000000 --- a/docs/mcp-server/quickstart.mdx +++ /dev/null @@ -1,253 +0,0 @@ ---- -title: "Quickstart" -description: "Configure Sei MCP Server with Cursor, Windsurf, Claude Desktop, or CLI" -icon: "download" ---- - - - - - - - Navigate to Cursor → Settings → Cursor Settings → MCP - - ``` - Cursor → Settings → Cursor Settings → MCP - ``` - - - - Click "Add new Global MCP server" and add this configuration to mcp.json: - - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"] - } - } - } - ``` - - - - - Restart Cursor to activate the MCP server. You'll see a notification when it's ready. - - - - - - - - - - Navigate to Windsurf → Settings → Windsurf Settings → Cascade - - ``` - Windsurf → Settings → Windsurf Settings → Cascade - ``` - - - - Add the Sei MCP Server to your configuration: - - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"] - } - } - } - ``` - - - - - Save and restart Windsurf. The server loads automatically. - - - - - - - - - - Download [Claude Desktop](https://claude.ai/download) from Anthropic. - - - - Open Settings → Developer → Edit Config and add: - - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"] - } - } - } - ``` - - - - - Save and restart Claude Desktop to enable Sei tools. - - - - - **Remote MCP Servers**: Claude Desktop also supports connectors for remote HTTP servers. If you want to use a remote Sei MCP server instead of running it locally, set up the server using the **Remote Servers (http)** tab above, then add a connector configuration instead of the local server setup. - - - - - - - - - ```bash - npm install -g @anthropic-ai/claude-code - ``` - - - - ```bash - # Read-only mode (default) - claude mcp add sei-mcp-server npx @sei-js/mcp-server - - # Wallet-enabled mode - claude mcp add sei-mcp-server-wallet npx @sei-js/mcp-server --env WALLET_MODE=private-key PRIVATE_KEY=0x123... - ``` - - - - ```bash - claude - ``` - - The Sei MCP Server activates automatically in your session. - - - - - - - The Sei MCP Server can be run as a standalone HTTP server via the `streamable-http` transport. - - - - Launch the MCP server with streamable-http transport: - - ```bash - # Basic API setup (port: 8080, path: /mcp) - SERVER_TRANSPORT=streamable-http npx @sei-js/mcp-server - ``` - - Or with custom configuration: - - ```bash - # Custom port and path - SERVER_TRANSPORT=streamable-http \ - SERVER_PORT=3001 \ - SERVER_PATH=/api/sei \ - SERVER_HOST=0.0.0.0 \ - npx @sei-js/mcp-server - ``` - - - - The server will output: - - ``` - EVM MCP Server initialized for networks: sei, sei-devnet, sei-testnet - MCP Server ready (streamable-http transport on localhost:8080/mcp) - ``` - - - - Test the API endpoint with curl: - - ```bash - # List available tools - curl -X POST http://localhost:8080/mcp \ - -H "Content-Type: application/json" \ - -H "Accept: application/json, text/event-stream" \ - -d '{ - "jsonrpc": "2.0", - "id": 1, - "method": "tools/list" - }' - - # Get latest block info - curl -X POST http://localhost:8080/mcp \ - -H "Content-Type: application/json" \ - -H "Accept: application/json, text/event-stream" \ - -d '{ - "jsonrpc": "2.0", - "id": 2, - "method": "tools/call", - "params": { - "name": "get_latest_block", - "arguments": { - "network": "sei" - } - } - }' - ``` - - - - - - -## Verification - -After setup, verify the server is working by asking your AI assistant: - - - - **Ask:** "What Sei tools are available?" - - You should see a list of available blockchain tools. - - - - **Ask:** "What's the latest block on Sei?" - - This tests basic blockchain connectivity. - - - - If you configured wallet access (see environment variables for setup): - - **Ask:** "What's my wallet address?" - - This confirms wallet tools are enabled. - - - -## Next Steps - - - - Configure wallet access and custom RPC endpoints - - - Explore 50+ blockchain tools and capabilities - - - Solutions to common setup and configuration issues - - - Learn how to effectively interact with the server - - \ No newline at end of file diff --git a/docs/mcp-server/tools.mdx b/docs/mcp-server/tools.mdx deleted file mode 100644 index eed895699..000000000 --- a/docs/mcp-server/tools.mdx +++ /dev/null @@ -1,158 +0,0 @@ ---- -title: "Available Tools" -description: "Complete reference of all Sei MCP server tools" -icon: "wrench" ---- - -The Sei MCP Server provides various tools for blockchain operations, queries, documentation lookup, and more. **By default, wallet tools are disabled** and only read-only tools are available. [Enable wallet tools](/mcp-server/quickstart#wallet-connection) to unlock transaction capabilities. - - -**Wallet Tools Disabled by Default** - -For security, wallet-dependent tools require explicit configuration. Only read-only blockchain data tools are available by default. - - -## Read-Only Tools (Always Available) - -These tools work without wallet connection and are available by default: - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `get_balance` | Check SEI balance | "What's my SEI balance?" | -| `is_contract` | Check if address is contract | "Is 0x3894... a contract?" | -| `estimate_gas` | Estimate transaction gas cost | "How much gas for this transaction?" | - -## Wallet Tools (Require Configuration) 🔐 - - -These tools require [wallet configuration](/mcp-server/quickstart#wallet-connection) and are **disabled by default** for security. - - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `get_address_from_private_key` | Get wallet address | "What's my wallet address?" | -| `transfer_sei` | Send SEI tokens | "Send 1 SEI to 0x742d..." | - -## Network & Blockchain Data - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `get_chain_info` | Get network information | "Show me Sei network info" | -| `get_supported_networks` | List supported networks | "What networks are supported?" | -| `get_latest_block` | Get latest block | "Get latest block" | -| `get_block_by_number` | Get specific block | "Get block 12345" | -| `get_transaction` | Get transaction details | "Analyze transaction 0xabc..." | -| `get_transaction_receipt` | Get transaction receipt | "Get receipt for 0xabc..." | - -## Token Management - -### Read-Only Token Tools - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `get_token_info` | Get ERC-20 token details | "Get info for token 0x3894..." | -| `get_token_balance` | Check token balance | "What's my USDC balance?" | -| `get_erc20_balance` | Check ERC-20 balance | "Check ERC20 balance for 0x742d..." | -| `get_token_balance_erc20` | Get ERC-20 token balance | "Get token balance for address" | - -### Wallet-Required Token Tools 🔐 - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `transfer_token` | Send ERC-20 tokens | "Send 100 USDC to 0x742d..." | -| `transfer_erc20` | Transfer ERC-20 tokens | "Transfer tokens to address" | -| `approve_token_spending` | Approve token spending | "Approve 1000 USDC for 0xDEX..." | - -## NFT Operations (ERC-721) - -### Read-Only NFT Tools - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `get_nft_info` | Get NFT details | "Get info for NFT token 123" | -| `check_nft_ownership` | Verify NFT ownership | "Do I own NFT token 123?" | -| `get_nft_balance` | Count NFTs owned | "How many NFTs do I own?" | - -### Wallet-Required NFT Tools 🔐 - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `transfer_nft` | Transfer NFT | "Transfer NFT token 123 to 0x742d..." | - -## Multi-Token Operations (ERC-1155) - -### Read-Only ERC-1155 Tools - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `get_erc1155_balance` | Get ERC-1155 token balance | "Check my ERC1155 token balance" | -| `get_erc1155_token_uri` | Get ERC-1155 metadata URI | "Get metadata for token ID 123" | - -### Wallet-Required ERC-1155 Tools 🔐 - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `transfer_erc1155` | Transfer ERC-1155 tokens | "Transfer ERC1155 token to address" | - -## Smart Contract Operations - -### Read-Only Contract Tools - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `read_contract` | Read contract data | "Read balanceOf from contract 0x3894..." | - -### Wallet-Required Contract Tools 🔐 - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `write_contract` | Execute contract function | "Call contract function with params" | -| `deploy_contract` | Deploy new smart contract | "Deploy my token contract" | - -## Documentation - -| Tool | Purpose | Example Usage | -|------|---------|---------------| -| `search_docs` | Search the main Sei docs for general chain information, ecosystem providers, and user onboarding guides | "How do I bridge tokens to Sei?" | -| `search_sei_js_docs` | Search Sei-JS documentation | "How do I use precompiles with Viem?" | - -## Enabling Wallet Tools - -To use wallet-required tools (🔐), you must configure a wallet connection: - - - - Add your private key to the MCP server configuration: - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"], - "env": { - "WALLET_MODE": "private-key", - "PRIVATE_KEY": "0x123..." - } - } - } - } - ``` - - - - Restart your AI assistant (Claude Desktop, Cursor, etc.) to activate wallet tools. - - - -[See full setup guide →](/mcp-server/quickstart#wallet-connection) - -## Security Notes - - -**Wallet tools require a private key for transaction signing. Ensure this key is:** -- Kept secure and never shared -- Only used with funds you can afford to lose -- Properly backed up before use -- From a dedicated wallet, not your main holdings - diff --git a/docs/mcp-server/transports.mdx b/docs/mcp-server/transports.mdx deleted file mode 100644 index 3df67f4c2..000000000 --- a/docs/mcp-server/transports.mdx +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: "Transport Modes" -description: "Understanding MCP transport protocols and when to use each" -icon: "network-wired" ---- - -The Sei MCP Server supports three transport modes for different integration scenarios. In most cases, `stdio` is the best choice, but understanding these modes is important if you need a remote MCP server or if your AI tool doesn't support MCP. Each transport offers unique advantages depending on your use case and client requirements. - -## Transport Overview - - - - **Default Mode** - Direct process communication via standard input/output streams. - - - **HTTP API** - RESTful HTTP server with streaming capabilities for web integrations. - - - **Server-Sent Events** - HTTP with server-sent events (deprecated, use streamable-http instead). - - - - -## Choosing the Right Transport - - - - **Recommended for:** - - Claude Desktop, Cursor, Windsurf integrations - - Local development and testing - - Maximum performance requirements - - **Pros:** - - Fastest performance (no network overhead) - - Automatic lifecycle management - - Native MCP client support - - **Cons:** - - Limited to local process communication - - No remote access capabilities - - **Security:** - - Process isolation (server runs as child process) - - No network exposure (communication via local IPC) - - Client-managed lifecycle - - - - **Recommended for:** - - Remote server deployments - - Custom HTTP clients - - Tools that don't support MCP - - Web applications - - **Pros:** - - Network accessible - - Standard HTTP protocols - - Scalable and load-balanceable - - Works with any HTTP client - - **Cons:** - - Network latency overhead - - Requires manual server management - - Additional security considerations - - **Security:** - - Network exposure (server accessible over HTTP) - - Consider implementing API keys or tokens - - Configure CORS policies as needed - - Restrict access to trusted networks - - Use reverse proxy with HTTPS for production - - - - **Status:** Deprecated - migrate to `streamable-http` - - This transport is no longer recommended for new implementations. Existing users should migrate to `streamable-http` for better performance and standards compliance. - - - ---- - -## Configuration - - - - ```json Claude Desktop - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"] - } - } - } - ``` - - ```bash Environment Variables - # stdio is the default, no configuration needed - SERVER_TRANSPORT=stdio # Optional, this is default - npx @sei-js/mcp-server - ``` - - - - ```bash Basic Setup - SERVER_TRANSPORT=streamable-http npx @sei-js/mcp-server - ``` - - Defaults to `http://localhost:8080/mcp` - - ```bash Custom Configuration - SERVER_TRANSPORT=streamable-http \ - SERVER_PORT=3001 \ - SERVER_HOST=0.0.0.0 \ - SERVER_PATH=/api/sei \ - npx @sei-js/mcp-server - ``` - - Runs on `http://0.0.0.0:3001/api/sei` - - ```json MCP Client Config - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"], - "env": { - "SERVER_TRANSPORT": "streamable-http", - "SERVER_PORT": "8080" - } - } - } - } - ``` - - ```bash Test with curl - # Get available tools - curl -X POST http://localhost:8080/mcp \ - -H "Content-Type: application/json" \ - -H "Accept: application/json, text/event-stream" \ - -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' - - # Call a specific tool (example: get balance) - curl -X POST http://localhost:8080/mcp \ - -H "Content-Type: application/json" \ - -H "Accept: application/json, text/event-stream" \ - -d '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "get_balance", "arguments": {"address": "0x1234..."}}}' - ``` - - - - - **Deprecated**: Migrate to `streamable-http` instead. - - - ```bash - SERVER_TRANSPORT=http-sse npx @sei-js/mcp-server - ``` - - - ---- diff --git a/docs/mcp-server/troubleshooting.mdx b/docs/mcp-server/troubleshooting.mdx deleted file mode 100644 index 70640bd68..000000000 --- a/docs/mcp-server/troubleshooting.mdx +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: "Troubleshooting" -description: "Resolve common issues and get help with Sei MCP Server setup and configuration" -icon: "bug" ---- - -## Quick Diagnosis - -Most issues are caused by an incorrect Node.js version being used. Start here: - - - - Verify your Node.js version is 18 or higher: - - ```bash - node --version - ``` - - If you see a version below 18, you'll need to upgrade. - - - - If your Node.js version looks correct but you're still getting errors, check your PATH: - - ```bash - echo $PATH - ``` - - Look for Node.js paths in the output. If you see multiple Node.js versions, the first one in the PATH will be used. You can set the PATH [environment variable](/mcp-server/quickstart#environment-variables) in your mcp config to override what node version is being used. - - - - Check that your environment variables are set correctly. See the [environment variables](/mcp-server/quickstart#environment-variables) section for reference. - - - -## Common Issues - -### 'fetch' is not defined errors - -This is the most common error and typically indicates a Node.js version issue. If the quick diagnosis above didn't solve your problem, try forcing a specific Node.js version: - - - - You can force the MCP server to use a specific Node.js version by setting the PATH environment variable: - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"], - "env": { - "PATH": "/path/to/your/node/bin" - } - } - } - } - ``` - - Replace `/path/to/your/node/bin` with the actual path to your preferred Node.js version. - - - **Quick Path Finder**: Run `dirname $(which npx)` to get the correct path to use. - - - - -### NVM Version Conflicts - -If you're using NVM (Node Version Manager), you might have multiple Node.js versions installed. - - - - Check your installed versions: - - ```bash - nvm list - ``` - - Look for versions below 18 that might be taking precedence. - - - - Uninstall Node.js versions below 18: - - ```bash - nvm uninstall 16.15.0 - nvm uninstall 14.21.3 - # ... uninstall other versions below 18 - ``` - - This will prevent conflicts with older versions. - - - - Alternatively, you can force the MCP server to use a specific Node.js version by setting the PATH environment variable: - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"], - "env": { - "PATH": "/Users/yourname/.nvm/versions/node/v18.18.0/bin:/usr/local/bin:/usr/bin:/bin" - } - } - } - } - ``` - - - -### Environment Variable Issues - -Many issues stem from incorrect environment variable configuration. - - - - Verify your environment variables are set correctly. Common issues include: - - - **WALLET_MODE**: Should be `"disabled"` or `"private-key"` - - **PRIVATE_KEY**: Must be 0x-prefixed hex string when using private-key mode - - **RPC URLs**: Should be valid URLs if you're overriding defaults - - - - Try running with minimal configuration first: - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"] - } - } - } - ``` - - If this works, gradually add your environment variables back. - - - - See the [Environment Variables](/mcp-server/quickstart#environment-variables) section for complete documentation of all available options. - - - - - -## Error Reference - - - - **Cause**: Node.js version below 18 or PATH pointing to wrong Node.js version - **Solution**: Upgrade Node.js or fix PATH as shown above - - - **Cause**: Package not installed or network issues - **Solution**: Check internet connection and try reinstalling the package - - - **Cause**: Insufficient permissions to execute npx - **Solution**: Ensure npx is executable or use full path to Node.js binary - - - **Cause**: Invalid RPC URL or network connectivity issues - **Solution**: Check your RPC URLs and internet connection - - - -## Getting Help - -### Before Reporting an Issue - -1. **Check this troubleshooting guide** - Your issue might already be covered -2. **Verify your environment** - Ensure Node.js 18+ and correct PATH -3. **Test with minimal config** - Try the basic setup first -4. **Check environment variables** - Verify all settings are correct - -### Reporting Issues - -If you're still experiencing problems, please [create an issue on GitHub](https://github.com/sei-protocol/sei-js/issues) with the following information: - - - - Include: - - Operating system and version - - Node.js version (`node --version`) - - MCP client (Cursor, Claude Desktop, etc.) - - Your PATH (`echo $PATH`) - - - - Share your MCP configuration (remove private keys): - - ```json - { - "mcpServers": { - "sei": { - "command": "npx", - "args": ["-y", "@sei-js/mcp-server"], - "env": { - "WALLET_MODE": "disabled" - // ... other env vars (no private keys) - } - } - } - } - ``` - - - - Include the complete error message and any relevant logs. - - - - Describe exactly what you did to encounter the issue. - - - - -**Security**: Never include private keys or sensitive information when reporting issues. Use placeholder values instead. - - -### Community Support - -- **GitHub Issues**: [Create an issue](https://github.com/sei-protocol/sei-js/issues) -- **Discord**: Join the [Sei Discord](https://discord.gg/sei) for community help -- **Documentation**: Check the [main Sei docs](https://docs.sei.io/) for additional resources \ No newline at end of file diff --git a/docs/overview.mdx b/docs/overview.mdx deleted file mode 100644 index ebd14c05b..000000000 --- a/docs/overview.mdx +++ /dev/null @@ -1,140 +0,0 @@ ---- -title: Quick Start Guide -description: Build your first Sei application in under 10 minutes with @sei-js -icon: "bolt" ---- - -## Prerequisites - -Before you begin, ensure you have the following installed: - - - - **Required for running @sei-js applications:** - - **Node.js** (v18 or higher) - Required for npx and package management - - **nvm** (Node Version Manager) - Recommended for managing Node.js versions - - - Verify your installation: `node --version` should output v18.0.0 or higher - - - - - **Traditional Editors:** - - **VS Code** - Popular, lightweight with excellent TypeScript support - - **WebStorm** - Full-featured IDE with advanced debugging and refactoring - - **AI-Powered Editors:** - - **Cursor** - VS Code fork with built-in AI coding assistance - - **Windsurf** - AI-first development environment with intelligent code generation - - - All editors work great with @sei-js projects. Choose based on your preference for AI assistance and feature requirements. - - - - -## Create your first Sei application - - - - Generate a new Sei application using our CLI tool: - - - ```bash npx - npx @sei-js/create-sei app - ``` - - ```bash pnpm - pnpm create @sei-js/create-sei app - ``` - - - - **Expected outcome:** A new project directory with TypeScript configuration, testing setup, and example code. - - - - The CLI will ask you to choose a template. Select "React + Wagmi" for a full-featured web application, or "Node.js" for backend/script development. - - - - - Move into your project directory and install dependencies: - - - ```bash npm - cd app - npm install - ``` - - ```bash yarn - cd app - yarn install - ``` - - ```bash pnpm - cd app - pnpm install - ``` - - - - **Expected outcome:** All dependencies installed successfully without errors. - - - - **Common issues and solutions:** - - - **Node version conflicts:** Use `nvm use` to switch to the correct Node.js version - - **Permission errors:** Avoid using `sudo` with npm. Use `nvm` or fix npm permissions - - **Network timeouts:** Try switching to a different registry: `npm config set registry https://registry.npmjs.org/` - - - - - Launch your application in development mode: - - - ```bash npm - npm run dev - ``` - - ```bash yarn - yarn dev - ``` - - ```bash pnpm - pnpm dev - ``` - - - - **Expected outcome:** Development server running at `http://localhost:3000` with hot reload enabled. - - - Your browser should automatically open to show your new Sei application with: - - Wallet connection button - - Network status display - - Example interactions ready to test - - - -## What you can build - -Your new Sei application comes with examples and patterns for common blockchain interactions: - - - - Connect to any Sei-compatible wallet including MetaMask, Compass, and more using the built-in wallet integration - - - Fetch and display wallet balances for SEI and other tokens with real-time updates - - - Access blockchain information like total SEI supply using precompile contracts - - - Deploy and interact with smart contracts including simple examples like counters and token transfers - - diff --git a/docs/precompiles/introduction.mdx b/docs/precompiles/introduction.mdx deleted file mode 100644 index e22cf4b21..000000000 --- a/docs/precompiles/introduction.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: 'Introduction' -description: '@sei-js/precompiles is a TypeScript library for interacting with Sei precompile contracts' -icon: "microchip" ---- - -## Overview - -The `@sei-js/precompiles` package provides TypeScript utilities and helpers for interacting with Sei's precompile contracts. It offers seamless integration with popular Ethereum development tools like Viem and Ethers.js, providing typed interfaces, contract factories, and utilities specifically designed for Sei's precompile ecosystem. - -## Key Features - -- **Precompile-First Design**: Purpose-built for Sei's precompile contract ecosystem -- **Type Safety**: Fully typed interfaces and contract factories for both Viem and Ethers.js -- **Contract Helpers**: Utilities and helpers specifically for precompile interactions -- **Production Ready**: Battle-tested precompile integrations used across the Sei ecosystem - -## Installation - - - -```bash npm -npm install @sei-js/precompiles -``` - -```bash yarn -yarn add @sei-js/precompiles -``` - -```bash pnpm -pnpm add @sei-js/precompiles -``` - - \ No newline at end of file diff --git a/docs/precompiles/precompiles/address.mdx b/docs/precompiles/precompiles/address.mdx deleted file mode 100644 index 8f3dc7dc0..000000000 --- a/docs/precompiles/precompiles/address.mdx +++ /dev/null @@ -1,459 +0,0 @@ ---- -title: 'Address Precompile' -description: 'Manage address associations between Sei and EVM addresses through the Address precompile contract' -icon: "address-card" ---- - -## Overview - -The Address precompile enables bidirectional address mapping between Sei's native Cosmos addresses (bech32 format) and EVM addresses (hex format). This is essential for cross-chain functionality and allows users to associate their Cosmos and EVM identities. - -**Contract Address:** `0x0000000000000000000000000000000000001004` - -## Key Features - -- **Address Translation**: Convert between Sei and EVM address formats -- **Address Association**: Link Cosmos and EVM addresses for the same account -- **Cross-Chain Identity**: Enable seamless interaction between EVM and Cosmos ecosystems -- **Public Key Association**: Associate addresses using public key cryptography - -## Available Functions - -### View Functions - - - - Get the associated Sei (Cosmos) address for an EVM address. - - **Parameters:** - - `addr` (address): The EVM address to lookup - - **Returns:** Associated Sei address in bech32 format - - ```typescript - const seiAddress = await addressContract.getSeiAddr( - "0x742d35Cc6634C0532925a3b8D6Ac0c2fb15d8d2A" - ); - // Returns: "sei1wsltdx4m9k8dafl92nkwmywd6k7jdlpz5h3j3q" - ``` - - - - Get the associated EVM address for a Sei (Cosmos) address. - - **Parameters:** - - `addr` (string): The Sei address to lookup (bech32 format) - - **Returns:** Associated EVM address in hex format - - ```typescript - const evmAddress = await addressContract.getEvmAddr( - "sei1wsltdx4m9k8dafl92nkwmywd6k7jdlpz5h3j3q" - ); - // Returns: "0x742d35Cc6634C0532925a3b8D6Ac0c2fb15d8d2A" - ``` - - - -### State-Changing Functions - - - - Associate addresses using signature verification. - - **Parameters:** - - `v` (string): Recovery ID from signature - - `r` (string): R component of signature - - `s` (string): S component of signature - - `customMessage` (string): Custom message that was signed - - **Returns:** Tuple of (seiAddr, evmAddr) - - ```typescript - const [seiAddr, evmAddr] = await addressContract.associate( - "27", // v - "0x1234...", // r - "0x5678...", // s - "Associate my addresses" // customMessage - ); - ``` - - - - Associate addresses using a public key. - - **Parameters:** - - `pubKeyHex` (string): Public key in hexadecimal format - - **Returns:** Tuple of (seiAddr, evmAddr) - - ```typescript - const [seiAddr, evmAddr] = await addressContract.associatePubKey( - "0x04a1b2c3d4e5f6..." // Uncompressed public key - ); - ``` - - - -## Usage Examples - - - - ```typescript - import { createPublicClient, createWalletClient, http } from 'viem'; - import { privateKeyToAccount } from 'viem/accounts'; - import { - seiTestnet, - ADDRESS_PRECOMPILE_ABI, - ADDRESS_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles/viem'; - - const publicClient = createPublicClient({ - chain: seiTestnet, - transport: http() - }); - - const account = privateKeyToAccount('0x...'); - const walletClient = createWalletClient({ - account, - chain: seiTestnet, - transport: http() - }); - - // Get Sei address for EVM address - async function getSeiAddress(evmAddress: string) { - try { - const seiAddress = await publicClient.readContract({ - address: ADDRESS_PRECOMPILE_ADDRESS, - abi: ADDRESS_PRECOMPILE_ABI, - functionName: 'getSeiAddr', - args: [evmAddress] - }); - - return seiAddress; - } catch (error) { - console.log('No association found for', evmAddress); - return null; - } - } - - // Get EVM address for Sei address - async function getEvmAddress(seiAddress: string) { - try { - const evmAddress = await publicClient.readContract({ - address: ADDRESS_PRECOMPILE_ADDRESS, - abi: ADDRESS_PRECOMPILE_ABI, - functionName: 'getEvmAddr', - args: [seiAddress] - }); - - return evmAddress; - } catch (error) { - console.log('No association found for', seiAddress); - return null; - } - } - - // Associate addresses using public key - async function associateAddresses(publicKey: string) { - const hash = await walletClient.writeContract({ - address: ADDRESS_PRECOMPILE_ADDRESS, - abi: ADDRESS_PRECOMPILE_ABI, - functionName: 'associatePubKey', - args: [publicKey] - }); - - const receipt = await publicClient.waitForTransactionReceipt({ hash }); - - // Parse the return values from logs or events - return receipt; - } - - // Check if addresses are associated - async function checkAssociation(evmAddress: string, seiAddress: string) { - const [associatedSei, associatedEvm] = await Promise.all([ - getSeiAddress(evmAddress), - getEvmAddress(seiAddress) - ]); - - return { - isAssociated: associatedSei === seiAddress && associatedEvm === evmAddress, - evmToSei: associatedSei, - seiToEvm: associatedEvm - }; - } - - // Batch lookup multiple addresses - async function batchLookupAddresses(addresses: string[]) { - const lookupPromises = addresses.map(async (addr) => { - if (addr.startsWith('0x')) { - // EVM address - const seiAddr = await getSeiAddress(addr); - return { evmAddr: addr, seiAddr, type: 'evm' }; - } else if (addr.startsWith('sei1')) { - // Sei address - const evmAddr = await getEvmAddress(addr); - return { seiAddr: addr, evmAddr, type: 'sei' }; - } - return { error: 'Invalid address format', address: addr }; - }); - - return await Promise.all(lookupPromises); - } - ``` - - - - ```typescript - import { ethers } from 'ethers'; - import { getAddressPrecompileEthersContract } from '@sei-js/precompiles/ethers'; - - const provider = new ethers.JsonRpcProvider('https://evm-rpc-testnet.sei-apis.com'); - const signer = new ethers.Wallet('0x...', provider); - const addressContract = getAddressPrecompileEthersContract(provider); - - // Get Sei address for EVM address - async function getSeiAddress(evmAddress: string) { - try { - return await addressContract.getSeiAddr(evmAddress); - } catch (error) { - console.log('No association found for', evmAddress); - return null; - } - } - - // Get EVM address for Sei address - async function getEvmAddress(seiAddress: string) { - try { - return await addressContract.getEvmAddr(seiAddress); - } catch (error) { - console.log('No association found for', seiAddress); - return null; - } - } - - // Associate addresses using public key - async function associateAddresses(publicKey: string) { - const addressWithSigner = addressContract.connect(signer); - - const tx = await addressWithSigner.associatePubKey(publicKey); - const receipt = await tx.wait(); - - // Extract return values from transaction logs - return receipt; - } - - // Create address mapping utility - class AddressMapper { - private contract: ethers.Contract; - - constructor(provider: ethers.Provider) { - this.contract = getAddressPrecompileEthersContract(provider); - } - - async mapEvmToSei(evmAddress: string): Promise { - try { - return await this.contract.getSeiAddr(evmAddress); - } catch { - return null; - } - } - - async mapSeiToEvm(seiAddress: string): Promise { - try { - return await this.contract.getEvmAddr(seiAddress); - } catch { - return null; - } - } - - async isAssociated(evmAddress: string, seiAddress: string): Promise { - const [mappedSei, mappedEvm] = await Promise.all([ - this.mapEvmToSei(evmAddress), - this.mapSeiToEvm(seiAddress) - ]); - - return mappedSei === seiAddress && mappedEvm === evmAddress; - } - } - - // Usage - const mapper = new AddressMapper(provider); - const isLinked = await mapper.isAssociated( - '0x742d35Cc6634C0532925a3b8D6Ac0c2fb15d8d2A', - 'sei1wsltdx4m9k8dafl92nkwmywd6k7jdlpz5h3j3q' - ); - ``` - - - - ```typescript - import { - ADDRESS_PRECOMPILE_ABI, - ADDRESS_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles'; - - // Using with web3.js - import Web3 from 'web3'; - - const web3 = new Web3('https://evm-rpc-testnet.sei-apis.com'); - const addressContract = new web3.eth.Contract( - ADDRESS_PRECOMPILE_ABI, - ADDRESS_PRECOMPILE_ADDRESS - ); - - // Get Sei address for EVM address - const seiAddress = await addressContract.methods - .getSeiAddr('0x742d35Cc6634C0532925a3b8D6Ac0c2fb15d8d2A') - .call(); - - // Get EVM address for Sei address - const evmAddress = await addressContract.methods - .getEvmAddr('sei1wsltdx4m9k8dafl92nkwmywd6k7jdlpz5h3j3q') - .call(); - - // Associate addresses using public key - const account = web3.eth.accounts.privateKeyToAccount('0x...'); - web3.eth.accounts.wallet.add(account); - - const tx = await addressContract.methods - .associatePubKey('0x04a1b2c3d4e5f6...') - .send({ - from: account.address, - gas: 100000 - }); - ``` - - - -## Common Use Cases - -### Cross-Chain Applications -- **Unified Identity**: Link user identities across EVM and Cosmos ecosystems -- **Asset Bridging**: Map assets between different address formats -- **Multi-Chain Wallets**: Support both EVM and Cosmos transactions - -### DeFi Integration -- **Liquidity Provision**: Use associated addresses for cross-chain liquidity -- **Yield Farming**: Participate in farming across both ecosystems -- **Governance**: Vote with associated addresses in different governance systems - -### Wallet Applications -- **Address Book**: Display both address formats for contacts -- **Transaction History**: Track transactions across both address types -- **Portfolio Management**: Aggregate holdings across associated addresses - -## Address Association Process - -### Using Public Key (Recommended) -```typescript -// 1. Get user's public key from wallet -const publicKey = await getPublicKeyFromWallet(); - -// 2. Associate addresses -const [seiAddr, evmAddr] = await addressContract.associatePubKey(publicKey); - -// 3. Verify association -const isAssociated = await checkAssociation(evmAddr, seiAddr); -``` - -### Using Signature Verification -```typescript -// 1. Create custom message -const message = "Associate my Sei and EVM addresses"; - -// 2. Sign message with private key -const signature = await signMessage(message, privateKey); - -// 3. Extract signature components -const { v, r, s } = parseSignature(signature); - -// 4. Associate addresses -const [seiAddr, evmAddr] = await addressContract.associate(v, r, s, message); -``` - -## Address Format Validation - -```typescript -// Validate EVM address format -function isValidEvmAddress(address: string): boolean { - return /^0x[a-fA-F0-9]{40}$/.test(address); -} - -// Validate Sei address format -function isValidSeiAddress(address: string): boolean { - return /^sei1[a-z0-9]{38}$/.test(address); -} - -// Address format converter utility -class AddressUtils { - static isEvm(address: string): boolean { - return address.startsWith('0x') && address.length === 42; - } - - static isSei(address: string): boolean { - return address.startsWith('sei1') && address.length === 43; - } - - static getAddressType(address: string): 'evm' | 'sei' | 'unknown' { - if (this.isEvm(address)) return 'evm'; - if (this.isSei(address)) return 'sei'; - return 'unknown'; - } -} -``` - -## Error Handling - -Common errors when using the Address precompile: - -- **No association found**: Addresses haven't been linked yet -- **Invalid address format**: Malformed EVM or Sei addresses -- **Association already exists**: Trying to associate already linked addresses -- **Invalid signature**: Signature verification failed during association - -```typescript -async function safeGetAssociation(address: string) { - try { - const addressType = AddressUtils.getAddressType(address); - - if (addressType === 'evm') { - return await addressContract.getSeiAddr(address); - } else if (addressType === 'sei') { - return await addressContract.getEvmAddr(address); - } else { - throw new Error('Invalid address format'); - } - } catch (error) { - if (error.message.includes('no association')) { - return null; // No association exists - } else if (error.message.includes('invalid address')) { - throw new Error('Invalid address format'); - } else { - throw error; // Re-throw unexpected errors - } - } -} -``` - -## Security Considerations - -- **Public Key Security**: Ensure public keys are handled securely -- **Signature Verification**: Validate signatures before association -- **Address Ownership**: Verify ownership before creating associations -- **Association Permanence**: Address associations are typically permanent - -```typescript -// Verify address ownership before association -async function verifyAddressOwnership(address: string, signature: string) { - const message = "I own this address"; - const recoveredAddress = recoverAddressFromSignature(message, signature); - return recoveredAddress.toLowerCase() === address.toLowerCase(); -} -``` - -## Related Precompiles - -- **[Bank](/precompiles/precompiles/bank)**: Transfer tokens between associated addresses -- **[IBC](/precompiles/precompiles/ibc)**: Cross-chain transfers using address mapping -- **[Staking](/precompiles/precompiles/staking)**: Delegate from associated addresses diff --git a/docs/precompiles/precompiles/bank.mdx b/docs/precompiles/precompiles/bank.mdx deleted file mode 100644 index 1bac2ec8e..000000000 --- a/docs/precompiles/precompiles/bank.mdx +++ /dev/null @@ -1,347 +0,0 @@ ---- -title: 'Bank Precompile' -description: 'Interact with Sei native tokens and balances through the Bank precompile contract' -icon: "building-columns" ---- - -## Overview - -The Bank precompile provides access to Sei's native token operations, allowing you to query balances, transfer tokens, and retrieve token metadata directly from EVM contracts. This precompile bridges EVM and Cosmos SDK bank module functionality. - -**Contract Address:** `0x0000000000000000000000000000000000001001` - -## Key Features - -- **Balance Queries**: Check token balances for any address and denomination -- **Token Transfers**: Send native tokens between addresses -- **Token Metadata**: Get token name, symbol, decimals, and total supply -- **Multi-Denomination Support**: Work with any native token denomination - -## Available Functions - -### View Functions - - - - Get the balance of a specific token denomination for an address. - - **Parameters:** - - `acc` (address): The account address to query - - `denom` (string): The token denomination (e.g., "usei") - - **Returns:** Token balance as uint256 - - ```typescript - const balance = await bankContract.balance( - "0x742d35Cc6634C0532925a3b8D6Ac0c2fb15d8d2A", - "usei" - ); - ``` - - - - Get all token balances for an address across all denominations. - - **Parameters:** - - `acc` (address): The account address to query - - **Returns:** Array of Coin structs with amount and denomination - - ```typescript - const balances = await bankContract.all_balances( - "0x742d35Cc6634C0532925a3b8D6Ac0c2fb15d8d2A" - ); - // Returns: [{ amount: 1000000n, denom: "usei" }, ...] - ``` - - - - Get the display name for a token denomination. - - **Parameters:** - - `denom` (string): The token denomination - - **Returns:** Human-readable token name - - ```typescript - const name = await bankContract.name("usei"); - // Returns: "Sei" - ``` - - - - Get the symbol for a token denomination. - - **Parameters:** - - `denom` (string): The token denomination - - **Returns:** Token symbol - - ```typescript - const symbol = await bankContract.symbol("usei"); - // Returns: "SEI" - ``` - - - - Get the number of decimals for a token denomination. - - **Parameters:** - - `denom` (string): The token denomination - - **Returns:** Number of decimal places - - ```typescript - const decimals = await bankContract.decimals("usei"); - // Returns: 6 - ``` - - - - Get the total supply of a token denomination. - - **Parameters:** - - `denom` (string): The token denomination - - **Returns:** Total token supply - - ```typescript - const supply = await bankContract.supply("usei"); - ``` - - - -### State-Changing Functions - - - - Transfer tokens between addresses. - - **Parameters:** - - `fromAddress` (address): Source address - - `toAddress` (address): Destination address - - `denom` (string): Token denomination - - `amount` (uint256): Amount to transfer - - **Returns:** Success boolean - - ```typescript - const success = await bankContract.send( - "0x742d35Cc6634C0532925a3b8D6Ac0c2fb15d8d2A", - "0x8ba1f109551bD432803012645Hac136c", - "usei", - 1000000n - ); - ``` - - - - Send native SEI tokens to a Cosmos address. - - **Parameters:** - - `toNativeAddress` (string): Destination Cosmos address - - **Returns:** Success boolean - - **Note:** This function is payable - send SEI with the transaction - - ```typescript - const success = await bankContract.sendNative( - "sei1...", - { value: parseEther("1.0") } - ); - ``` - - - -## Usage Examples - - - - ```typescript - import { createPublicClient, http, formatEther } from 'viem'; - import { - seiTestnet, - BANK_PRECOMPILE_ABI, - BANK_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles/viem'; - - const client = createPublicClient({ - chain: seiTestnet, - transport: http() - }); - - // Get SEI balance - async function getSeiBalance(address: string) { - const balance = await client.readContract({ - address: BANK_PRECOMPILE_ADDRESS, - abi: BANK_PRECOMPILE_ABI, - functionName: 'balance', - args: [address, 'usei'] - }); - - return formatEther(balance); - } - - // Get all balances - async function getAllBalances(address: string) { - const balances = await client.readContract({ - address: BANK_PRECOMPILE_ADDRESS, - abi: BANK_PRECOMPILE_ABI, - functionName: 'all_balances', - args: [address] - }); - - return balances.map(coin => ({ - denom: coin.denom, - amount: formatEther(coin.amount) - })); - } - - // Get token metadata - async function getTokenInfo(denom: string) { - const [name, symbol, decimals] = await Promise.all([ - client.readContract({ - address: BANK_PRECOMPILE_ADDRESS, - abi: BANK_PRECOMPILE_ABI, - functionName: 'name', - args: [denom] - }), - client.readContract({ - address: BANK_PRECOMPILE_ADDRESS, - abi: BANK_PRECOMPILE_ABI, - functionName: 'symbol', - args: [denom] - }), - client.readContract({ - address: BANK_PRECOMPILE_ADDRESS, - abi: BANK_PRECOMPILE_ABI, - functionName: 'decimals', - args: [denom] - }) - ]); - - return { name, symbol, decimals }; - } - ``` - - - - ```typescript - import { ethers } from 'ethers'; - import { getBankPrecompileEthersContract } from '@sei-js/precompiles/ethers'; - - const provider = new ethers.JsonRpcProvider('https://evm-rpc-testnet.sei-apis.com'); - const bankContract = getBankPrecompileEthersContract(provider); - - // Get SEI balance - async function getSeiBalance(address: string) { - const balance = await bankContract.balance(address, 'usei'); - return ethers.formatEther(balance); - } - - // Get all balances - async function getAllBalances(address: string) { - const balances = await bankContract.all_balances(address); - return balances.map(coin => ({ - denom: coin.denom, - amount: ethers.formatEther(coin.amount) - })); - } - - // Transfer tokens - async function transferTokens( - signer: ethers.Signer, - to: string, - amount: string - ) { - const bankWithSigner = bankContract.connect(signer); - const fromAddress = await signer.getAddress(); - - const tx = await bankWithSigner.send( - fromAddress, - to, - 'usei', - ethers.parseEther(amount) - ); - - return await tx.wait(); - } - ``` - - - - ```typescript - import { - BANK_PRECOMPILE_ABI, - BANK_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles'; - - // Using with web3.js - import Web3 from 'web3'; - - const web3 = new Web3('https://evm-rpc-testnet.sei-apis.com'); - const bankContract = new web3.eth.Contract( - BANK_PRECOMPILE_ABI, - BANK_PRECOMPILE_ADDRESS - ); - - // Get balance - const balance = await bankContract.methods - .balance('0x742d35Cc6634C0532925a3b8D6Ac0c2fb15d8d2A', 'usei') - .call(); - - // Get all balances - const allBalances = await bankContract.methods - .all_balances('0x742d35Cc6634C0532925a3b8D6Ac0c2fb15d8d2A') - .call(); - ``` - - - -## Common Use Cases - -### DeFi Integration -- Query user token balances before swaps -- Check available liquidity across denominations -- Validate token transfers in smart contracts - -### Wallet Applications -- Display user portfolio across all native tokens -- Enable native token transfers -- Show token metadata and formatting - -### Cross-Chain Applications -- Bridge native tokens to other chains -- Query token supplies for economic analysis -- Handle multi-denomination transactions - -## Error Handling - -Common errors when using the Bank precompile: - -- **Invalid address format**: Ensure addresses are valid EVM addresses -- **Unknown denomination**: Verify the token denomination exists -- **Insufficient balance**: Check balance before attempting transfers -- **Invalid amount**: Ensure transfer amounts are positive and within limits - -```typescript -try { - const balance = await bankContract.balance(address, 'usei'); - console.log('Balance:', formatEther(balance)); -} catch (error) { - if (error.message.includes('invalid address')) { - console.error('Invalid address format'); - } else if (error.message.includes('unknown denomination')) { - console.error('Token denomination not found'); - } else { - console.error('Unexpected error:', error); - } -} -``` - -## Related Precompiles - -- **[Distribution](/precompiles/precompiles/distribution)**: Claim staking rewards -- **[Staking](/precompiles/precompiles/staking)**: Delegate tokens to validators -- **[IBC](/precompiles/precompiles/ibc)**: Transfer tokens cross-chain diff --git a/docs/precompiles/precompiles/distribution.mdx b/docs/precompiles/precompiles/distribution.mdx deleted file mode 100644 index 532558f61..000000000 --- a/docs/precompiles/precompiles/distribution.mdx +++ /dev/null @@ -1,628 +0,0 @@ ---- -title: "Distribution Precompile" -description: "Claim staking rewards and manage reward distribution through the Distribution precompile contract" -icon: "gift" ---- - -## Overview - -The Distribution precompile provides access to Sei's staking reward distribution system, allowing you to claim delegation rewards, set withdrawal addresses, and query pending rewards directly from EVM contracts. This bridges EVM functionality with Cosmos SDK distribution module. - -**Contract Address:** `0x0000000000000000000000000000000000001007` - -## Key Features - -- **Reward Claiming**: Withdraw staking rewards from validator delegations -- **Batch Operations**: Claim rewards from multiple validators in a single transaction -- **Reward Queries**: Check pending rewards before claiming -- **Withdrawal Management**: Set custom withdrawal addresses for rewards - -## Available Functions - -### State-Changing Functions - - - - Withdraw staking rewards from a specific validator. - - **Parameters:** - - `validator` (string): The validator's operator address - - **Returns:** Success boolean - - ```typescript - const success = await distributionContract.withdrawDelegationRewards( - "seivaloper1..." - ); - ``` - - - - Withdraw staking rewards from multiple validators in a single transaction. - **Parameters:** - `validators` (string[]): Array of validator operator - addresses **Returns:** Success boolean ```typescript const validators = [ - "seivaloper1...", "seivaloper2...", "seivaloper3..." ]; const success = await - distributionContract.withdrawMultipleDelegationRewards( validators ); ``` - - - - Set a custom address to receive withdrawn rewards. - - **Parameters:** - - `withdrawAddr` (address): The EVM address to receive rewards - - **Returns:** Success boolean - - ```typescript - const success = await distributionContract.setWithdrawAddress( - "0x742d35Cc6634C0532925a3b8D6Ac0c2fb15d8d2A" - ); - ``` - - - -### View Functions - - - - Query pending staking rewards for a delegator. - - **Parameters:** - - `delegatorAddress` (address): The delegator's EVM address - - **Returns:** Rewards struct with detailed breakdown - - **Return Structure:** - ```typescript - interface Rewards { - rewards: Array<{ - coins: Array<{ - amount: bigint; - decimals: bigint; - denom: string; - }>; - validator_address: string; - }>; - total: Array<{ - amount: bigint; - decimals: bigint; - denom: string; - }>; - } - ``` - - ```typescript - const rewards = await distributionContract.rewards( - "0x742d35Cc6634C0532925a3b8D6Ac0c2fb15d8d2A" - ); - - // Access total rewards - console.log('Total SEI rewards:', formatEther(rewards.total[0].amount)); - - // Access per-validator rewards - rewards.rewards.forEach(reward => { - console.log(`Validator ${reward.validator_address}:`); - reward.coins.forEach(coin => { - console.log(` ${coin.denom}: ${formatEther(coin.amount)}`); - }); - }); - ``` - - - -## Usage Examples - - - - ```typescript - import { createPublicClient, createWalletClient, http, formatEther } from 'viem'; - import { privateKeyToAccount } from 'viem/accounts'; - import { - seiTestnet, - DISTRIBUTION_PRECOMPILE_ABI, - DISTRIBUTION_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles'; - - const publicClient = createPublicClient({ - chain: seiTestnet, - transport: http() - }); - - const account = privateKeyToAccount('0x...'); - const walletClient = createWalletClient({ - account, - chain: seiTestnet, - transport: http() - }); - - // Query pending rewards - async function getPendingRewards(delegatorAddress: string) { - const rewards = await publicClient.readContract({ - address: DISTRIBUTION_PRECOMPILE_ADDRESS, - abi: DISTRIBUTION_PRECOMPILE_ABI, - functionName: 'rewards', - args: [delegatorAddress] - }); - - return { - totalRewards: rewards.total.map(coin => ({ - denom: coin.denom, - amount: formatEther(coin.amount), - decimals: Number(coin.decimals) - })), - validatorRewards: rewards.rewards.map(reward => ({ - validator: reward.validator_address, - coins: reward.coins.map(coin => ({ - denom: coin.denom, - amount: formatEther(coin.amount), - decimals: Number(coin.decimals) - })) - })) - }; - } - - // Claim rewards from a single validator - async function claimRewardsFromValidator(validatorAddress: string) { - const hash = await walletClient.writeContract({ - address: DISTRIBUTION_PRECOMPILE_ADDRESS, - abi: DISTRIBUTION_PRECOMPILE_ABI, - functionName: 'withdrawDelegationRewards', - args: [validatorAddress] - }); - - return await publicClient.waitForTransactionReceipt({ hash }); - } - - // Claim rewards from multiple validators - async function claimAllRewards(validatorAddresses: string[]) { - const hash = await walletClient.writeContract({ - address: DISTRIBUTION_PRECOMPILE_ADDRESS, - abi: DISTRIBUTION_PRECOMPILE_ABI, - functionName: 'withdrawMultipleDelegationRewards', - args: [validatorAddresses] - }); - - return await publicClient.waitForTransactionReceipt({ hash }); - } - - // Set withdrawal address - async function setRewardWithdrawalAddress(withdrawAddress: string) { - const hash = await walletClient.writeContract({ - address: DISTRIBUTION_PRECOMPILE_ADDRESS, - abi: DISTRIBUTION_PRECOMPILE_ABI, - functionName: 'setWithdrawAddress', - args: [withdrawAddress] - }); - - return await publicClient.waitForTransactionReceipt({ hash }); - } - - // Comprehensive reward management - async function manageRewards(delegatorAddress: string) { - // 1. Check pending rewards - const pendingRewards = await getPendingRewards(delegatorAddress); - - console.log('Pending rewards:'); - pendingRewards.totalRewards.forEach(reward => { - console.log(` ${reward.denom}: ${reward.amount}`); - }); - - // 2. Get validators with rewards - const validatorsWithRewards = pendingRewards.validatorRewards - .filter(reward => reward.coins.some(coin => parseFloat(coin.amount) > 0)) - .map(reward => reward.validator); - - if (validatorsWithRewards.length === 0) { - console.log('No rewards to claim'); - return; - } - - // 3. Claim all rewards efficiently - if (validatorsWithRewards.length === 1) { - console.log('Claiming rewards from single validator'); - return await claimRewardsFromValidator(validatorsWithRewards[0]); - } else { - console.log(`Claiming rewards from ${validatorsWithRewards.length} validators`); - return await claimAllRewards(validatorsWithRewards); - } - } - - // Auto-compound rewards (claim and re-delegate) - async function autoCompoundRewards( - delegatorAddress: string, - preferredValidator: string - ) { - // This would require integration with staking precompile - const rewards = await getPendingRewards(delegatorAddress); - const totalSeiRewards = rewards.totalRewards.find(r => r.denom === 'usei'); - - if (totalSeiRewards && parseFloat(totalSeiRewards.amount) > 0) { - console.log(`Auto-compounding ${totalSeiRewards.amount} SEI`); - - // 1. Claim rewards - const validatorsWithRewards = rewards.validatorRewards - .filter(r => r.coins.some(c => c.denom === 'usei' && parseFloat(c.amount) > 0)) - .map(r => r.validator); - - await claimAllRewards(validatorsWithRewards); - - // 2. Re-delegate (would need staking precompile integration) - console.log(`Would re-delegate to ${preferredValidator}`); - } - } - ``` - - - - - ```typescript - import { ethers } from 'ethers'; - import { getDistributionPrecompileEthersV6Contract } from '@sei-js/precompiles'; - - const provider = new ethers.JsonRpcProvider('https://evm-rpc-testnet.sei-apis.com'); - const signer = new ethers.Wallet('0x...', provider); - const distributionContract = getDistributionPrecompileEthersV6Contract(provider); - - // Query pending rewards - async function getPendingRewards(delegatorAddress: string) { - const rewards = await distributionContract.rewards(delegatorAddress); - - return { - totalRewards: rewards.total.map(coin => ({ - denom: coin.denom, - amount: ethers.formatEther(coin.amount), - decimals: Number(coin.decimals) - })), - validatorRewards: rewards.rewards.map(reward => ({ - validator: reward.validator_address, - coins: reward.coins.map(coin => ({ - denom: coin.denom, - amount: ethers.formatEther(coin.amount), - decimals: Number(coin.decimals) - })) - })) - }; - } - - // Claim rewards from single validator - async function claimRewardsFromValidator(validatorAddress: string) { - const distributionWithSigner = distributionContract.connect(signer); - - const tx = await distributionWithSigner.withdrawDelegationRewards(validatorAddress); - return await tx.wait(); - } - - // Claim rewards from multiple validators - async function claimAllRewards(validatorAddresses: string[]) { - const distributionWithSigner = distributionContract.connect(signer); - - const tx = await distributionWithSigner.withdrawMultipleDelegationRewards(validatorAddresses); - return await tx.wait(); - } - - // Reward management class - class RewardManager { - private contract: ethers.Contract; - private signer: ethers.Signer; - - constructor(provider: ethers.Provider, signer: ethers.Signer) { - this.contract = getDistributionPrecompileEthersV6Contract(provider); - this.signer = signer; - } - - async getPendingRewards(delegatorAddress: string) { - const rewards = await this.contract.rewards(delegatorAddress); - - return { - totalRewards: rewards.total.map(coin => ({ - denom: coin.denom, - amount: ethers.formatEther(coin.amount), - decimals: Number(coin.decimals) - })), - validatorRewards: rewards.rewards.map(reward => ({ - validator: reward.validator_address, - coins: reward.coins.map(coin => ({ - denom: coin.denom, - amount: ethers.formatEther(coin.amount), - decimals: Number(coin.decimals) - })) - })) - }; - } - - async claimAllAvailableRewards(delegatorAddress: string) { - const rewards = await this.getPendingRewards(delegatorAddress); - - const validatorsWithRewards = rewards.validatorRewards - .filter(reward => reward.coins.some(coin => parseFloat(coin.amount) > 0)) - .map(reward => reward.validator); - - if (validatorsWithRewards.length === 0) { - throw new Error('No rewards available to claim'); - } - - const contractWithSigner = this.contract.connect(this.signer); - - if (validatorsWithRewards.length === 1) { - const tx = await contractWithSigner.withdrawDelegationRewards(validatorsWithRewards[0]); - return await tx.wait(); - } else { - const tx = await contractWithSigner.withdrawMultipleDelegationRewards(validatorsWithRewards); - return await tx.wait(); - } - } - - async setWithdrawAddress(withdrawAddress: string) { - const contractWithSigner = this.contract.connect(this.signer); - const tx = await contractWithSigner.setWithdrawAddress(withdrawAddress); - return await tx.wait(); - } - } - - // Usage - const rewardManager = new RewardManager(provider, signer); - - // Check and claim all rewards - const delegatorAddress = await signer.getAddress(); - await rewardManager.claimAllAvailableRewards(delegatorAddress); - ``` - - - - - ```typescript - import { - DISTRIBUTION_PRECOMPILE_ABI, - DISTRIBUTION_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles'; - - // Using with web3.js - import Web3 from 'web3'; - - const web3 = new Web3('https://evm-rpc-testnet.sei-apis.com'); - const distributionContract = new web3.eth.Contract( - DISTRIBUTION_PRECOMPILE_ABI, - DISTRIBUTION_PRECOMPILE_ADDRESS - ); - - // Query pending rewards - const rewards = await distributionContract.methods - .rewards('0xAddress') - .call(); - - // Setup account for transactions - const account = web3.eth.accounts.privateKeyToAccount('0x...'); - web3.eth.accounts.wallet.add(account); - - // Claim rewards from single validator - const claimTx = await distributionContract.methods - .withdrawDelegationRewards('seivaloper1...') - .send({ - from: account.address, - gas: 200000 - }); - - // Claim rewards from multiple validators - const validators = ['seivaloper1...', 'seivaloper2...']; - const claimAllTx = await distributionContract.methods - .withdrawMultipleDelegationRewards(validators) - .send({ - from: account.address, - gas: 300000 - }); - ``` - - - - -## Common Use Cases - -### Automated Reward Claiming - -- **DeFi Protocols**: Automatically claim and reinvest staking rewards -- **Yield Optimization**: Compound rewards to maximize returns -- **Portfolio Management**: Regular reward harvesting across multiple validators - -### Liquid Staking Protocols - -- **Reward Distribution**: Distribute claimed rewards to token holders -- **Fee Collection**: Set withdrawal addresses to protocol treasury -- **Automated Compounding**: Reinvest rewards to increase staking positions - -### Staking-as-a-Service - -- **Client Management**: Claim rewards on behalf of clients -- **Fee Deduction**: Set withdrawal addresses for fee collection -- **Performance Tracking**: Monitor reward generation across validators - -## Reward Optimization Strategies - -### Timing Optimization - -```typescript -// Check if rewards are worth claiming (considering gas costs) -async function shouldClaimRewards( - delegatorAddress: string, - minRewardThreshold: string = "1", // 1 SEI minimum -) { - const rewards = await getPendingRewards(delegatorAddress); - const totalSeiRewards = rewards.totalRewards.find((r) => r.denom === "usei"); - - if (!totalSeiRewards) return false; - - const rewardAmount = parseFloat(totalSeiRewards.amount); - const threshold = parseFloat(minRewardThreshold); - - return rewardAmount >= threshold; -} -``` - -### Validator Selection for Claiming - -```typescript -// Prioritize validators with highest rewards -async function getOptimalClaimingOrder(delegatorAddress: string) { - const rewards = await getPendingRewards(delegatorAddress); - - return rewards.validatorRewards - .filter((reward) => - reward.coins.some((coin) => parseFloat(coin.amount) > 0), - ) - .sort((a, b) => { - const aSeiReward = a.coins.find((c) => c.denom === "usei"); - const bSeiReward = b.coins.find((c) => c.denom === "usei"); - - const aAmount = aSeiReward ? parseFloat(aSeiReward.amount) : 0; - const bAmount = bSeiReward ? parseFloat(bSeiReward.amount) : 0; - - return bAmount - aAmount; // Descending order - }) - .map((reward) => reward.validator); -} -``` - -### Batch Claiming Strategy - -```typescript -// Determine optimal batching strategy -async function getOptimalClaimingStrategy( - delegatorAddress: string, - maxValidatorsPerTx: number = 10, -) { - const validatorsWithRewards = await getOptimalClaimingOrder(delegatorAddress); - - if (validatorsWithRewards.length <= maxValidatorsPerTx) { - return { - strategy: "single_batch", - batches: [validatorsWithRewards], - }; - } else { - const batches = []; - for (let i = 0; i < validatorsWithRewards.length; i += maxValidatorsPerTx) { - batches.push(validatorsWithRewards.slice(i, i + maxValidatorsPerTx)); - } - - return { - strategy: "multiple_batches", - batches, - }; - } -} -``` - -## Reward Tracking and Analytics - -```typescript -// Reward tracking utility -class RewardTracker { - private claimedRewards: Array<{ - timestamp: number; - validators: string[]; - amount: string; - txHash: string; - }> = []; - - recordClaim(validators: string[], amount: string, txHash: string) { - this.claimedRewards.push({ - timestamp: Date.now(), - validators, - amount, - txHash, - }); - } - - getTotalClaimed(): string { - return this.claimedRewards - .reduce((total, claim) => total + parseFloat(claim.amount), 0) - .toString(); - } - - getClaimFrequency(): number { - if (this.claimedRewards.length < 2) return 0; - - const timeSpan = - this.claimedRewards[this.claimedRewards.length - 1].timestamp - - this.claimedRewards[0].timestamp; - - return timeSpan / (this.claimedRewards.length - 1); // Average time between claims - } - - getMostRewardingValidators(): string[] { - const validatorRewards = new Map(); - - this.claimedRewards.forEach((claim) => { - const rewardPerValidator = - parseFloat(claim.amount) / claim.validators.length; - claim.validators.forEach((validator) => { - validatorRewards.set( - validator, - (validatorRewards.get(validator) || 0) + rewardPerValidator, - ); - }); - }); - - return Array.from(validatorRewards.entries()) - .sort((a, b) => b[1] - a[1]) - .map((entry) => entry[0]); - } -} -``` - -## Error Handling - -Common errors when using the Distribution precompile: - -- **No rewards available**: No pending rewards to claim -- **Invalid validator**: Validator address doesn't exist -- **Withdrawal address error**: Invalid withdrawal address format -- **Insufficient gas**: Complex multi-validator claims need more gas - -```typescript -async function safeClaimRewards(validatorAddresses: string[]) { - try { - // Validate inputs - if (validatorAddresses.length === 0) { - throw new Error("No validators specified"); - } - - // Check for pending rewards first - const delegatorAddress = await signer.getAddress(); - const rewards = await getPendingRewards(delegatorAddress); - - const hasRewards = rewards.validatorRewards.some( - (reward) => - validatorAddresses.includes(reward.validator) && - reward.coins.some((coin) => parseFloat(coin.amount) > 0), - ); - - if (!hasRewards) { - throw new Error("No rewards available for specified validators"); - } - - // Claim rewards - if (validatorAddresses.length === 1) { - return await claimRewardsFromValidator(validatorAddresses[0]); - } else { - return await claimAllRewards(validatorAddresses); - } - } catch (error) { - if (error.message.includes("no rewards")) { - throw new Error("No rewards available to claim"); - } else if (error.message.includes("validator not found")) { - throw new Error("One or more validators not found"); - } else if (error.message.includes("out of gas")) { - throw new Error( - "Insufficient gas - try claiming fewer validators at once", - ); - } else { - throw error; - } - } -} -``` - -## Related Precompiles - -- **[Staking](/precompiles/precompiles/staking)**: Delegate tokens to earn rewards -- **[Bank](/precompiles/precompiles/bank)**: Check reward balances after claiming -- **[Governance](/precompiles/precompiles/governance)**: Participate in governance with staked tokens diff --git a/docs/precompiles/precompiles/governance.mdx b/docs/precompiles/precompiles/governance.mdx deleted file mode 100644 index 196a925ab..000000000 --- a/docs/precompiles/precompiles/governance.mdx +++ /dev/null @@ -1,470 +0,0 @@ ---- -title: 'Governance Precompile' -description: 'Participate in Sei network governance through voting and deposits via the Governance precompile contract' -icon: "check-to-slot" ---- - -## Overview - -The Governance precompile enables participation in Sei's on-chain governance system directly from EVM contracts. Users can vote on proposals and make deposits to support governance proposals, bridging EVM functionality with Cosmos SDK governance. - -**Contract Address:** `0x0000000000000000000000000000000000001006` - -## Key Features - -- **Proposal Voting**: Cast votes on governance proposals with different options -- **Proposal Deposits**: Deposit tokens to support governance proposals -- **Democratic Participation**: Enable EVM contracts to participate in network governance -- **Transparent Governance**: All governance actions are recorded on-chain - -## Available Functions - -### State-Changing Functions - - - - Cast a vote on a governance proposal. - - **Parameters:** - - `proposalID` (uint64): The ID of the proposal to vote on - - `option` (int32): The vote option (1=Yes, 2=Abstain, 3=No, 4=NoWithVeto) - - **Returns:** Success boolean - - **Vote Options:** - - `1` - **Yes**: Support the proposal - - `2` - **Abstain**: Neutral vote (counts toward quorum) - - `3` - **No**: Oppose the proposal - - `4` - **NoWithVeto**: Strong opposition (can cause proposal failure) - - ```typescript - // Vote "Yes" on proposal #42 - const success = await governanceContract.vote(42n, 1); - - // Vote "No" on proposal #43 - const success = await governanceContract.vote(43n, 3); - ``` - - - - Make a deposit to support a governance proposal. - - **Parameters:** - - `proposalID` (uint64): The ID of the proposal to deposit to - - **Returns:** Success boolean - - **Note:** This function is payable - send SEI with the transaction as deposit - - ```typescript - // Deposit 100 SEI to proposal #42 - const success = await governanceContract.deposit(42n, { - value: parseEther("100") - }); - ``` - - - -## Usage Examples - - - - ```typescript - import { createPublicClient, createWalletClient, http, parseEther } from 'viem'; - import { privateKeyToAccount } from 'viem/accounts'; - import { - seiTestnet, - GOVERNANCE_PRECOMPILE_ABI, - GOVERNANCE_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles/viem'; - - const publicClient = createPublicClient({ - chain: seiTestnet, - transport: http() - }); - - const account = privateKeyToAccount('0x...'); - const walletClient = createWalletClient({ - account, - chain: seiTestnet, - transport: http() - }); - - // Vote options enum for clarity - enum VoteOption { - YES = 1, - ABSTAIN = 2, - NO = 3, - NO_WITH_VETO = 4 - } - - // Cast a vote on a proposal - async function voteOnProposal(proposalId: bigint, option: VoteOption) { - const hash = await walletClient.writeContract({ - address: GOVERNANCE_PRECOMPILE_ADDRESS, - abi: GOVERNANCE_PRECOMPILE_ABI, - functionName: 'vote', - args: [proposalId, option] - }); - - return await publicClient.waitForTransactionReceipt({ hash }); - } - - // Make a deposit to a proposal - async function depositToProposal(proposalId: bigint, amount: string) { - const hash = await walletClient.writeContract({ - address: GOVERNANCE_PRECOMPILE_ADDRESS, - abi: GOVERNANCE_PRECOMPILE_ABI, - functionName: 'deposit', - args: [proposalId], - value: parseEther(amount) - }); - - return await publicClient.waitForTransactionReceipt({ hash }); - } - - // Governance participation helper - async function participateInGovernance( - proposalId: bigint, - vote: VoteOption, - depositAmount?: string - ) { - const actions = []; - - // Make deposit if specified - if (depositAmount) { - console.log(`Depositing ${depositAmount} SEI to proposal ${proposalId}`); - const depositTx = await depositToProposal(proposalId, depositAmount); - actions.push({ type: 'deposit', tx: depositTx }); - } - - // Cast vote - console.log(`Voting ${VoteOption[vote]} on proposal ${proposalId}`); - const voteTx = await voteOnProposal(proposalId, vote); - actions.push({ type: 'vote', tx: voteTx }); - - return actions; - } - - // Batch voting on multiple proposals - async function batchVote(votes: Array<{ proposalId: bigint; option: VoteOption }>) { - const votePromises = votes.map(({ proposalId, option }) => - voteOnProposal(proposalId, option) - ); - - return await Promise.all(votePromises); - } - - // Example usage - await participateInGovernance(42n, VoteOption.YES, "100"); - await batchVote([ - { proposalId: 43n, option: VoteOption.NO }, - { proposalId: 44n, option: VoteOption.ABSTAIN } - ]); - ``` - - - - ```typescript - import { ethers } from 'ethers'; - import { getGovernancePrecompileEthersContract } from '@sei-js/precompiles/ethers'; - - const provider = new ethers.JsonRpcProvider('https://evm-rpc-testnet.sei-apis.com'); - const signer = new ethers.Wallet('0x...', provider); - const governanceContract = getGovernancePrecompileEthersContract(provider); - - // Vote options enum - enum VoteOption { - YES = 1, - ABSTAIN = 2, - NO = 3, - NO_WITH_VETO = 4 - } - - // Cast a vote on a proposal - async function voteOnProposal(proposalId: number, option: VoteOption) { - const governanceWithSigner = governanceContract.connect(signer); - - const tx = await governanceWithSigner.vote(proposalId, option); - return await tx.wait(); - } - - // Make a deposit to a proposal - async function depositToProposal(proposalId: number, amount: string) { - const governanceWithSigner = governanceContract.connect(signer); - - const tx = await governanceWithSigner.deposit(proposalId, { - value: ethers.parseEther(amount) - }); - - return await tx.wait(); - } - - // Governance manager class - class GovernanceManager { - private contract: ethers.Contract; - private signer: ethers.Signer; - - constructor(provider: ethers.Provider, signer: ethers.Signer) { - this.contract = getGovernancePrecompileEthersContract(provider); - this.signer = signer; - } - - async vote(proposalId: number, option: VoteOption): Promise { - const contractWithSigner = this.contract.connect(this.signer); - const tx = await contractWithSigner.vote(proposalId, option); - return await tx.wait(); - } - - async deposit(proposalId: number, amount: string): Promise { - const contractWithSigner = this.contract.connect(this.signer); - const tx = await contractWithSigner.deposit(proposalId, { - value: ethers.parseEther(amount) - }); - return await tx.wait(); - } - - async voteWithDeposit( - proposalId: number, - option: VoteOption, - depositAmount: string - ): Promise<{ depositTx: ethers.TransactionReceipt; voteTx: ethers.TransactionReceipt }> { - const depositTx = await this.deposit(proposalId, depositAmount); - const voteTx = await this.vote(proposalId, option); - - return { depositTx, voteTx }; - } - } - - // Usage - const governance = new GovernanceManager(provider, signer); - - // Vote on a proposal - await governance.vote(42, VoteOption.YES); - - // Deposit and vote - await governance.voteWithDeposit(43, VoteOption.NO, "50"); - ``` - - - - ```typescript - import { - GOVERNANCE_PRECOMPILE_ABI, - GOVERNANCE_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles'; - - // Using with web3.js - import Web3 from 'web3'; - - const web3 = new Web3('https://evm-rpc-testnet.sei-apis.com'); - const governanceContract = new web3.eth.Contract( - GOVERNANCE_PRECOMPILE_ABI, - GOVERNANCE_PRECOMPILE_ADDRESS - ); - - // Setup account - const account = web3.eth.accounts.privateKeyToAccount('0x...'); - web3.eth.accounts.wallet.add(account); - - // Vote on proposal - const voteTx = await governanceContract.methods - .vote(42, 1) // Vote "Yes" on proposal 42 - .send({ - from: account.address, - gas: 100000 - }); - - // Deposit to proposal - const depositTx = await governanceContract.methods - .deposit(42) - .send({ - from: account.address, - value: web3.utils.toWei('100', 'ether'), // 100 SEI - gas: 100000 - }); - ``` - - - -## Vote Options Explained - -### 1. Yes (Option 1) -- **Purpose**: Support the proposal -- **Effect**: Counts toward proposal approval -- **When to use**: When you agree with the proposal - -### 2. Abstain (Option 2) -- **Purpose**: Neutral stance but participate in quorum -- **Effect**: Counts toward quorum but not for/against -- **When to use**: When you want to participate but have no strong opinion - -### 3. No (Option 3) -- **Purpose**: Oppose the proposal -- **Effect**: Counts against proposal approval -- **When to use**: When you disagree with the proposal - -### 4. NoWithVeto (Option 4) -- **Purpose**: Strong opposition with penalty implications -- **Effect**: Can cause proposal failure and deposit forfeiture -- **When to use**: When you believe the proposal is harmful or spam - -```typescript -// Helper function to get vote option description -function getVoteDescription(option: number): string { - switch (option) { - case 1: return "Yes - Support the proposal"; - case 2: return "Abstain - Neutral participation"; - case 3: return "No - Oppose the proposal"; - case 4: return "NoWithVeto - Strong opposition"; - default: return "Invalid vote option"; - } -} -``` - -## Common Use Cases - -### DAO Integration -- **Automated Voting**: Smart contracts can vote based on predetermined logic -- **Delegation Systems**: Allow token holders to delegate voting power -- **Proposal Support**: Automatically deposit to proposals meeting criteria - -### Community Governance -- **Voting Campaigns**: Coordinate community voting efforts -- **Proposal Funding**: Pool resources to support important proposals -- **Governance Analytics**: Track voting patterns and participation - -### Protocol Governance -- **Parameter Updates**: Vote on protocol parameter changes -- **Upgrade Proposals**: Participate in network upgrade decisions -- **Treasury Management**: Vote on treasury spending proposals - -## Governance Workflow - -### 1. Proposal Lifecycle -```typescript -// Typical governance proposal states: -enum ProposalStatus { - DEPOSIT_PERIOD = "deposit_period", // Accepting deposits - VOTING_PERIOD = "voting_period", // Active voting - PASSED = "passed", // Proposal approved - REJECTED = "rejected", // Proposal failed - FAILED = "failed" // Proposal failed due to veto -} -``` - -### 2. Participation Strategy -```typescript -async function smartGovernanceParticipation( - proposalId: bigint, - proposalType: string, - userPreferences: GovernancePreferences -) { - // Analyze proposal type and user preferences - const decision = analyzeProposal(proposalType, userPreferences); - - if (decision.shouldDeposit) { - await depositToProposal(proposalId, decision.depositAmount); - } - - if (decision.shouldVote) { - await voteOnProposal(proposalId, decision.voteOption); - } - - return decision; -} -``` - -## Governance Best Practices - -### Research Before Voting -- Read proposal details thoroughly -- Understand the implications of changes -- Consider long-term effects on the network - -### Deposit Considerations -- Deposits help proposals reach voting stage -- Failed proposals may result in deposit forfeiture -- Consider the proposal's likelihood of success - -### Vote Timing -- Vote early to signal community sentiment -- Monitor voting progress and participation -- Consider changing vote if new information emerges - -```typescript -// Governance participation tracker -class GovernanceTracker { - private votes: Map = new Map(); - private deposits: Map = new Map(); - - recordVote(proposalId: bigint, option: VoteOption) { - this.votes.set(proposalId, option); - } - - recordDeposit(proposalId: bigint, amount: string) { - this.deposits.set(proposalId, amount); - } - - getParticipationSummary() { - return { - totalVotes: this.votes.size, - totalDeposits: this.deposits.size, - voteBreakdown: this.getVoteBreakdown(), - totalDepositAmount: this.getTotalDepositAmount() - }; - } - - private getVoteBreakdown() { - const breakdown = { yes: 0, no: 0, abstain: 0, noWithVeto: 0 }; - for (const option of this.votes.values()) { - switch (option) { - case VoteOption.YES: breakdown.yes++; break; - case VoteOption.NO: breakdown.no++; break; - case VoteOption.ABSTAIN: breakdown.abstain++; break; - case VoteOption.NO_WITH_VETO: breakdown.noWithVeto++; break; - } - } - return breakdown; - } - - private getTotalDepositAmount(): string { - return Array.from(this.deposits.values()) - .reduce((total, amount) => total + parseFloat(amount), 0) - .toString(); - } -} -``` - -## Error Handling - -Common errors when using the Governance precompile: - -- **Invalid proposal ID**: Proposal doesn't exist -- **Voting period ended**: Cannot vote after voting period closes -- **Already voted**: Cannot change vote once cast -- **Insufficient deposit**: Deposit amount too small - -```typescript -async function safeVote(proposalId: bigint, option: VoteOption) { - try { - return await voteOnProposal(proposalId, option); - } catch (error) { - if (error.message.includes('proposal not found')) { - throw new Error(`Proposal ${proposalId} does not exist`); - } else if (error.message.includes('voting period ended')) { - throw new Error(`Voting period for proposal ${proposalId} has ended`); - } else if (error.message.includes('already voted')) { - throw new Error(`Already voted on proposal ${proposalId}`); - } else { - throw error; - } - } -} -``` - -## Related Precompiles - -- **[Bank](/precompiles/precompiles/bank)**: Check SEI balance before making deposits -- **[Staking](/precompiles/precompiles/staking)**: Voting power is based on staked tokens -- **[Distribution](/precompiles/precompiles/distribution)**: Claim rewards from governance participation diff --git a/docs/precompiles/precompiles/ibc.mdx b/docs/precompiles/precompiles/ibc.mdx deleted file mode 100644 index 3b8b489f5..000000000 --- a/docs/precompiles/precompiles/ibc.mdx +++ /dev/null @@ -1,708 +0,0 @@ ---- -title: 'IBC Precompile' -description: 'Transfer tokens across Cosmos chains using the Inter-Blockchain Communication (IBC) protocol through the IBC precompile contract' -icon: "arrow-right-arrow-left" ---- - -## Overview - -The IBC precompile enables cross-chain token transfers using the Inter-Blockchain Communication (IBC) protocol directly from EVM contracts. This allows seamless integration between Sei and other Cosmos SDK chains, enabling multi-chain DeFi applications and cross-chain asset management. - -**Contract Address:** `0x0000000000000000000000000000000000001009` - -## Key Features - -- **Cross-Chain Transfers**: Send tokens to any IBC-enabled Cosmos chain -- **Flexible Timeouts**: Set custom timeout parameters or use defaults -- **Memo Support**: Include arbitrary data with transfers -- **Multi-Asset Support**: Transfer any IBC-compatible token denomination - -## Available Functions - -### State-Changing Functions - - - - Transfer tokens to another chain via IBC with custom timeout parameters. - - **Parameters:** - - `toAddress` (string): Recipient address on destination chain - - `port` (string): IBC port identifier (usually "transfer") - - `channel` (string): IBC channel identifier (e.g., "channel-0") - - `denom` (string): Token denomination to transfer - - `amount` (uint256): Amount to transfer (in base units) - - `revisionNumber` (uint64): Timeout height revision number - - `revisionHeight` (uint64): Timeout height revision height - - `timeoutTimestamp` (uint64): Timeout timestamp (nanoseconds) - - `memo` (string): Optional memo data - - **Returns:** Success boolean - - ```typescript - const success = await ibcContract.transfer( - "cosmos1...", // Destination address - "transfer", // Port - "channel-0", // Channel - "usei", // Denomination - parseEther("100"), // Amount (100 SEI) - 1n, // Revision number - 1000000n, // Revision height - 0n, // Timeout timestamp (0 = no timeout) - "Cross-chain transfer" // Memo - ); - ``` - - - - Transfer tokens to another chain via IBC using default timeout parameters. - - **Parameters:** - - `toAddress` (string): Recipient address on destination chain - - `port` (string): IBC port identifier (usually "transfer") - - `channel` (string): IBC channel identifier - - `denom` (string): Token denomination to transfer - - `amount` (uint256): Amount to transfer (in base units) - - `memo` (string): Optional memo data - - **Returns:** Success boolean - - **Note:** Uses default timeout of 10 minutes from current time - - ```typescript - const success = await ibcContract.transferWithDefaultTimeout( - "cosmos1...", // Destination address - "transfer", // Port - "channel-0", // Channel - "usei", // Denomination - parseEther("50"), // Amount (50 SEI) - "Simple transfer" // Memo - ); - ``` - - - -## Usage Examples - - - - ```typescript - import { createPublicClient, createWalletClient, http, parseEther } from 'viem'; - import { privateKeyToAccount } from 'viem/accounts'; - import { - seiTestnet, - IBC_PRECOMPILE_ABI, - IBC_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles/viem'; - - const publicClient = createPublicClient({ - chain: seiTestnet, - transport: http() - }); - - const account = privateKeyToAccount('0x...'); - const walletClient = createWalletClient({ - account, - chain: seiTestnet, - transport: http() - }); - - // Common IBC channels and their destinations - const IBC_CHANNELS = { - OSMOSIS: 'channel-0', - COSMOS_HUB: 'channel-1', - JUNO: 'channel-2', - STARGAZE: 'channel-3' - } as const; - - // Transfer with default timeout (recommended for most use cases) - async function transferToChain( - destinationAddress: string, - channel: string, - denom: string, - amount: string, - memo: string = "" - ) { - const hash = await walletClient.writeContract({ - address: IBC_PRECOMPILE_ADDRESS, - abi: IBC_PRECOMPILE_ABI, - functionName: 'transferWithDefaultTimeout', - args: [ - destinationAddress, - "transfer", - channel, - denom, - parseEther(amount), - memo - ] - }); - - return await publicClient.waitForTransactionReceipt({ hash }); - } - - // Transfer with custom timeout - async function transferWithCustomTimeout( - destinationAddress: string, - channel: string, - denom: string, - amount: string, - timeoutMinutes: number = 10, - memo: string = "" - ) { - const currentTime = Math.floor(Date.now() / 1000); - const timeoutTimestamp = BigInt((currentTime + timeoutMinutes * 60) * 1_000_000_000); // Convert to nanoseconds - - const hash = await walletClient.writeContract({ - address: IBC_PRECOMPILE_ADDRESS, - abi: IBC_PRECOMPILE_ABI, - functionName: 'transfer', - args: [ - destinationAddress, - "transfer", - channel, - denom, - parseEther(amount), - 1n, // Revision number - 0n, // Revision height (0 = no height timeout) - timeoutTimestamp, - memo - ] - }); - - return await publicClient.waitForTransactionReceipt({ hash }); - } - - // Cross-chain DeFi helper - async function crossChainSwap( - destinationChain: keyof typeof IBC_CHANNELS, - destinationAddress: string, - amount: string, - swapMemo: string - ) { - const channel = IBC_CHANNELS[destinationChain]; - - console.log(`Initiating cross-chain swap to ${destinationChain}`); - console.log(`Channel: ${channel}, Amount: ${amount} SEI`); - - return await transferToChain( - destinationAddress, - channel, - "usei", - amount, - swapMemo - ); - } - - // Batch cross-chain transfers - async function batchTransfer( - transfers: Array<{ - destinationAddress: string; - channel: string; - denom: string; - amount: string; - memo?: string; - }> - ) { - const transferPromises = transfers.map(transfer => - transferToChain( - transfer.destinationAddress, - transfer.channel, - transfer.denom, - transfer.amount, - transfer.memo || "" - ) - ); - - return await Promise.all(transferPromises); - } - - // Multi-chain portfolio rebalancing - async function rebalancePortfolio( - rebalanceConfig: Array<{ - chain: keyof typeof IBC_CHANNELS; - targetAddress: string; - percentage: number; // Percentage of total balance - }>, - totalAmount: string - ) { - const totalAmountBN = parseFloat(totalAmount); - - const transfers = rebalanceConfig.map(config => ({ - destinationAddress: config.targetAddress, - channel: IBC_CHANNELS[config.chain], - denom: "usei", - amount: (totalAmountBN * config.percentage / 100).toString(), - memo: `Portfolio rebalancing - ${config.percentage}% to ${config.chain}` - })); - - return await batchTransfer(transfers); - } - - // Example usage - await crossChainSwap( - "OSMOSIS", - "osmo1...", - "100", - "=swap:uosmo:osmo1..." - ); - - await rebalancePortfolio([ - { chain: "OSMOSIS", targetAddress: "osmo1...", percentage: 40 }, - { chain: "COSMOS_HUB", targetAddress: "cosmos1...", percentage: 30 }, - { chain: "JUNO", targetAddress: "juno1...", percentage: 30 } - ], "1000"); - ``` - - - - ```typescript - import { ethers } from 'ethers'; - import { getIbcPrecompileEthersContract } from '@sei-js/precompiles/ethers'; - - const provider = new ethers.JsonRpcProvider('https://evm-rpc-testnet.sei-apis.com'); - const signer = new ethers.Wallet('0x...', provider); - const ibcContract = getIbcPrecompileEthersContract(provider); - - // Transfer with default timeout - async function transferToChain( - destinationAddress: string, - channel: string, - denom: string, - amount: string, - memo: string = "" - ) { - const ibcWithSigner = ibcContract.connect(signer); - - const tx = await ibcWithSigner.transferWithDefaultTimeout( - destinationAddress, - "transfer", - channel, - denom, - ethers.parseEther(amount), - memo - ); - - return await tx.wait(); - } - - // IBC transfer manager class - class IBCTransferManager { - private contract: ethers.Contract; - private signer: ethers.Signer; - - // Common chain configurations - private readonly CHAINS = { - OSMOSIS: { channel: 'channel-0', prefix: 'osmo' }, - COSMOS_HUB: { channel: 'channel-1', prefix: 'cosmos' }, - JUNO: { channel: 'channel-2', prefix: 'juno' }, - STARGAZE: { channel: 'channel-3', prefix: 'stars' } - }; - - constructor(provider: ethers.Provider, signer: ethers.Signer) { - this.contract = getIbcPrecompileEthersContract(provider); - this.signer = signer; - } - - async transferWithDefaults( - destinationAddress: string, - channel: string, - denom: string, - amount: string, - memo: string = "" - ): Promise { - const contractWithSigner = this.contract.connect(this.signer); - - const tx = await contractWithSigner.transferWithDefaultTimeout( - destinationAddress, - "transfer", - channel, - denom, - ethers.parseEther(amount), - memo - ); - - return await tx.wait(); - } - - async transferWithCustomTimeout( - destinationAddress: string, - channel: string, - denom: string, - amount: string, - timeoutMinutes: number, - memo: string = "" - ): Promise { - const contractWithSigner = this.contract.connect(this.signer); - - const currentTime = Math.floor(Date.now() / 1000); - const timeoutTimestamp = BigInt((currentTime + timeoutMinutes * 60) * 1_000_000_000); - - const tx = await contractWithSigner.transfer( - destinationAddress, - "transfer", - channel, - denom, - ethers.parseEther(amount), - 1n, // Revision number - 0n, // Revision height - timeoutTimestamp, - memo - ); - - return await tx.wait(); - } - - async transferToKnownChain( - chainName: keyof typeof this.CHAINS, - destinationAddress: string, - amount: string, - memo: string = "" - ): Promise { - const chainConfig = this.CHAINS[chainName]; - if (!chainConfig) { - throw new Error(`Unknown chain: ${chainName}`); - } - - return await this.transferWithDefaults( - destinationAddress, - chainConfig.channel, - "usei", - amount, - memo - ); - } - - // Validate destination address format - validateDestinationAddress(address: string, chainPrefix: string): boolean { - return address.startsWith(chainPrefix) && address.length >= 39; - } - - // Get estimated transfer time - getEstimatedTransferTime(chainName: keyof typeof this.CHAINS): string { - const times = { - OSMOSIS: "1-2 minutes", - COSMOS_HUB: "1-2 minutes", - JUNO: "1-2 minutes", - STARGAZE: "1-2 minutes" - }; - - return times[chainName] || "1-3 minutes"; - } - } - - // Usage - const ibcManager = new IBCTransferManager(provider, signer); - - // Transfer to Osmosis - await ibcManager.transferToKnownChain( - "OSMOSIS", - "osmo1...", - "100", - "DeFi farming" - ); - ``` - - - - ```typescript - import { - IBC_PRECOMPILE_ABI, - IBC_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles'; - - // Using with web3.js - import Web3 from 'web3'; - - const web3 = new Web3('https://evm-rpc-testnet.sei-apis.com'); - const ibcContract = new web3.eth.Contract( - IBC_PRECOMPILE_ABI, - IBC_PRECOMPILE_ADDRESS - ); - - // Setup account - const account = web3.eth.accounts.privateKeyToAccount('0x...'); - web3.eth.accounts.wallet.add(account); - - // Transfer with default timeout - const transferTx = await ibcContract.methods - .transferWithDefaultTimeout( - 'cosmos1...', // Destination address - 'transfer', // Port - 'channel-0', // Channel - 'usei', // Denomination - web3.utils.toWei('100', 'ether'), // Amount - 'Cross-chain transfer' // Memo - ) - .send({ - from: account.address, - gas: 300000 - }); - - // Transfer with custom timeout - const currentTime = Math.floor(Date.now() / 1000); - const timeoutTimestamp = (currentTime + 600) * 1_000_000_000; // 10 minutes - - const customTransferTx = await ibcContract.methods - .transfer( - 'cosmos1...', - 'transfer', - 'channel-0', - 'usei', - web3.utils.toWei('50', 'ether'), - 1, // Revision number - 0, // Revision height - timeoutTimestamp, - 'Custom timeout transfer' - ) - .send({ - from: account.address, - gas: 300000 - }); - ``` - - - -## IBC Channel Configuration - -### Common Sei IBC Channels - -| Chain | Channel ID | Destination Prefix | Transfer Time | -|-------|------------|-------------------|---------------| -| Osmosis | channel-0 | osmo | 1-2 minutes | -| Cosmos Hub | channel-1 | cosmos | 1-2 minutes | -| Juno | channel-2 | juno | 1-2 minutes | -| Stargaze | channel-3 | stars | 1-2 minutes | - -### Channel Discovery -```typescript -// Helper to validate channel and destination -function validateIBCTransfer( - channel: string, - destinationAddress: string, - expectedPrefix: string -) { - // Validate channel format - if (!channel.startsWith('channel-')) { - throw new Error('Invalid channel format. Must start with "channel-"'); - } - - // Validate destination address - if (!destinationAddress.startsWith(expectedPrefix)) { - throw new Error(`Invalid destination address. Must start with "${expectedPrefix}"`); - } - - // Validate address length (typical Cosmos address is 39-45 characters) - if (destinationAddress.length < 39 || destinationAddress.length > 45) { - throw new Error('Invalid destination address length'); - } - - return true; -} -``` - -## Common Use Cases - -### Cross-Chain DeFi -- **Yield Farming**: Transfer tokens to other chains for higher yields -- **Arbitrage**: Move assets between chains to exploit price differences -- **Liquidity Provision**: Provide liquidity on multiple DEXs across chains - -### Portfolio Management -- **Diversification**: Spread assets across multiple chains -- **Risk Management**: Move assets to safer chains during market volatility -- **Rebalancing**: Maintain target allocations across chains - -### Multi-Chain Applications -- **Cross-Chain Swaps**: Enable swaps between assets on different chains -- **Unified Wallets**: Manage assets across multiple chains from one interface -- **Cross-Chain Governance**: Participate in governance across multiple chains - -## Transfer Strategies - -### Timeout Management -```typescript -// Calculate appropriate timeout based on network conditions -function calculateOptimalTimeout( - destinationChain: string, - amount: string, - networkCongestion: 'low' | 'medium' | 'high' = 'medium' -): number { - const baseTimeout = 10; // 10 minutes base - - const congestionMultiplier = { - low: 1, - medium: 1.5, - high: 2 - }; - - const amountMultiplier = parseFloat(amount) > 1000 ? 1.2 : 1; // Extra time for large transfers - - return Math.ceil(baseTimeout * congestionMultiplier[networkCongestion] * amountMultiplier); -} -``` - -### Memo Optimization -```typescript -// Generate optimized memos for different use cases -function generateTransferMemo( - purpose: 'swap' | 'farming' | 'arbitrage' | 'general', - additionalData?: Record -): string { - const memos = { - swap: (data: any) => `=swap:${data.outputToken}:${data.recipient}`, - farming: (data: any) => `farm:${data.poolId}:${data.strategy}`, - arbitrage: (data: any) => `arb:${data.targetPrice}:${data.slippage}`, - general: (data: any) => data?.message || 'IBC transfer' - }; - - return memos[purpose](additionalData); -} -``` - -### Batch Transfer Optimization -```typescript -// Optimize batch transfers for gas efficiency -async function optimizedBatchTransfer( - transfers: Array<{ - destinationAddress: string; - channel: string; - denom: string; - amount: string; - memo?: string; - }>, - maxConcurrent: number = 3 -) { - // Group transfers by channel for efficiency - const transfersByChannel = transfers.reduce((acc, transfer) => { - if (!acc[transfer.channel]) acc[transfer.channel] = []; - acc[transfer.channel].push(transfer); - return acc; - }, {} as Record); - - // Process transfers in batches - const results = []; - for (const [channel, channelTransfers] of Object.entries(transfersByChannel)) { - for (let i = 0; i < channelTransfers.length; i += maxConcurrent) { - const batch = channelTransfers.slice(i, i + maxConcurrent); - const batchPromises = batch.map(transfer => - transferToChain( - transfer.destinationAddress, - transfer.channel, - transfer.denom, - transfer.amount, - transfer.memo - ) - ); - - const batchResults = await Promise.all(batchPromises); - results.push(...batchResults); - } - } - - return results; -} -``` - -## Error Handling - -Common errors when using the IBC precompile: - -- **Invalid channel**: Channel doesn't exist or is closed -- **Timeout expired**: Transfer took too long to complete -- **Insufficient balance**: Not enough tokens to transfer -- **Invalid destination**: Malformed destination address - -```typescript -async function safeIBCTransfer( - destinationAddress: string, - channel: string, - denom: string, - amount: string, - memo: string = "" -) { - try { - // Validate inputs - if (!destinationAddress || !channel || !denom || !amount) { - throw new Error('Missing required parameters'); - } - - // Validate channel format - if (!channel.startsWith('channel-')) { - throw new Error('Invalid channel format'); - } - - // Validate amount - if (parseFloat(amount) <= 0) { - throw new Error('Amount must be greater than 0'); - } - - return await transferToChain(destinationAddress, channel, denom, amount, memo); - } catch (error) { - if (error.message.includes('channel not found')) { - throw new Error(`IBC channel ${channel} not found or inactive`); - } else if (error.message.includes('insufficient funds')) { - throw new Error(`Insufficient ${denom} balance for transfer`); - } else if (error.message.includes('timeout')) { - throw new Error('Transfer timeout - try again with longer timeout'); - } else if (error.message.includes('invalid destination')) { - throw new Error('Invalid destination address format'); - } else { - throw error; - } - } -} -``` - -## Security Considerations - -### Address Validation -- Always validate destination addresses match the expected chain prefix -- Verify channel IDs are correct for the intended destination chain -- Double-check amounts and denominations before transfer - -### Timeout Management -- Use appropriate timeouts based on network conditions -- Consider using default timeouts for most transfers -- Monitor for failed transfers due to timeouts - -### Memo Security -- Avoid including sensitive information in memos -- Be cautious with automated memo generation -- Validate memo content for cross-chain applications - -```typescript -// Security validation helper -function validateTransferSecurity( - destinationAddress: string, - channel: string, - amount: string, - memo: string -): { valid: boolean; warnings: string[] } { - const warnings: string[] = []; - - // Check for common address typos - if (destinationAddress.includes('0x')) { - warnings.push('Destination address contains 0x - this may be an Ethereum address'); - } - - // Check for large transfers - if (parseFloat(amount) > 10000) { - warnings.push('Large transfer amount - please double-check'); - } - - // Check memo for sensitive data - if (memo.includes('private') || memo.includes('secret') || memo.includes('key')) { - warnings.push('Memo may contain sensitive information'); - } - - return { - valid: warnings.length === 0, - warnings - }; -} -``` - -## Related Precompiles - -- **[Bank](/precompiles/precompiles/bank)**: Check token balances before IBC transfers -- **[Address](/precompiles/precompiles/address)**: Convert between EVM and Cosmos addresses -- **[Oracle](/precompiles/precompiles/oracle)**: Get exchange rates for cross-chain arbitrage diff --git a/docs/precompiles/precompiles/json.mdx b/docs/precompiles/precompiles/json.mdx deleted file mode 100644 index bd82ff98b..000000000 --- a/docs/precompiles/precompiles/json.mdx +++ /dev/null @@ -1,712 +0,0 @@ ---- -title: 'JSON Precompile' -description: 'Parse and extract data from JSON responses using the JSON precompile contract for efficient on-chain data processing' -icon: "brackets-curly" ---- - -## Overview - -The JSON precompile provides efficient JSON parsing capabilities directly on-chain, allowing smart contracts to extract specific values from JSON data without complex string manipulation. This is particularly useful for processing API responses, oracle data, and structured data from external sources. - -**Contract Address:** `0x0000000000000000000000000000000000001003` - -## Key Features - -- **Efficient Parsing**: Gas-optimized JSON parsing on-chain -- **Type-Safe Extraction**: Extract data as specific types (bytes, uint256, arrays) -- **Key-Based Access**: Extract values using JSON key paths -- **Oracle Integration**: Process structured data from external APIs - -## Available Functions - -### View Functions - - - - Extract a value from JSON data as bytes. - - **Parameters:** - - `input` (bytes): The JSON data as bytes - - `key` (string): The JSON key path to extract - - **Returns:** The extracted value as bytes - - ```typescript - const jsonData = '{"price": "100.50", "symbol": "SEI"}'; - const jsonBytes = ethers.toUtf8Bytes(jsonData); - - const priceBytes = await jsonContract.extractAsBytes( - jsonBytes, - "price" - ); - - // Convert back to string - const price = ethers.toUtf8String(priceBytes); - console.log('Price:', price); // "100.50" - ``` - - - - Extract an array of values from JSON data as bytes array. - - **Parameters:** - - `input` (bytes): The JSON data as bytes - - `key` (string): The JSON key path to extract (must point to an array) - - **Returns:** Array of extracted values as bytes - - ```typescript - const jsonData = '{"validators": ["seivaloper1...", "seivaloper2..."]}'; - const jsonBytes = ethers.toUtf8Bytes(jsonData); - - const validatorBytes = await jsonContract.extractAsBytesList( - jsonBytes, - "validators" - ); - - // Convert bytes array to string array - const validators = validatorBytes.map(bytes => ethers.toUtf8String(bytes)); - console.log('Validators:', validators); - ``` - - - - Extract a numeric value from JSON data as uint256. - - **Parameters:** - - `input` (bytes): The JSON data as bytes - - `key` (string): The JSON key path to extract (must be numeric) - - **Returns:** The extracted value as uint256 - - ```typescript - const jsonData = '{"balance": "1000000000000000000", "decimals": 18}'; - const jsonBytes = ethers.toUtf8Bytes(jsonData); - - const balance = await jsonContract.extractAsUint256( - jsonBytes, - "balance" - ); - - const decimals = await jsonContract.extractAsUint256( - jsonBytes, - "decimals" - ); - - console.log('Balance:', formatEther(balance)); // "1.0" - console.log('Decimals:', decimals.toString()); // "18" - ``` - - - -## Usage Examples - - - - ```typescript - import { createPublicClient, http, formatEther, toHex } from 'viem'; - import { - seiTestnet, - JSON_PRECOMPILE_ABI, - JSON_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles/viem'; - - const publicClient = createPublicClient({ - chain: seiTestnet, - transport: http() - }); - - // Helper to convert string to bytes - function stringToBytes(str: string): `0x${string}` { - return toHex(new TextEncoder().encode(str)); - } - - // Helper to convert bytes to string - function bytesToString(bytes: `0x${string}`): string { - const uint8Array = new Uint8Array( - bytes.slice(2).match(/.{1,2}/g)?.map(byte => parseInt(byte, 16)) || [] - ); - return new TextDecoder().decode(uint8Array); - } - - // Extract string value from JSON - async function extractStringValue(jsonData: string, key: string): Promise { - const jsonBytes = stringToBytes(jsonData); - - const result = await publicClient.readContract({ - address: JSON_PRECOMPILE_ADDRESS, - abi: JSON_PRECOMPILE_ABI, - functionName: 'extractAsBytes', - args: [jsonBytes, key] - }); - - return bytesToString(result); - } - - // Extract numeric value from JSON - async function extractNumericValue(jsonData: string, key: string): Promise { - const jsonBytes = stringToBytes(jsonData); - - return await publicClient.readContract({ - address: JSON_PRECOMPILE_ADDRESS, - abi: JSON_PRECOMPILE_ABI, - functionName: 'extractAsUint256', - args: [jsonBytes, key] - }); - } - - // Extract array from JSON - async function extractArrayValue(jsonData: string, key: string): Promise { - const jsonBytes = stringToBytes(jsonData); - - const result = await publicClient.readContract({ - address: JSON_PRECOMPILE_ADDRESS, - abi: JSON_PRECOMPILE_ABI, - functionName: 'extractAsBytesList', - args: [jsonBytes, key] - }); - - return result.map(bytes => bytesToString(bytes)); - } - - // Oracle data processor - async function processOracleData(oracleResponse: string) { - // Example oracle response - const jsonData = `{ - "prices": { - "SEI": { - "usd": "0.45", - "change_24h": "5.2" - }, - "ATOM": { - "usd": "12.30", - "change_24h": "-2.1" - } - }, - "timestamp": "1640995200", - "source": "coingecko" - }`; - - // Extract individual values - const seiPrice = await extractStringValue(jsonData, "prices.SEI.usd"); - const atomPrice = await extractStringValue(jsonData, "prices.ATOM.usd"); - const timestamp = await extractNumericValue(jsonData, "timestamp"); - const source = await extractStringValue(jsonData, "source"); - - return { - prices: { - SEI: parseFloat(seiPrice), - ATOM: parseFloat(atomPrice) - }, - timestamp: Number(timestamp), - source - }; - } - - // DeFi price aggregator - async function aggregatePriceData(priceFeeds: string[]) { - const results = []; - - for (const feed of priceFeeds) { - try { - // Each feed is a JSON string with price data - const symbol = await extractStringValue(feed, "symbol"); - const price = await extractStringValue(feed, "price"); - const volume = await extractNumericValue(feed, "volume"); - const lastUpdate = await extractNumericValue(feed, "last_update"); - - results.push({ - symbol, - price: parseFloat(price), - volume: Number(volume), - lastUpdate: Number(lastUpdate) - }); - } catch (error) { - console.error('Failed to process price feed:', error); - } - } - - return results; - } - - // Multi-chain data processor - async function processMultiChainData(chainDataJson: string) { - // Extract chain information - const chainName = await extractStringValue(chainDataJson, "chain_name"); - const blockHeight = await extractNumericValue(chainDataJson, "block_height"); - const validators = await extractArrayValue(chainDataJson, "validators"); - const totalSupply = await extractNumericValue(chainDataJson, "total_supply"); - - return { - chainName, - blockHeight: Number(blockHeight), - validators, - totalSupply: formatEther(totalSupply) - }; - } - - // Configuration parser - async function parseProtocolConfig(configJson: string) { - const protocolName = await extractStringValue(configJson, "protocol_name"); - const version = await extractStringValue(configJson, "version"); - const maxSupply = await extractNumericValue(configJson, "max_supply"); - const features = await extractArrayValue(configJson, "features"); - const feeRate = await extractNumericValue(configJson, "fee_rate"); - - return { - protocolName, - version, - maxSupply: formatEther(maxSupply), - features, - feeRate: Number(feeRate) - }; - } - - // Example usage - const oracleData = await processOracleData('oracle_response'); - console.log('SEI Price:', oracleData.prices.SEI); - - const chainData = `{ - "chain_name": "Sei", - "block_height": "1000000", - "validators": ["seivaloper1...", "seivaloper2..."], - "total_supply": "1000000000000000000000000000" - }`; - - const processedData = await processMultiChainData(chainData); - console.log('Chain data:', processedData); - ``` - - - - ```typescript - import { ethers } from 'ethers'; - import { getJsonPrecompileEthersContract } from '@sei-js/precompiles/ethers'; - - const provider = new ethers.JsonRpcProvider('https://evm-rpc-testnet.sei-apis.com'); - const jsonContract = getJsonPrecompileEthersContract(provider); - - // Extract string value from JSON - async function extractStringValue(jsonData: string, key: string): Promise { - const jsonBytes = ethers.toUtf8Bytes(jsonData); - const result = await jsonContract.extractAsBytes(jsonBytes, key); - return ethers.toUtf8String(result); - } - - // Extract numeric value from JSON - async function extractNumericValue(jsonData: string, key: string): Promise { - const jsonBytes = ethers.toUtf8Bytes(jsonData); - return await jsonContract.extractAsUint256(jsonBytes, key); - } - - // Extract array from JSON - async function extractArrayValue(jsonData: string, key: string): Promise { - const jsonBytes = ethers.toUtf8Bytes(jsonData); - const result = await jsonContract.extractAsBytesList(jsonBytes, key); - return result.map(bytes => ethers.toUtf8String(bytes)); - } - - // JSON data processor class - class JSONDataProcessor { - private contract: ethers.Contract; - - constructor(provider: ethers.Provider) { - this.contract = getJsonPrecompileEthersContract(provider); - } - - async extractString(jsonData: string, key: string): Promise { - const jsonBytes = ethers.toUtf8Bytes(jsonData); - const result = await this.contract.extractAsBytes(jsonBytes, key); - return ethers.toUtf8String(result); - } - - async extractNumber(jsonData: string, key: string): Promise { - const jsonBytes = ethers.toUtf8Bytes(jsonData); - return await this.contract.extractAsUint256(jsonBytes, key); - } - - async extractArray(jsonData: string, key: string): Promise { - const jsonBytes = ethers.toUtf8Bytes(jsonData); - const result = await this.contract.extractAsBytesList(jsonBytes, key); - return result.map(bytes => ethers.toUtf8String(bytes)); - } - - // Process complex nested JSON - async processNestedData(jsonData: string, schema: Record) { - const results: Record = {}; - - for (const [field, keyPath] of Object.entries(schema)) { - try { - // Try to extract as string first - const stringValue = await this.extractString(jsonData, keyPath); - - // Check if it's a number - if (/^\d+(\.\d+)?$/.test(stringValue)) { - results[field] = parseFloat(stringValue); - } else { - results[field] = stringValue; - } - } catch { - try { - // Try to extract as number - const numberValue = await this.extractNumber(jsonData, keyPath); - results[field] = Number(numberValue); - } catch { - try { - // Try to extract as array - const arrayValue = await this.extractArray(jsonData, keyPath); - results[field] = arrayValue; - } catch (error) { - console.error(`Failed to extract ${field} from ${keyPath}:`, error); - results[field] = null; - } - } - } - } - - return results; - } - - // Validate JSON structure - async validateJsonStructure( - jsonData: string, - requiredFields: string[] - ): Promise<{ valid: boolean; missingFields: string[] }> { - const missingFields: string[] = []; - - for (const field of requiredFields) { - try { - await this.extractString(jsonData, field); - } catch { - try { - await this.extractNumber(jsonData, field); - } catch { - try { - await this.extractArray(jsonData, field); - } catch { - missingFields.push(field); - } - } - } - } - - return { - valid: missingFields.length === 0, - missingFields - }; - } - } - - // Usage - const processor = new JSONDataProcessor(provider); - - const jsonData = `{ - "token": { - "name": "Sei", - "symbol": "SEI", - "decimals": 18, - "total_supply": "1000000000000000000000000000" - }, - "price_data": { - "current_price": "0.45", - "market_cap": "450000000" - } - }`; - - // Extract token information - const tokenName = await processor.extractString(jsonData, "token.name"); - const tokenSymbol = await processor.extractString(jsonData, "token.symbol"); - const decimals = await processor.extractNumber(jsonData, "token.decimals"); - - console.log(`Token: ${tokenName} (${tokenSymbol}), Decimals: ${decimals}`); - ``` - - - - ```typescript - import { - JSON_PRECOMPILE_ABI, - JSON_PRECOMPILE_ADDRESS - } from '@sei-js/precompiles'; - - // Using with web3.js - import Web3 from 'web3'; - - const web3 = new Web3('https://evm-rpc-testnet.sei-apis.com'); - const jsonContract = new web3.eth.Contract( - JSON_PRECOMPILE_ABI, - JSON_PRECOMPILE_ADDRESS - ); - - // Extract string value - const jsonData = '{"price": "100.50", "symbol": "SEI"}'; - const jsonBytes = web3.utils.toHex(jsonData); - - const priceBytes = await jsonContract.methods - .extractAsBytes(jsonBytes, 'price') - .call(); - - const price = web3.utils.hexToUtf8(priceBytes); - console.log('Price:', price); - - // Extract numeric value - const balance = await jsonContract.methods - .extractAsUint256(jsonBytes, 'balance') - .call(); - - console.log('Balance:', balance); - - // Extract array - const arrayData = '{"validators": ["val1", "val2", "val3"]}'; - const arrayBytes = web3.utils.toHex(arrayData); - - const validatorBytes = await jsonContract.methods - .extractAsBytesList(arrayBytes, 'validators') - .call(); - - const validators = validatorBytes.map(bytes => web3.utils.hexToUtf8(bytes)); - console.log('Validators:', validators); - ``` - - - -## JSON Key Path Syntax - -### Simple Keys -```typescript -// For JSON: {"name": "Sei", "price": "0.45"} -const name = await extractStringValue(jsonData, "name"); -const price = await extractStringValue(jsonData, "price"); -``` - -### Nested Objects -```typescript -// For JSON: {"token": {"name": "Sei", "decimals": 18}} -const tokenName = await extractStringValue(jsonData, "token.name"); -const decimals = await extractNumericValue(jsonData, "token.decimals"); -``` - -### Array Access -```typescript -// For JSON: {"prices": ["0.45", "0.46", "0.44"]} -const allPrices = await extractArrayValue(jsonData, "prices"); - -// For JSON: {"validators": [{"name": "val1"}, {"name": "val2"}]} -const validatorNames = await extractArrayValue(jsonData, "validators.name"); -``` - -## Common Use Cases - -### Oracle Data Processing -- **Price Feeds**: Extract price data from oracle responses -- **Market Data**: Process trading volume, market cap, and other metrics -- **External APIs**: Parse responses from external data sources - -### DeFi Protocol Integration -- **Token Metadata**: Extract token information from registry responses -- **Pool Data**: Process liquidity pool information -- **Yield Data**: Extract APY and reward information - -### Cross-Chain Data -- **Chain State**: Process blockchain state information -- **Validator Data**: Extract validator sets and staking information -- **Transaction Data**: Parse complex transaction metadata - -## Data Processing Patterns - -### Type-Safe Extraction -```typescript -// Define data schema -interface TokenData { - name: string; - symbol: string; - decimals: number; - totalSupply: bigint; - holders: string[]; -} - -async function extractTokenData(jsonData: string): Promise { - return { - name: await extractStringValue(jsonData, "name"), - symbol: await extractStringValue(jsonData, "symbol"), - decimals: Number(await extractNumericValue(jsonData, "decimals")), - totalSupply: await extractNumericValue(jsonData, "total_supply"), - holders: await extractArrayValue(jsonData, "holders") - }; -} -``` - -### Batch Processing -```typescript -// Process multiple JSON objects efficiently -async function batchProcessJsonData(jsonDataArray: string[], keyPath: string) { - const extractPromises = jsonDataArray.map(jsonData => - extractStringValue(jsonData, keyPath) - ); - - return await Promise.all(extractPromises); -} -``` - -### Error-Resilient Parsing -```typescript -async function safeExtractValue( - jsonData: string, - key: string, - defaultValue: any = null -): Promise { - try { - // Try string extraction first - return await extractStringValue(jsonData, key); - } catch { - try { - // Try numeric extraction - return await extractNumericValue(jsonData, key); - } catch { - try { - // Try array extraction - return await extractArrayValue(jsonData, key); - } catch { - return defaultValue; - } - } - } -} -``` - -## Performance Optimization - -### Efficient Data Extraction -```typescript -// Cache frequently accessed data -class JSONCache { - private cache = new Map(); - - async getCachedValue(jsonData: string, key: string, extractor: Function) { - const cacheKey = `${jsonData.slice(0, 100)}-${key}`; - - if (this.cache.has(cacheKey)) { - return this.cache.get(cacheKey); - } - - const value = await extractor(jsonData, key); - this.cache.set(cacheKey, value); - - return value; - } -} -``` - -### Batch Key Extraction -```typescript -// Extract multiple keys in parallel -async function extractMultipleKeys( - jsonData: string, - keys: Array<{ key: string; type: 'string' | 'number' | 'array' }> -) { - const extractPromises = keys.map(async ({ key, type }) => { - switch (type) { - case 'string': - return { key, value: await extractStringValue(jsonData, key) }; - case 'number': - return { key, value: await extractNumericValue(jsonData, key) }; - case 'array': - return { key, value: await extractArrayValue(jsonData, key) }; - default: - throw new Error(`Unknown type: ${type}`); - } - }); - - const results = await Promise.all(extractPromises); - - return results.reduce((acc, { key, value }) => { - acc[key] = value; - return acc; - }, {} as Record); -} -``` - -## Error Handling - -Common errors when using the JSON precompile: - -- **Invalid JSON**: Malformed JSON data -- **Key not found**: Specified key doesn't exist in JSON -- **Type mismatch**: Trying to extract wrong data type -- **Invalid key path**: Malformed key path syntax - -```typescript -async function safeJsonExtraction( - jsonData: string, - key: string, - expectedType: 'string' | 'number' | 'array' -) { - try { - // Validate JSON format first - JSON.parse(jsonData); // This will throw if invalid - - switch (expectedType) { - case 'string': - return await extractStringValue(jsonData, key); - case 'number': - return await extractNumericValue(jsonData, key); - case 'array': - return await extractArrayValue(jsonData, key); - default: - throw new Error(`Unsupported type: ${expectedType}`); - } - } catch (error) { - if (error.message.includes('JSON')) { - throw new Error('Invalid JSON format'); - } else if (error.message.includes('key not found')) { - throw new Error(`Key "${key}" not found in JSON data`); - } else if (error.message.includes('type mismatch')) { - throw new Error(`Type mismatch: expected ${expectedType} for key "${key}"`); - } else { - throw error; - } - } -} -``` - -## Security Considerations - -### Input Validation -- Always validate JSON data before processing -- Sanitize key paths to prevent injection attacks -- Limit JSON data size to prevent DoS attacks - -### Data Integrity -- Verify data sources and authenticity -- Implement checksums for critical data -- Use multiple data sources for validation - -```typescript -// Security validation helper -function validateJsonInput(jsonData: string, maxSize: number = 10000): boolean { - // Check size limit - if (jsonData.length > maxSize) { - throw new Error('JSON data exceeds size limit'); - } - - // Validate JSON format - try { - JSON.parse(jsonData); - } catch { - throw new Error('Invalid JSON format'); - } - - // Check for potential security issues - if (jsonData.includes('