@sodax/skills 2.0.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +13 -0
- package/AGENTS.md +81 -0
- package/LICENSE +21 -0
- package/README.md +49 -0
- package/knowledge/dapp-kit/AGENTS.md +50 -0
- package/knowledge/dapp-kit/integration/README.md +49 -0
- package/knowledge/dapp-kit/integration/ai-rules.md +80 -0
- package/knowledge/dapp-kit/integration/architecture.md +276 -0
- package/knowledge/dapp-kit/integration/features/README.md +29 -0
- package/knowledge/dapp-kit/integration/features/auxiliary-services.md +169 -0
- package/knowledge/dapp-kit/integration/features/bitcoin.md +87 -0
- package/knowledge/dapp-kit/integration/features/bridge.md +91 -0
- package/knowledge/dapp-kit/integration/features/dex.md +152 -0
- package/knowledge/dapp-kit/integration/features/migration.md +118 -0
- package/knowledge/dapp-kit/integration/features/money-market.md +144 -0
- package/knowledge/dapp-kit/integration/features/staking.md +123 -0
- package/knowledge/dapp-kit/integration/features/swap.md +101 -0
- package/knowledge/dapp-kit/integration/quickstart.md +188 -0
- package/knowledge/dapp-kit/integration/recipes/README.md +136 -0
- package/knowledge/dapp-kit/integration/recipes/backend-queries.md +157 -0
- package/knowledge/dapp-kit/integration/recipes/bitcoin.md +193 -0
- package/knowledge/dapp-kit/integration/recipes/bridge.md +174 -0
- package/knowledge/dapp-kit/integration/recipes/dex.md +204 -0
- package/knowledge/dapp-kit/integration/recipes/invalidations.md +115 -0
- package/knowledge/dapp-kit/integration/recipes/migration.md +212 -0
- package/knowledge/dapp-kit/integration/recipes/money-market.md +207 -0
- package/knowledge/dapp-kit/integration/recipes/mutation-error-handling.md +118 -0
- package/knowledge/dapp-kit/integration/recipes/observability.md +93 -0
- package/knowledge/dapp-kit/integration/recipes/setup.md +168 -0
- package/knowledge/dapp-kit/integration/recipes/staking.md +202 -0
- package/knowledge/dapp-kit/integration/recipes/swap.md +272 -0
- package/knowledge/dapp-kit/integration/recipes/wallet-connectivity.md +128 -0
- package/knowledge/dapp-kit/integration/reference/README.md +12 -0
- package/knowledge/dapp-kit/integration/reference/glossary.md +190 -0
- package/knowledge/dapp-kit/integration/reference/hooks-index.md +190 -0
- package/knowledge/dapp-kit/integration/reference/public-api.md +110 -0
- package/knowledge/dapp-kit/integration/reference/querykey-conventions.md +179 -0
- package/knowledge/dapp-kit/migration/README.md +60 -0
- package/knowledge/dapp-kit/migration/ai-rules.md +81 -0
- package/knowledge/dapp-kit/migration/breaking-changes/hook-signatures.md +233 -0
- package/knowledge/dapp-kit/migration/breaking-changes/querykey-conventions.md +108 -0
- package/knowledge/dapp-kit/migration/breaking-changes/result-handling.md +211 -0
- package/knowledge/dapp-kit/migration/breaking-changes/sdk-leakage.md +167 -0
- package/knowledge/dapp-kit/migration/checklist.md +89 -0
- package/knowledge/dapp-kit/migration/features/README.md +34 -0
- package/knowledge/dapp-kit/migration/features/auxiliary-services.md +114 -0
- package/knowledge/dapp-kit/migration/features/bitcoin.md +88 -0
- package/knowledge/dapp-kit/migration/features/bridge.md +160 -0
- package/knowledge/dapp-kit/migration/features/dex.md +101 -0
- package/knowledge/dapp-kit/migration/features/migration.md +120 -0
- package/knowledge/dapp-kit/migration/features/money-market.md +139 -0
- package/knowledge/dapp-kit/migration/features/staking.md +109 -0
- package/knowledge/dapp-kit/migration/features/swap.md +133 -0
- package/knowledge/dapp-kit/migration/recipes.md +185 -0
- package/knowledge/dapp-kit/migration/reference/README.md +15 -0
- package/knowledge/dapp-kit/migration/reference/deleted-hooks.md +110 -0
- package/knowledge/dapp-kit/migration/reference/error-shape-crosswalk.md +144 -0
- package/knowledge/dapp-kit/migration/reference/renamed-hooks.md +68 -0
- package/knowledge/sdk/AGENTS.md +41 -0
- package/knowledge/sdk/integration/README.md +41 -0
- package/knowledge/sdk/integration/ai-rules.md +75 -0
- package/knowledge/sdk/integration/architecture.md +533 -0
- package/knowledge/sdk/integration/chain-specifics.md +189 -0
- package/knowledge/sdk/integration/features/README.md +19 -0
- package/knowledge/sdk/integration/features/auxiliary-services.md +189 -0
- package/knowledge/sdk/integration/features/bridge.md +136 -0
- package/knowledge/sdk/integration/features/dex.md +182 -0
- package/knowledge/sdk/integration/features/icx-bnusd-baln.md +181 -0
- package/knowledge/sdk/integration/features/money-market.md +198 -0
- package/knowledge/sdk/integration/features/staking.md +166 -0
- package/knowledge/sdk/integration/features/swap.md +207 -0
- package/knowledge/sdk/integration/quickstart.md +213 -0
- package/knowledge/sdk/integration/recipes/README.md +21 -0
- package/knowledge/sdk/integration/recipes/backend-server-init.md +69 -0
- package/knowledge/sdk/integration/recipes/chain-key-narrowing.md +65 -0
- package/knowledge/sdk/integration/recipes/gas-estimation.md +33 -0
- package/knowledge/sdk/integration/recipes/initialize-sodax.md +78 -0
- package/knowledge/sdk/integration/recipes/raw-tx-flow.md +71 -0
- package/knowledge/sdk/integration/recipes/result-and-errors.md +104 -0
- package/knowledge/sdk/integration/recipes/signed-tx-flow.md +46 -0
- package/knowledge/sdk/integration/recipes/testing.md +101 -0
- package/knowledge/sdk/integration/reference/README.md +18 -0
- package/knowledge/sdk/integration/reference/chain-keys.md +67 -0
- package/knowledge/sdk/integration/reference/error-codes.md +165 -0
- package/knowledge/sdk/integration/reference/glossary.md +32 -0
- package/knowledge/sdk/integration/reference/public-api.md +138 -0
- package/knowledge/sdk/integration/reference/wallet-providers.md +62 -0
- package/knowledge/sdk/migration/README.md +58 -0
- package/knowledge/sdk/migration/ai-rules.md +80 -0
- package/knowledge/sdk/migration/breaking-changes/architecture.md +344 -0
- package/knowledge/sdk/migration/breaking-changes/result-and-errors.md +363 -0
- package/knowledge/sdk/migration/breaking-changes/type-system.md +341 -0
- package/knowledge/sdk/migration/checklist.md +67 -0
- package/knowledge/sdk/migration/features/README.md +35 -0
- package/knowledge/sdk/migration/features/auxiliary-services.md +156 -0
- package/knowledge/sdk/migration/features/bridge.md +128 -0
- package/knowledge/sdk/migration/features/dex.md +143 -0
- package/knowledge/sdk/migration/features/icx-bnusd-baln.md +151 -0
- package/knowledge/sdk/migration/features/money-market.md +214 -0
- package/knowledge/sdk/migration/features/staking.md +138 -0
- package/knowledge/sdk/migration/features/swap.md +198 -0
- package/knowledge/sdk/migration/recipes.md +350 -0
- package/knowledge/sdk/migration/reference/README.md +18 -0
- package/knowledge/sdk/migration/reference/deleted-exports.md +127 -0
- package/knowledge/sdk/migration/reference/error-code-crosswalk.md +104 -0
- package/knowledge/sdk/migration/reference/return-shapes.md +49 -0
- package/knowledge/sdk/migration/reference/sodax-config.md +145 -0
- package/knowledge/wallet-sdk-core/AGENTS.md +43 -0
- package/knowledge/wallet-sdk-core/integration/README.md +108 -0
- package/knowledge/wallet-sdk-core/integration/ai-rules.md +141 -0
- package/knowledge/wallet-sdk-core/integration/architecture.md +212 -0
- package/knowledge/wallet-sdk-core/integration/features/README.md +22 -0
- package/knowledge/wallet-sdk-core/integration/features/bitcoin.md +103 -0
- package/knowledge/wallet-sdk-core/integration/features/evm.md +102 -0
- package/knowledge/wallet-sdk-core/integration/features/icon.md +88 -0
- package/knowledge/wallet-sdk-core/integration/features/injective.md +92 -0
- package/knowledge/wallet-sdk-core/integration/features/near.md +92 -0
- package/knowledge/wallet-sdk-core/integration/features/solana.md +104 -0
- package/knowledge/wallet-sdk-core/integration/features/stacks.md +91 -0
- package/knowledge/wallet-sdk-core/integration/features/stellar.md +95 -0
- package/knowledge/wallet-sdk-core/integration/features/sui.md +96 -0
- package/knowledge/wallet-sdk-core/integration/quickstart.md +259 -0
- package/knowledge/wallet-sdk-core/integration/recipes/README.md +15 -0
- package/knowledge/wallet-sdk-core/integration/recipes/bridge-to-sdk.md +145 -0
- package/knowledge/wallet-sdk-core/integration/recipes/defaults-and-overrides.md +159 -0
- package/knowledge/wallet-sdk-core/integration/recipes/library-exports.md +129 -0
- package/knowledge/wallet-sdk-core/integration/recipes/setup-browser-extension.md +137 -0
- package/knowledge/wallet-sdk-core/integration/recipes/setup-private-key.md +115 -0
- package/knowledge/wallet-sdk-core/integration/recipes/sign-and-broadcast.md +201 -0
- package/knowledge/wallet-sdk-core/integration/recipes/testing.md +163 -0
- package/knowledge/wallet-sdk-core/integration/reference/README.md +13 -0
- package/knowledge/wallet-sdk-core/integration/reference/chain-support.md +65 -0
- package/knowledge/wallet-sdk-core/integration/reference/glossary.md +28 -0
- package/knowledge/wallet-sdk-core/integration/reference/interfaces.md +131 -0
- package/knowledge/wallet-sdk-core/integration/reference/provider-classes.md +54 -0
- package/knowledge/wallet-sdk-core/integration/reference/public-api.md +128 -0
- package/knowledge/wallet-sdk-core/migration/README.md +84 -0
- package/knowledge/wallet-sdk-core/migration/ai-rules.md +139 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/README.md +14 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/base-wallet-provider.md +52 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/defaults-config.md +57 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/folder-layout.md +99 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/library-exports.md +58 -0
- package/knowledge/wallet-sdk-core/migration/checklist.md +62 -0
- package/knowledge/wallet-sdk-core/migration/recipes/README.md +12 -0
- package/knowledge/wallet-sdk-core/migration/recipes/adopt-defaults.md +84 -0
- package/knowledge/wallet-sdk-core/migration/recipes/adopt-library-exports.md +99 -0
- package/knowledge/wallet-sdk-core/migration/reference/README.md +12 -0
- package/knowledge/wallet-sdk-core/migration/reference/added-fields.md +71 -0
- package/knowledge/wallet-sdk-core/migration/reference/deleted-exports.md +35 -0
- package/knowledge/wallet-sdk-core/migration/reference/renamed-symbols.md +31 -0
- package/knowledge/wallet-sdk-core/migration/reference/return-shapes.md +23 -0
- package/knowledge/wallet-sdk-react/AGENTS.md +46 -0
- package/knowledge/wallet-sdk-react/integration/README.md +103 -0
- package/knowledge/wallet-sdk-react/integration/ai-rules.md +136 -0
- package/knowledge/wallet-sdk-react/integration/architecture.md +185 -0
- package/knowledge/wallet-sdk-react/integration/examples/01-minimal-evm.tsx +75 -0
- package/knowledge/wallet-sdk-react/integration/examples/02-multi-chain-modal.tsx +169 -0
- package/knowledge/wallet-sdk-react/integration/examples/03-nextjs-app-router.tsx +99 -0
- package/knowledge/wallet-sdk-react/integration/examples/04-walletconnect-setup.tsx +89 -0
- package/knowledge/wallet-sdk-react/integration/examples/README.md +29 -0
- package/knowledge/wallet-sdk-react/integration/recipes/batch-operations.md +224 -0
- package/knowledge/wallet-sdk-react/integration/recipes/bridge-to-sdk.md +165 -0
- package/knowledge/wallet-sdk-react/integration/recipes/chain-detection.md +259 -0
- package/knowledge/wallet-sdk-react/integration/recipes/connect-button.md +159 -0
- package/knowledge/wallet-sdk-react/integration/recipes/multi-chain-modal.md +203 -0
- package/knowledge/wallet-sdk-react/integration/recipes/setup.md +163 -0
- package/knowledge/wallet-sdk-react/integration/recipes/sign-message.md +138 -0
- package/knowledge/wallet-sdk-react/integration/recipes/sub-path-imports.md +97 -0
- package/knowledge/wallet-sdk-react/integration/recipes/switch-chain.md +144 -0
- package/knowledge/wallet-sdk-react/integration/recipes/walletconnect-setup.md +139 -0
- package/knowledge/wallet-sdk-react/integration/reference/api-surface.md +176 -0
- package/knowledge/wallet-sdk-react/integration/reference/chain-support.md +79 -0
- package/knowledge/wallet-sdk-react/integration/reference/connectors.md +75 -0
- package/knowledge/wallet-sdk-react/integration/reference/hooks.md +212 -0
- package/knowledge/wallet-sdk-react/integration/reference/wallet-brands.md +107 -0
- package/knowledge/wallet-sdk-react/migration/README.md +49 -0
- package/knowledge/wallet-sdk-react/migration/ai-rules.md +144 -0
- package/knowledge/wallet-sdk-react/migration/breaking-changes.md +310 -0
- package/knowledge/wallet-sdk-react/migration/checklist.md +159 -0
- package/knowledge/wallet-sdk-react/migration/recipes/connect-button.md +170 -0
- package/knowledge/wallet-sdk-react/migration/recipes/multi-chain-modal.md +245 -0
- package/knowledge/wallet-sdk-react/migration/recipes/ssr-setup.md +165 -0
- package/knowledge/wallet-sdk-react/migration/recipes/walletconnect-migration.md +170 -0
- package/knowledge/wallet-sdk-react/migration/reference/components.md +75 -0
- package/knowledge/wallet-sdk-react/migration/reference/config.md +339 -0
- package/knowledge/wallet-sdk-react/migration/reference/hooks.md +336 -0
- package/knowledge/wallet-sdk-react/migration/reference/imports.md +158 -0
- package/package.json +59 -0
- package/skills/sodax-dapp-kit-integration/SKILL.md +71 -0
- package/skills/sodax-dapp-kit-migration/SKILL.md +58 -0
- package/skills/sodax-sdk-integration/SKILL.md +66 -0
- package/skills/sodax-sdk-migration/SKILL.md +75 -0
- package/skills/sodax-wallet-sdk-core-integration/SKILL.md +55 -0
- package/skills/sodax-wallet-sdk-core-migration/SKILL.md +56 -0
- package/skills/sodax-wallet-sdk-react-integration/SKILL.md +80 -0
- package/skills/sodax-wallet-sdk-react-migration/SKILL.md +71 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sodax-skills",
|
|
3
|
+
"skills": [
|
|
4
|
+
"./skills/sodax-sdk-migration",
|
|
5
|
+
"./skills/sodax-sdk-integration",
|
|
6
|
+
"./skills/sodax-wallet-sdk-core-migration",
|
|
7
|
+
"./skills/sodax-wallet-sdk-core-integration",
|
|
8
|
+
"./skills/sodax-wallet-sdk-react-migration",
|
|
9
|
+
"./skills/sodax-wallet-sdk-react-integration",
|
|
10
|
+
"./skills/sodax-dapp-kit-migration",
|
|
11
|
+
"./skills/sodax-dapp-kit-integration"
|
|
12
|
+
]
|
|
13
|
+
}
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# AGENTS.md — `@sodax/skills` router
|
|
2
|
+
|
|
3
|
+
> Tool-neutral entry point. You are looking at the consumer-facing AI material for the `@sodax/*` SDKs. If you can read multiple `SKILL.md` files, load **2–3 skills** based on what the user is building (table below). Then follow each skill's internal workflow.
|
|
4
|
+
|
|
5
|
+
## What's here
|
|
6
|
+
|
|
7
|
+
This package ships **eight skills** (`skills/<name>/SKILL.md`) and a **knowledge** tree (`knowledge/<pkg>/<mode>/`) split per SODAX package. Skills are action-oriented: when to use, workflow, anti-patterns, links into knowledge. Knowledge is the reference material your workflow points at.
|
|
8
|
+
|
|
9
|
+
| SDK package | Skill (write new code) | Skill (port v1 → v2) |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `@sodax/sdk` | `sodax-sdk-integration` | `sodax-sdk-migration` |
|
|
12
|
+
| `@sodax/wallet-sdk-core` | `sodax-wallet-sdk-core-integration` | `sodax-wallet-sdk-core-migration` |
|
|
13
|
+
| `@sodax/wallet-sdk-react` | `sodax-wallet-sdk-react-integration` | `sodax-wallet-sdk-react-migration` |
|
|
14
|
+
| `@sodax/dapp-kit` | `sodax-dapp-kit-integration` | `sodax-dapp-kit-migration` |
|
|
15
|
+
|
|
16
|
+
> **What about `@sodax/types`?** No skill. The package has no consumer-facing surface — it's pure TypeScript types, re-exported through `@sodax/sdk`. Importing `@sodax/types` directly invites version skew. The SDK skills cover all `@sodax/types` symbols you need.
|
|
17
|
+
|
|
18
|
+
## Route by consumer intent
|
|
19
|
+
|
|
20
|
+
Pick the consumer's situation, load the listed skills in order:
|
|
21
|
+
|
|
22
|
+
| Consumer is… | Load skills |
|
|
23
|
+
|---|---|
|
|
24
|
+
| **Building a NEW React dapp** | `sodax-wallet-sdk-react-integration` → `sodax-dapp-kit-integration` → (`sodax-sdk-integration` only if dropping below dapp-kit) |
|
|
25
|
+
| **Building a NEW React app, no dapp-kit** (calling the SDK directly) | `sodax-wallet-sdk-react-integration` → `sodax-sdk-integration` |
|
|
26
|
+
| **Building a NEW Node / backend service or script** | `sodax-sdk-integration` → `sodax-wallet-sdk-core-integration` (only if it signs) |
|
|
27
|
+
| **Building a NEW non-React browser flow** | `sodax-wallet-sdk-core-integration` → `sodax-sdk-integration` |
|
|
28
|
+
| **Porting an EXISTING v1 React dapp** | `sodax-wallet-sdk-react-migration` → `sodax-dapp-kit-migration` → `sodax-sdk-migration` (then the matching `*-integration` skills for any new code) |
|
|
29
|
+
| **Porting an EXISTING v1 backend** | `sodax-sdk-migration` → `sodax-wallet-sdk-core-migration` (often no-op — additive only) |
|
|
30
|
+
|
|
31
|
+
If you don't know which situation applies, **ask the user** rather than guessing. Two signals to listen for:
|
|
32
|
+
|
|
33
|
+
- "Migrate / upgrade / port" + v1 fingerprints (`useSpokeProvider`, `*_MAINNET_CHAIN_ID`, `xChainId`, `useXWagmiStore`, `MoneyMarketError`/`IntentError`/etc.) → migration first.
|
|
34
|
+
- "Add / build / integrate" + no existing SODAX code → integration only.
|
|
35
|
+
|
|
36
|
+
If both: do migration first. Stale v1 patterns leak into new code if you skip it.
|
|
37
|
+
|
|
38
|
+
## How to use a skill
|
|
39
|
+
|
|
40
|
+
Each `SKILL.md` is short on purpose. Follow it like a procedure:
|
|
41
|
+
|
|
42
|
+
1. The skill's frontmatter `description` tells you the trigger conditions.
|
|
43
|
+
2. The body's **Workflow** section links into knowledge files. Read them in order — token budgets are sized so the right 2–3 files fit in your context.
|
|
44
|
+
3. The **Top traps** + **Conventions** sections are the consolidated DO / DO NOT list. Skipping them is the most common cause of generating v1 code.
|
|
45
|
+
4. The **Verification** section is the done-criteria. Run those checks before reporting the task complete.
|
|
46
|
+
|
|
47
|
+
## Layout reference
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
packages/skills/
|
|
51
|
+
├── AGENTS.md # You are here
|
|
52
|
+
├── .claude-plugin/plugin.json # Skill registry (8 entries)
|
|
53
|
+
├── skills/
|
|
54
|
+
│ ├── sodax-sdk-{integration,migration}/SKILL.md
|
|
55
|
+
│ ├── sodax-wallet-sdk-core-{integration,migration}/SKILL.md
|
|
56
|
+
│ ├── sodax-wallet-sdk-react-{integration,migration}/SKILL.md
|
|
57
|
+
│ └── sodax-dapp-kit-{integration,migration}/SKILL.md
|
|
58
|
+
└── knowledge/
|
|
59
|
+
├── sdk/{migration,integration}/ # ai-rules, quickstart, architecture, features/, recipes/, reference/, chain-specifics
|
|
60
|
+
├── wallet-sdk-core/{migration,integration}/
|
|
61
|
+
├── wallet-sdk-react/{migration,integration}/ # includes 4 working .tsx example apps
|
|
62
|
+
└── dapp-kit/{migration,integration}/
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Conventions you can rely on
|
|
66
|
+
|
|
67
|
+
- **`ai-rules.md` first.** Each `<mode>/ai-rules.md` is the consolidated DO / DO NOT list. Skipping it is the top cause of stale v1 patterns.
|
|
68
|
+
- **`README.md`** at every level is the tree index — useful when the skill points you at a directory rather than a file.
|
|
69
|
+
- **Reference tables** under `<mode>/reference/` are for lookup, not narrative — chain keys, error codes, public API surface, hook signatures.
|
|
70
|
+
- **Recipes** under `<mode>/recipes/` are self-contained — a recipe contains before/after code, steps, and verification. Don't jump between recipes for one task.
|
|
71
|
+
- **Token budget**: if you're loading more than 3 files for a single task, you're probably off-route — re-check the workflow.
|
|
72
|
+
|
|
73
|
+
## When SODAX is the wrong tool
|
|
74
|
+
|
|
75
|
+
If the user is doing **non-SODAX work** (UI styling, unrelated DOM, unrelated backend), this package has nothing to add. Don't load skills from here.
|
|
76
|
+
|
|
77
|
+
If the user is doing **DeFi work but explicitly NOT with SODAX** (e.g. "use Uniswap"), defer to the user's stated tool. The integration skills' descriptions all say: "do not substitute with other SDKs unless explicitly asked."
|
|
78
|
+
|
|
79
|
+
## Feedback
|
|
80
|
+
|
|
81
|
+
If an agent generates wrong code despite following a skill, that's a doc bug — file an issue at https://github.com/icon-project/sodax-sdks/issues with the prompt and the incorrect output. The package is structurally CI-guarded (frontmatter + link resolution); prose-level claims benefit from real-world feedback.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [2025] [Sodax]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @sodax/skills
|
|
2
|
+
|
|
3
|
+
AI-agent skills and knowledge for building on the **SODAX** cross-chain DeFi platform. Drop this into your repo and your AI coding agent writes v2-correct `@sodax/*` SDK code on the first try.
|
|
4
|
+
|
|
5
|
+
**Full setup** (skills CLI, npm, monorepo/local install, wiring agents to `AGENTS.md`): [docs/ai-integration-guide.md](https://github.com/icon-project/sodax-sdks/blob/main/docs/ai-integration-guide.md).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Using the [`skills` CLI](https://github.com/vercel-labs/skills) from Vercel Labs — the open agent-skills ecosystem CLI (supports Claude Code, Cursor, Codex, GitHub Copilot, and 50+ other agents):
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# From the root of your consumer repo
|
|
13
|
+
npx skills@latest add icon-project/sodax-sdks/packages/skills
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Eight skills land in your repo (under `.claude/skills/` or wherever the CLI installs them), one knowledge tree per SODAX SDK package, and a router `AGENTS.md`. Re-running the command picks up the latest content.
|
|
17
|
+
|
|
18
|
+
> **npm fallback** (web chats or when you prefer a devDependency): `pnpm add -D @sodax/skills`, then point your agent at `node_modules/@sodax/skills/AGENTS.md`. See the [integration guide](https://github.com/icon-project/sodax-sdks/blob/main/docs/ai-integration-guide.md#wire-your-agent).
|
|
19
|
+
|
|
20
|
+
## What you get
|
|
21
|
+
|
|
22
|
+
| Bundle | Contains |
|
|
23
|
+
|---|---|
|
|
24
|
+
| **8 skills** under `skills/sodax-<pkg>-<mode>/SKILL.md` | One skill per (package, mode). `<pkg>` ∈ `sdk`, `wallet-sdk-core`, `wallet-sdk-react`, `dapp-kit`. `<mode>` ∈ `migration` (port v1 → v2), `integration` (write new v2 code). |
|
|
25
|
+
| **Knowledge** under `knowledge/<pkg>/<mode>/` | Long-form supporting docs — features, recipes, reference tables, breaking-change writeups, code examples. Skills link into these. |
|
|
26
|
+
| **`AGENTS.md`** at the package root | Tool-neutral router: maps the consumer's stated task to the right set of skills. |
|
|
27
|
+
|
|
28
|
+
Skills are short and action-oriented (workflow + anti-patterns + links). Knowledge is the lookup material. Don't read knowledge files top-to-bottom — the skill tells the agent which file is relevant for the current task.
|
|
29
|
+
|
|
30
|
+
## Which skill applies?
|
|
31
|
+
|
|
32
|
+
After install, your agent picks based on what you're building. Quick guide:
|
|
33
|
+
|
|
34
|
+
| You're building | Load these skills |
|
|
35
|
+
|---|---|
|
|
36
|
+
| Backend / Node app (no React) using `@sodax/sdk` | `sodax-sdk-integration` (always) + `sodax-wallet-sdk-core-integration` (if signing) |
|
|
37
|
+
| React dapp using `@sodax/dapp-kit` | `sodax-dapp-kit-integration` + `sodax-wallet-sdk-react-integration` (always) + `sodax-sdk-integration` (for any unwrapped operations) |
|
|
38
|
+
| React app calling the SDK directly (no `dapp-kit`) | `sodax-sdk-integration` + `sodax-wallet-sdk-react-integration` |
|
|
39
|
+
| **Porting v1 code** | Add the corresponding `*-migration` skill alongside each `*-integration` you'd use. |
|
|
40
|
+
|
|
41
|
+
`AGENTS.md` says the same thing in router form — your agent reads it first and picks.
|
|
42
|
+
|
|
43
|
+
## Why this exists
|
|
44
|
+
|
|
45
|
+
LLM training data drifts: snippets from chat often use stale method names, reshaped types, or outdated error codes. Public docs help humans, not agents — an agent only reads what's in its context window. This package ships the right material in agent-native form so the agent reads it before generating code. The content is version-locked to the SDK — upgrade `@sodax/skills`, the docs upgrade with it.
|
|
46
|
+
|
|
47
|
+
## Feedback
|
|
48
|
+
|
|
49
|
+
If your agent generates wrong code despite reading the docs, that's a doc bug — please open an issue on the [Sodax SDKs repo](https://github.com/icon-project/sodax-sdks/issues) with the prompt and the incorrect output. The `knowledge/` tree is structurally CI-guarded (frontmatter, link resolution); prose claims benefit from real-world feedback.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Knowledge tree — `@sodax/dapp-kit`
|
|
2
|
+
|
|
3
|
+
Long-form knowledge supporting the `@sodax/dapp-kit` skills under `@sodax/skills`. The action-oriented entry points are the SKILL.md files in the sibling `skills/` directory:
|
|
4
|
+
|
|
5
|
+
- New code → `packages/skills/skills/sodax-dapp-kit-integration/SKILL.md`
|
|
6
|
+
- Porting v1 → `packages/skills/skills/sodax-dapp-kit-migration/SKILL.md`
|
|
7
|
+
|
|
8
|
+
**Don't read this tree top-to-bottom.** Load files from the **Workflow** section of the relevant SKILL.md.
|
|
9
|
+
|
|
10
|
+
## Package summary
|
|
11
|
+
|
|
12
|
+
`@sodax/dapp-kit` is a React hooks library that wraps `@sodax/sdk` with React Query. It provides hooks across 11 feature domains (swap, money market, staking, bridge, dex, migration, partner, recovery, bitcoin/Radfi, backend queries, shared) for consumer dApps. It is **React-only** — Node.js scripts and backend services use `@sodax/sdk` directly.
|
|
13
|
+
|
|
14
|
+
This package is **v2**. v2 was a deep canonicalization pass over v1's hook shapes — single-object params, mandatory `mutateAsyncSafe`, hook-owned invalidations, throw-on-`Result.!ok` inside `mutationFn`, canonical queryKey/mutationKey conventions. Plus the SDK underneath was reshaped (chain-key-driven routing, `Result<T>` everywhere, `WalletProviderSlot<K, Raw>`). Code written against v1 dapp-kit will not compile against v2.
|
|
15
|
+
|
|
16
|
+
## v2 in one minute
|
|
17
|
+
|
|
18
|
+
1. **Hooks accept a single object with one or two top-level keys.** Mutation hooks take only `{ mutationOptions }` at hook-init; query hooks take `{ params, queryOptions }`. ALL domain inputs (`params`, `walletProvider`, per-call config) flow through `mutate(vars)` for mutations.
|
|
19
|
+
2. **Every mutation hook returns `SafeUseMutationResult`** — extends React Query's `UseMutationResult` with `mutateAsyncSafe(vars): Promise<Result<TData>>` (never rejects).
|
|
20
|
+
3. **`mutationFn` throws on SDK `!ok`.** dapp-kit calls `unwrapResult` on the SDK's `Result<T>`, throwing on failure. React Query's native error model (`isError`, `error`, `onError`, `retry`, devtools) engages. `mutateAsyncSafe` packages the throw back into `Result<T>` for ergonomic branching.
|
|
21
|
+
4. **Hook-owned invalidations.** Each mutation hook invalidates the relevant query keys in its `onSuccess`. Consumer-provided `onSuccess` runs after.
|
|
22
|
+
5. **Canonical queryKey shape.** `[feature, action, ...identifiers]`. First segment matches the directory name (`swap`, `mm`, `bridge`, `staking`, `dex`, `bitcoin`, `partner`, `recovery`, `backend`, `shared`, `migrate`). camelCase. Bigints stringified.
|
|
23
|
+
|
|
24
|
+
## Layout
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
knowledge/dapp-kit/
|
|
28
|
+
├── AGENTS.md # You are here
|
|
29
|
+
├── integration/ # New code
|
|
30
|
+
│ ├── README.md
|
|
31
|
+
│ ├── ai-rules.md
|
|
32
|
+
│ ├── quickstart.md # Install + wire providers + first feature
|
|
33
|
+
│ ├── architecture.md # Hook shapes, queryKey conventions, useSafeMutation, unwrapResult
|
|
34
|
+
│ ├── features/ # Per-feature reference (swap, money-market, staking, bridge, dex, migration, bitcoin, auxiliary-services)
|
|
35
|
+
│ ├── recipes/ # 13 patterns (setup, wallet-connectivity, per-feature, mutation-error-handling, observability, invalidations, backend-queries)
|
|
36
|
+
│ └── reference/ # hooks-index, querykey-conventions, public-api, glossary
|
|
37
|
+
└── migration/ # v1 → v2 port
|
|
38
|
+
├── README.md
|
|
39
|
+
├── ai-rules.md
|
|
40
|
+
├── checklist.md
|
|
41
|
+
├── breaking-changes/ # hook-signatures, result-handling, querykey-conventions, sdk-leakage
|
|
42
|
+
├── features/ # Per-feature porting playbooks
|
|
43
|
+
├── recipes.md # Codemods + adapters
|
|
44
|
+
└── reference/ # deleted-hooks, renamed-hooks, error-shape-crosswalk
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Cross-references
|
|
48
|
+
|
|
49
|
+
- The underlying SDK: `packages/skills/knowledge/sdk/` (for any direct SDK call from a React app, or to understand how dapp-kit's hooks wrap SDK methods).
|
|
50
|
+
- The wallet layer: `packages/skills/knowledge/wallet-sdk-react/` (every dapp-kit consumer needs wallet connectivity; `useWalletProvider` bridges into `mutate(vars)`).
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Integration — `@sodax/dapp-kit` v2
|
|
2
|
+
|
|
3
|
+
This tree documents v2 of the dapp-kit React hooks for **new consumers** building against it. If you're porting v1 code, start at [`../migration/README.md`](../migration/README.md) instead.
|
|
4
|
+
|
|
5
|
+
## Files in this tree
|
|
6
|
+
|
|
7
|
+
| File | What's in it |
|
|
8
|
+
|---|---|
|
|
9
|
+
| [`ai-rules.md`](ai-rules.md) | **Read first.** DO / DO NOT / workflow / stop-conditions for AI agents writing v2 dapp-kit code. |
|
|
10
|
+
| [`quickstart.md`](quickstart.md) | Install, wire providers, get a wallet provider, run your first mutation. |
|
|
11
|
+
| [`architecture.md`](architecture.md) | Every v2 design concept the hooks rest on: ReadHookParams / MutationHookParams, useSafeMutation, unwrapResult, queryKey conventions, mutateAsyncSafe semantics, createSodaxQueryClient. |
|
|
12
|
+
| [`features/swap.md`](features/swap.md) | Swap hooks: `useQuote`, `useSwap`, `useSwapAllowance`, `useSwapApprove`, limit orders, status polling. |
|
|
13
|
+
| [`features/money-market.md`](features/money-market.md) | Money market hooks: `useSupply`, `useBorrow`, `useWithdraw`, `useRepay`, allowance/approve, reserves data. |
|
|
14
|
+
| [`features/staking.md`](features/staking.md) | Staking hooks: `useStake`, `useUnstake`, `useInstantUnstake`, `useClaim`, `useCancelUnstake`, info/ratio reads. |
|
|
15
|
+
| [`features/bridge.md`](features/bridge.md) | Bridge hooks: `useBridge`, allowance/approve, bridgeable amount/tokens. |
|
|
16
|
+
| [`features/dex.md`](features/dex.md) | DEX hooks: deposit/withdraw, supply/decrease liquidity, claim rewards, position info, pools. |
|
|
17
|
+
| [`features/migration.md`](features/migration.md) | Migration hooks: ICX/bnUSD/BALN forward + reverse, allowance/approve. |
|
|
18
|
+
| [`features/bitcoin.md`](features/bitcoin.md) | Radfi hooks (dapp-kit-unique): session, trading wallet, fund/withdraw, UTXOs. |
|
|
19
|
+
| [`features/auxiliary-services.md`](features/auxiliary-services.md) | Partner, recovery, backend queries, shared (xBalances, gas estimation, trustlines). |
|
|
20
|
+
| [`recipes/`](recipes/) | Copy-paste patterns: setup, wallet connectivity, per-feature flows, mutation error handling, observability, invalidations. |
|
|
21
|
+
| [`reference/`](reference/) | Lookup tables: full hook index, queryKey conventions, public API surface, glossary. |
|
|
22
|
+
|
|
23
|
+
## Reading order for a new integrator
|
|
24
|
+
|
|
25
|
+
1. **[`ai-rules.md`](ai-rules.md)** — agent rules, before any code.
|
|
26
|
+
2. **[`quickstart.md`](quickstart.md)** — get providers wired and a button rendering.
|
|
27
|
+
3. **[`architecture.md`](architecture.md)** — understand `useSafeMutation` / `mutateAsyncSafe` / hook shapes before writing call sites.
|
|
28
|
+
4. **[`recipes/`](recipes/)** — pick the patterns you need (mutation error handling, observability, invalidations).
|
|
29
|
+
5. **[`features/<x>.md`](features/)** — read the file for the feature you're integrating (reference shape; pair with the matching recipe in `recipes/<x>.md` for working examples).
|
|
30
|
+
6. **[`reference/`](reference/)** — keep open while writing for table lookups.
|
|
31
|
+
|
|
32
|
+
## Cross-references to migration
|
|
33
|
+
|
|
34
|
+
If your project also has v1 dapp-kit call sites, port them first using:
|
|
35
|
+
|
|
36
|
+
- [`../migration/README.md`](../migration/README.md) — overview, reading order, and v1↔v2 glossary.
|
|
37
|
+
- [`../migration/checklist.md`](../migration/checklist.md) — top-down cross-cutting checklist.
|
|
38
|
+
- [`../migration/breaking-changes/`](../migration/breaking-changes/) — the four cross-cutting changes (hook-signatures, result-handling, queryKey-conventions, sdk-leakage).
|
|
39
|
+
- [`../migration/features/`](../migration/features/) — per-feature playbooks in lockstep with `integration/features/` here.
|
|
40
|
+
|
|
41
|
+
The naming rule: **every file in `integration/features/` has a sibling in `migration/features/` with the same filename.** When you're deep in one, the other is one path-swap away.
|
|
42
|
+
|
|
43
|
+
## Cross-references to the underlying SDK
|
|
44
|
+
|
|
45
|
+
`@sodax/dapp-kit` re-exports `@sodax/sdk` at the package root, so most types you'd reach for (`ChainKeys`, `SodaxConfig`, `CreateIntentParams`, `XToken`, `Result`, `SodaxError`) are available from `@sodax/dapp-kit` directly. The Core SDK has its own knowledge tree at [`@sodax/sdk` knowledge tree](https://github.com/icon-project/sodax-sdks/tree/main/packages/skills/knowledge/sdk/) (sibling under `@sodax/skills`). Useful for:
|
|
46
|
+
|
|
47
|
+
- The full SDK migration playbook for v1→v2 (chain-key terminology, `Result<T>` semantics, ConfigService) — referenced from [`../migration/breaking-changes/sdk-leakage.md`](../migration/breaking-changes/sdk-leakage.md).
|
|
48
|
+
- Architectural concepts that surface through hook signatures (`SodaxError<C>` vocabulary, `WalletProviderSlot<K, Raw>` discriminator semantics).
|
|
49
|
+
- Backend / Node.js usage patterns (where dapp-kit isn't applicable).
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# AI rules — `@sodax/dapp-kit` integration
|
|
2
|
+
|
|
3
|
+
DO / DO NOT / workflow / stop conditions for AI agents writing v2 dapp-kit code. Read this **before** the per-feature docs — these rules prevent the most common load-bearing v2 traps.
|
|
4
|
+
|
|
5
|
+
## Workflow (do these in order)
|
|
6
|
+
|
|
7
|
+
1. **Survey the project before touching code.**
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm tsc --noEmit # baseline typecheck
|
|
11
|
+
grep -rE '@sodax/(dapp-kit|sdk|wallet-sdk-react)' --include='*.ts' --include='*.tsx' src/ # see what's already imported
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
2. **Wire providers first if not already wired.** [`recipes/setup.md`](recipes/setup.md). Provider stack: `SodaxProvider > QueryClientProvider > SodaxWalletProvider > YourApp`.
|
|
15
|
+
3. **Pick `mutate` / `mutateAsync` / `mutateAsyncSafe` deliberately.** See [`recipes/mutation-error-handling.md`](recipes/mutation-error-handling.md). Default to `mutateAsyncSafe` for sequenced flows.
|
|
16
|
+
4. **Branch on `result.ok` for `mutateAsyncSafe` results, or on `mutation.isError` / `mutation.error`** for fire-and-forget. Never assume mutation success.
|
|
17
|
+
5. **Use `useWalletProvider({ xChainId: chainKey })` from `@sodax/wallet-sdk-react` for every signed flow.** Pass the result into `mutate(vars).walletProvider`. Don't create or import any `*SpokeProvider` class — those don't exist in v2.
|
|
18
|
+
|
|
19
|
+
## DO
|
|
20
|
+
|
|
21
|
+
- **DO** call dapp-kit's exported hooks (which wrap `useSafeMutation`). Never call React Query's `useMutation` directly inside a wrapper around a dapp-kit hook — consumers depend on `mutateAsyncSafe`.
|
|
22
|
+
- **DO** branch on `mutateAsyncSafe`'s `Result.ok` for sequenced flows (`if (!hasAllowance) await approve(...); await action(...);`). User-rejects are modal, not exceptional.
|
|
23
|
+
- **DO** use `ChainKeys.X_MAINNET` constants for chain identifiers. Never hard-code chain key strings (`'sonic'`, `'0xa4b1.arbitrum'`).
|
|
24
|
+
- **DO** import everything from `@sodax/dapp-kit` (or `@sodax/sdk` for SDK-only types and constants — `@sodax/dapp-kit` re-exports them anyway).
|
|
25
|
+
- **DO** preserve literal chain keys in generic positions where possible (e.g. `srcChainKey: ChainKeys.ETHEREUM_MAINNET as const`) — TypeScript narrowing flows from the literal, including the `walletProvider` parameter type.
|
|
26
|
+
- **DO** use the canonical hook shape: queries take `{ params, queryOptions }`; mutations take only `{ mutationOptions }` and flow domain inputs through `mutate(vars)`.
|
|
27
|
+
- **DO** compose `onSuccess` instead of replacing it: `mutationOptions: { onSuccess: (data, vars, ctx) => myExtra(...) }` runs AFTER dapp-kit's hook-owned invalidations.
|
|
28
|
+
|
|
29
|
+
## DO NOT
|
|
30
|
+
|
|
31
|
+
- **DO NOT** call `useSpokeProvider` — it's deleted. v1 React consumers got a `SpokeProvider` from this hook; v2 has no such concept. Pass `walletProvider` directly into `mutate(vars)`.
|
|
32
|
+
- **DO NOT** treat mutation `data` as `Result<T>`. `mutationFn` calls `unwrapResult` and throws on `!ok`; `data` is the unwrapped success value (e.g. `SwapResponse`, `TxHashPair`). For SDK failures, look at `mutation.error` or use `mutateAsyncSafe`.
|
|
33
|
+
- **DO NOT** call `mutateAsync` without `try/catch`. It rejects on SDK `!ok`; an unhandled rejection lands in the global handler. Prefer `mutateAsyncSafe` for sequenced flows.
|
|
34
|
+
- **DO NOT** put `params`, `walletProvider`, or per-call config at the hook-init level. They go in `mutate(vars)` for mutations and in `params` for queries.
|
|
35
|
+
- **DO NOT** override `queryKey`, `queryFn`, or `enabled` via `queryOptions` — the hook owns those. The `queryOptions` slot is typed `Omit<UseQueryOptions, 'queryKey' | 'queryFn' | 'enabled'>`.
|
|
36
|
+
- **DO NOT** override `mutationFn` via `mutationOptions` — the hook owns it. Type prevents this.
|
|
37
|
+
- **DO NOT** import from `@sodax/dapp-kit/dist/...`. Deep-imports unstable; only the package root barrel is the public contract.
|
|
38
|
+
- **DO NOT** add `@sodax/types` as a separate dependency. It's re-exported transitively via `@sodax/sdk` (which dapp-kit re-exports). Adding it independently invites version skew.
|
|
39
|
+
- **DO NOT** recreate the v1 `invalidateMmQueries(...)` utility or anything similar. Each mutation hook invalidates the relevant keys in its own `onSuccess`. Add cross-feature invalidations via consumer `onSuccess`.
|
|
40
|
+
- **DO NOT** destructure cross-chain mutation results as arrays — `[a, b] = result.value` is wrong. The shape is `TxHashPair = { srcChainTxHash, dstChainTxHash }` (object). This applies to `useBridge`, `useStake`/`useUnstake`/etc., `useDexDeposit`/`useDexWithdraw`, all four MM mutations, and all four migration mutations.
|
|
41
|
+
- **DO NOT** use legacy chain-id constants (`BSC_MAINNET_CHAIN_ID`, etc.). They're gone in v2 — use `ChainKeys.X_MAINNET`.
|
|
42
|
+
- **DO NOT** reach for `as any` / `as IEvmWalletProvider` casts when wiring `useWalletProvider({ xChainId })` into mutation `mutate(vars)`. v2 supports the broad-union case structurally; the cast is not needed. See `recipes/wallet-connectivity.md` § "No type cast is needed".
|
|
43
|
+
|
|
44
|
+
## Stop conditions (defer to user)
|
|
45
|
+
|
|
46
|
+
| Signal | Why stop |
|
|
47
|
+
|---|---|
|
|
48
|
+
| User wants a chain not in `ChainKeys.*` | Adding a new chain requires SDK-level changes — out of scope for consumer code. |
|
|
49
|
+
| User wants to use React Server Components / RSC patterns | dapp-kit is client-side React (uses React Query, hooks, browser APIs). Server Components don't run hooks. Tell the user the dapp-kit code goes in client components. |
|
|
50
|
+
| User wants to skip the wallet-sdk-react integration | If they have their own wallet abstraction, it's possible — they need to construct objects satisfying `I*WalletProvider` interfaces from `@sodax/sdk`. Refer them to the `sodax-sdk-integration` skill (sibling under `@sodax/skills`) for non-React patterns. |
|
|
51
|
+
| User wants to use v1 dapp-kit (positional args, `useSpokeProvider`, `Result<T>` in success path) | Tell them to either upgrade or stay on v1. The shapes are not compatible. |
|
|
52
|
+
|
|
53
|
+
## Verification protocol
|
|
54
|
+
|
|
55
|
+
Before declaring a dapp-kit integration "done":
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# 1. Type-check the consumer.
|
|
59
|
+
pnpm -C <consumer> tsc --noEmit
|
|
60
|
+
|
|
61
|
+
# 2. Confirm no leftover v1 patterns (if porting).
|
|
62
|
+
grep -rE '\buseSpokeProvider\b|\binvalidateMmQueries\b|_MAINNET_CHAIN_ID\b|\bxChainId\b' src/
|
|
63
|
+
|
|
64
|
+
# 3. Confirm all SDK-level mutation results are handled (either mutateAsyncSafe + result.ok branch
|
|
65
|
+
# or mutateAsync wrapped in try/catch).
|
|
66
|
+
grep -rE 'mutateAsync\(' src/ | grep -v 'try\|catch\|mutateAsyncSafe'
|
|
67
|
+
|
|
68
|
+
# 4. Confirm all hooks are imported from @sodax/dapp-kit, not deep paths.
|
|
69
|
+
# (matches `'@sodax/dapp-kit/dist'` and similar deep-import patterns)
|
|
70
|
+
grep -rE "@sodax/dapp-kit/[a-z]" src/ # zero hits expected (only the root path is public)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Done criteria
|
|
74
|
+
|
|
75
|
+
- [ ] `SodaxProvider` + `QueryClientProvider` (preferably `createSodaxQueryClient()`) wired at the app root.
|
|
76
|
+
- [ ] Every mutation invocation uses `mutateAsyncSafe` (preferred), `mutateAsync` wrapped in `try/catch`, or fire-and-forget `mutate` with state read in render.
|
|
77
|
+
- [ ] No `useSpokeProvider`, no `invalidateMmQueries`, no `*_MAINNET_CHAIN_ID` constants, no `xChainId` outside known v2 hooks (e.g. `useXBalances` still uses `xChainId`).
|
|
78
|
+
- [ ] No `import` from `@sodax/dapp-kit/dist/...` or any other deep path.
|
|
79
|
+
- [ ] No standalone `@sodax/types` dependency in `package.json`.
|
|
80
|
+
- [ ] Consumer typecheck (`pnpm tsc --noEmit`) is clean.
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# Architecture — `@sodax/dapp-kit` v2
|
|
2
|
+
|
|
3
|
+
Every v2 design concept the hooks rest on, in one TOC-navigable file. Read it once before writing call sites — most of the v1→v2 breakage and most of the new-code traps come from misunderstanding one of these.
|
|
4
|
+
|
|
5
|
+
## Five pieces hold it together
|
|
6
|
+
|
|
7
|
+
1. **Two canonical hook shapes.**
|
|
8
|
+
- Read hooks accept `{ params, queryOptions }` typed via `ReadHookParams<TData, TParams>`.
|
|
9
|
+
- Mutation hooks accept `{ mutationOptions }` typed via `MutationHookParams<TData, TVars>` and return `SafeUseMutationResult<TData, Error, TVars>`.
|
|
10
|
+
- All domain inputs (params, walletProvider, apiConfig) flow through `mutate(vars)`, never the hook arg.
|
|
11
|
+
2. **`useSafeMutation` foundation.** Every mutation hook calls `useSafeMutation(...)` (drop-in for React Query's `useMutation`), which augments the result with `mutateAsyncSafe(vars): Promise<Result<TData>>` — never rejects.
|
|
12
|
+
3. **`unwrapResult` translation.** SDK service methods return `Result<T>`. `unwrapResult` converts to thrown errors inside `mutationFn` so React Query's native error model engages (`isError`, `error`, `onError`, `retry`, devtools) for SDK failures.
|
|
13
|
+
4. **`createSodaxQueryClient`** (optional). Factory that returns a `QueryClient` with a `MutationCache.onError` hook giving consumers a single observability seam, plus a `meta.silent` per-mutation opt-out.
|
|
14
|
+
5. **Mechanical enforcement.** `_mutationContract.test.ts` asserts the canonical shape on every mutation hook (`useSafeMutation` not `useMutation`, default `mutationKey` before the spread, `mutationFn` after, `unwrapResult` translation, feature-prefix queryKey rule).
|
|
15
|
+
|
|
16
|
+
## Provider stack
|
|
17
|
+
|
|
18
|
+
`SodaxProvider` wraps the app and provides:
|
|
19
|
+
- The `Sodax` SDK instance
|
|
20
|
+
- RPC configuration for all chains
|
|
21
|
+
- Hub provider access
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
// @ai-snippets-skip
|
|
25
|
+
<SodaxProvider config={sodaxConfig}> {/* SDK instance + RPC config */}
|
|
26
|
+
<QueryClientProvider client={queryClient}> {/* prefer createSodaxQueryClient() */}
|
|
27
|
+
<SodaxWalletProvider config={walletConfig}> {/* from @sodax/wallet-sdk-react (optional) */}
|
|
28
|
+
<YourApp />
|
|
29
|
+
</SodaxWalletProvider>
|
|
30
|
+
</QueryClientProvider>
|
|
31
|
+
</SodaxProvider>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`SodaxProvider` does **not** depend on `@sodax/wallet-sdk-react` — wallet state is wired side-by-side. Backend / non-React consumers (Node scripts, bots) bypass dapp-kit entirely and use `@sodax/sdk` directly with their own wallet implementation.
|
|
35
|
+
|
|
36
|
+
**Config reactivity.** `config` is tracked by reference - see [`recipes/setup.md § Config reactivity`](recipes/setup.md#config-reactivity) for the module-const vs `useMemo` patterns.
|
|
37
|
+
|
|
38
|
+
### `createSodaxQueryClient`
|
|
39
|
+
|
|
40
|
+
Returns a `QueryClient` pre-wired with a `MutationCache.onError` hook for global mutation observability. Default behavior: logs every mutation failure to console as `[sodax] Mutation error: <error>`.
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { createSodaxQueryClient } from '@sodax/dapp-kit';
|
|
44
|
+
|
|
45
|
+
// Default
|
|
46
|
+
const queryClientDefault = createSodaxQueryClient();
|
|
47
|
+
|
|
48
|
+
// Wire to your own logger
|
|
49
|
+
const queryClientWithSentry = createSodaxQueryClient({
|
|
50
|
+
onMutationError: (e) => Sentry.captureException(e),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Disable entirely
|
|
54
|
+
const queryClientSilent = createSodaxQueryClient({ onMutationError: () => {} });
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Per-mutation opt-out via `meta.silent`:
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
// @ai-snippets-skip
|
|
61
|
+
const swap = useSwap({
|
|
62
|
+
mutationOptions: {
|
|
63
|
+
meta: { silent: true },
|
|
64
|
+
onError: (e) => toast.error(e.message),
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
This is **observability**, not prevention. It does NOT detect "unhandled" rejections — it fires for **every** mutation failure regardless of whether the consumer caught the rejection or registered a per-hook `onError`. To prevent unhandled rejections, use `mutateAsyncSafe`.
|
|
70
|
+
|
|
71
|
+
## Read hook shape (mandatory)
|
|
72
|
+
|
|
73
|
+
All read-only hooks accept a single object with exactly two top-level keys: `params` (SDK-feature-domain inputs — the *what* being fetched) and `queryOptions` (React Query knobs — the *how*).
|
|
74
|
+
|
|
75
|
+
Rules:
|
|
76
|
+
|
|
77
|
+
- **Single params object with two top-level keys.** `{ params, queryOptions }`. Nothing else at the top level.
|
|
78
|
+
- **Use the shared types.** Params type MUST be `ReadHookParams<TData, TParams>`; the `queryOptions` slot is typed `ReadQueryOptions<TData>` (which is `Omit<UseQueryOptions<TData, Error>, 'queryKey' | 'queryFn' | 'enabled'>`). Hook owns `queryKey`, `queryFn`, `enabled` — never consumer-overridable.
|
|
79
|
+
- **Hierarchical query keys.** `[feature, action, ...inputs]`. Stringify bigints with `.toString()`.
|
|
80
|
+
- **No-input hooks.** Type as `ReadHookParams<TData>` (no `TParams` generic) and accept the whole arg as optional, defaulting to `{}` for ergonomic no-arg calls (`useStakingConfig({})`).
|
|
81
|
+
|
|
82
|
+
Canonical example:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// @ai-snippets-skip — definition-shape illustration; function body elided with `// ...`
|
|
86
|
+
import type { PoolData, PoolKey } from '@sodax/sdk';
|
|
87
|
+
import { useQuery, type UseQueryResult } from '@tanstack/react-query';
|
|
88
|
+
import type { ReadHookParams } from '@sodax/dapp-kit';
|
|
89
|
+
|
|
90
|
+
export type UsePoolDataParams = ReadHookParams<PoolData, { poolKey: PoolKey | null }>;
|
|
91
|
+
|
|
92
|
+
export function usePoolData({ params, queryOptions }: UsePoolDataParams = {}): UseQueryResult<PoolData, Error> {
|
|
93
|
+
// ... uses sodax.dex.clService.getPoolData internally
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Call site:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
// @ai-snippets-skip
|
|
101
|
+
const { data } = usePoolData({ params: { poolKey } });
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Mutation hook shape (mandatory)
|
|
105
|
+
|
|
106
|
+
All mutation hooks follow the **zero-domain-param** policy: the hook function takes a single optional argument with exactly one top-level key — `mutationOptions` — and ALL domain inputs (`params`, `walletProvider`, per-call config, etc.) flow through `mutate(vars)` via the typed `TVars` payload.
|
|
107
|
+
|
|
108
|
+
Three shared utilities underpin every mutation hook:
|
|
109
|
+
|
|
110
|
+
- **`useSafeMutation(options)`** — drop-in for React Query's `useMutation`. Returns `SafeUseMutationResult<TData, Error, TVars>` (extends `UseMutationResult` with `mutateAsyncSafe`).
|
|
111
|
+
- **`unwrapResult(result)`** — `Result<T>` → throw `error` on `!ok`, return `value` on `ok`. Use inside `mutationFn`.
|
|
112
|
+
- **`toResult(promise)`** — pure helper that catches `Promise<T>` rejection and packs into `Result<T>`. Used internally by `useSafeMutation`.
|
|
113
|
+
|
|
114
|
+
Rules:
|
|
115
|
+
|
|
116
|
+
- **Use `useSafeMutation`, not `useMutation`.** Every dapp-kit mutation hook MUST call `useSafeMutation`. The wrapper augments the result with `mutateAsyncSafe`, which consumers depend on.
|
|
117
|
+
- **One optional top-level arg.** `useFoo({ mutationOptions } = {}): SafeUseMutationResult<TData, Error, TVars>`.
|
|
118
|
+
- **Use the shared types.** `MutationHookParams<TData, TVars>`; return `SafeUseMutationResult<TData, Error, TVars>`; `mutationOptions` typed `MutationHookOptions<TData, TVars>` (which is `Omit<UseMutationOptions<TData, Error, TVars>, 'mutationFn'>`).
|
|
119
|
+
- **Hook owns `mutationFn`.** Never consumer-overridable.
|
|
120
|
+
- **`mutationFn` throws on SDK `!ok`.** Use `unwrapResult` from `@sodax/dapp-kit`. SDK returns `Result<T>`; the hook unwraps to `T` so React Query's native error model engages. `TData` is the unwrapped success type, NOT `Result<T>`.
|
|
121
|
+
- **Default `mutationKey` BEFORE the spread**, then spread `...mutationOptions`, then `mutationFn` last. Order matters: default key is overridable by consumer (spread wins), but `mutationFn` is hook-owned.
|
|
122
|
+
- **Compose `onSuccess` (and any other callbacks the hook itself defines).** Invalidations are correctness logic owned by the hook. Inside the hook's `onSuccess`, run invalidations first, then `await mutationOptions?.onSuccess?.(...)` so consumer hooks still fire.
|
|
123
|
+
- **Derive invalidation keys from `vars`, not closures.** `(data, vars, ctx) => ...` and read `vars.params.srcChainKey`.
|
|
124
|
+
- **All domain inputs go in `TVars`.** No `params`, `walletProvider`, `apiConfig` at the hook level. Pushing inputs into `mutate(vars)` lets a single hook serve many call shapes without remounting.
|
|
125
|
+
|
|
126
|
+
Canonical example:
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import type { SwapActionParams, SwapResponse, SpokeChainKey } from '@sodax/sdk';
|
|
130
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
131
|
+
import {
|
|
132
|
+
useSodaxContext,
|
|
133
|
+
useSafeMutation,
|
|
134
|
+
unwrapResult,
|
|
135
|
+
type MutationHookParams,
|
|
136
|
+
type SafeUseMutationResult,
|
|
137
|
+
} from '@sodax/dapp-kit';
|
|
138
|
+
|
|
139
|
+
export type UseSwapVars<K extends SpokeChainKey = SpokeChainKey> = Omit<SwapActionParams<K, false>, 'raw'>;
|
|
140
|
+
|
|
141
|
+
export function useSwap<K extends SpokeChainKey = SpokeChainKey>({
|
|
142
|
+
mutationOptions,
|
|
143
|
+
}: MutationHookParams<SwapResponse, UseSwapVars<K>> = {}): SafeUseMutationResult<SwapResponse, Error, UseSwapVars<K>> {
|
|
144
|
+
const { sodax } = useSodaxContext();
|
|
145
|
+
const queryClient = useQueryClient();
|
|
146
|
+
|
|
147
|
+
return useSafeMutation<SwapResponse, Error, UseSwapVars<K>>({
|
|
148
|
+
mutationKey: ['swap'],
|
|
149
|
+
...mutationOptions,
|
|
150
|
+
mutationFn: async vars => unwrapResult(await sodax.swaps.swap({ ...vars, raw: false })),
|
|
151
|
+
onSuccess: async (data, vars, ctx) => {
|
|
152
|
+
queryClient.invalidateQueries({ queryKey: ['shared', 'xBalances', vars.params.srcChainKey] });
|
|
153
|
+
queryClient.invalidateQueries({ queryKey: ['shared', 'xBalances', vars.params.dstChainKey] });
|
|
154
|
+
await mutationOptions?.onSuccess?.(data, vars, ctx);
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Choosing `mutate` / `mutateAsync` / `mutateAsyncSafe`
|
|
161
|
+
|
|
162
|
+
| Method | Returns | Rejects? | When to use |
|
|
163
|
+
|---|---|---|---|
|
|
164
|
+
| `mutate(vars)` | `void` (fire-and-forget) | Never | Button-click handlers reading `isPending` / `isError` / `error` in render. Consumer-supplied `onError` fires; React Query owns state. |
|
|
165
|
+
| `mutateAsync(vars)` | `Promise<TData>` | **Yes** on `!ok` | Imperative chains where you want exception flow. **MUST be inside `try/catch`.** |
|
|
166
|
+
| `mutateAsyncSafe(vars)` | `Promise<Result<TData>>` | **Never** | Imperative chains with explicit branching, no exception flow. Same React Query state under the hood. |
|
|
167
|
+
|
|
168
|
+
`mutateAsyncSafe` is the **recommended default** for sequenced flows — the user-reject case is the modal failure mode in dApps, not exceptional, and `Result<T>`-style branching reads cleaner than exception flow control.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
// @ai-snippets-skip
|
|
172
|
+
// fire-and-forget — read state in render
|
|
173
|
+
const m = useSwap();
|
|
174
|
+
<button onClick={() => m.mutate({ params, walletProvider })}>Swap</button>
|
|
175
|
+
|
|
176
|
+
// throws — for chains where you want exception flow
|
|
177
|
+
const { mutateAsync } = useSwap();
|
|
178
|
+
try { const r = await mutateAsync({ params, walletProvider }); /* … */ }
|
|
179
|
+
catch (e) { toast(e instanceof Error ? e.message : 'Swap failed'); }
|
|
180
|
+
|
|
181
|
+
// safe — for chains where you want explicit branching, no try/catch
|
|
182
|
+
const { mutateAsyncSafe } = useSwap();
|
|
183
|
+
const result = await mutateAsyncSafe({ params, walletProvider });
|
|
184
|
+
if (!result.ok) { toast(result.error.message); return; }
|
|
185
|
+
const { intent, intentDeliveryInfo } = result.value;
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## SDK Result handling
|
|
189
|
+
|
|
190
|
+
Every public SDK service method returns `Result<T> = { ok: true; value: T } | { ok: false; error: Error | unknown }` and never throws. dapp-kit translates that contract into the React Query contract by **throwing `result.error` on `!ok` inside `mutationFn`.**
|
|
191
|
+
|
|
192
|
+
Why throw?
|
|
193
|
+
- React Query's `isError`, `error`, `onError`, `retry`, `throwOnError`, devtools all key off `mutationFn` throwing.
|
|
194
|
+
- Consumers had to remember to branch on `data.ok` inside every `onSuccess` to avoid running success logic on a failed swap. Forgetting was easy and silent.
|
|
195
|
+
- Hook-owned invalidations (in `onSuccess`) used to fire on SDK failure too, burning RPC traffic on every failed click.
|
|
196
|
+
|
|
197
|
+
After translating, the public hook signature is `SafeUseMutationResult<T, Error, TVars>`. `data` is the unwrapped success value (e.g. `SwapResponse`, `TxHashPair`); SDK failures arrive via `mutation.error` exactly like any other thrown error. Call sites pick from three call shapes (above).
|
|
198
|
+
|
|
199
|
+
The dual API means consumers never have to choose between React Query's error model and `Result<T>` ergonomics — both are exposed by the same hook.
|
|
200
|
+
|
|
201
|
+
## queryKey / mutationKey conventions (mandatory)
|
|
202
|
+
|
|
203
|
+
Every `queryKey` and `mutationKey` follows the same structural rule. Enforced by `_mutationContract.test.ts` for mutation keys; reviewer-enforced for query keys.
|
|
204
|
+
|
|
205
|
+
**Rule 1 — first segment is the feature directory name.** No exceptions.
|
|
206
|
+
|
|
207
|
+
| Hook directory | First segment |
|
|
208
|
+
|---|---|
|
|
209
|
+
| `backend/` | `'backend'` |
|
|
210
|
+
| `bitcoin/` | `'bitcoin'` |
|
|
211
|
+
| `bridge/` | `'bridge'` |
|
|
212
|
+
| `dex/` | `'dex'` |
|
|
213
|
+
| `mm/` | `'mm'` |
|
|
214
|
+
| `partner/` | `'partner'` |
|
|
215
|
+
| `recovery/` | `'recovery'` |
|
|
216
|
+
| `shared/` | `'shared'` |
|
|
217
|
+
| `staking/` | `'staking'` |
|
|
218
|
+
| `swap/` | `'swap'` |
|
|
219
|
+
| `migrate/` | `'migrate'` |
|
|
220
|
+
|
|
221
|
+
**Rule 2 — camelCase for all segments.** No kebab-case (`'btc-balance'`), no ad-hoc casing. Identifiers are camelCase string literals (`'tradingWalletBalance'`, `'submitSwapTx'`).
|
|
222
|
+
|
|
223
|
+
**Rule 3 — shape is `[feature, action, ...identifiers]`** in stable order: chain → token/asset → user → amount. Example: `['mm', 'allowance', srcChainKey, token, action]`.
|
|
224
|
+
|
|
225
|
+
**Rule 4 — bigints stringify** via `.toString()` before going into a key (React Query's hash uses `JSON.stringify`, which throws on raw bigints).
|
|
226
|
+
|
|
227
|
+
**Rule 5 — invalidate the narrowest key that could change.** If the mutation knows the affected `tokenId` / user / chain, scope the invalidation to it.
|
|
228
|
+
|
|
229
|
+
Worked examples:
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
// @ai-snippets-skip
|
|
233
|
+
queryKey: ['mm', 'userReservesData', spokeChainKey, userAddress]
|
|
234
|
+
queryKey: ['mm', 'allowance', srcChainKey, token, action]
|
|
235
|
+
queryKey: ['shared', 'xBalances', xChainId, tokens, address]
|
|
236
|
+
mutationKey: ['mm', 'supply']
|
|
237
|
+
queryClient.invalidateQueries({ queryKey: ['dex', 'positionInfo', tokenId, poolKey] });
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Hook organization
|
|
241
|
+
|
|
242
|
+
Hooks organized by feature domain in `src/hooks/`:
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
hooks/
|
|
246
|
+
├── shared/ # useSodaxContext, useSafeMutation, unwrapResult, useEstimateGas,
|
|
247
|
+
│ # useDeriveUserWalletAddress, useGetUserHubWalletAddress, useXBalances,
|
|
248
|
+
│ # useStellarTrustlineCheck, useRequestTrustline
|
|
249
|
+
├── provider/ # useHubProvider
|
|
250
|
+
├── swap/ # useQuote, useSwap, useStatus, useSwapAllowance, useSwapApprove,
|
|
251
|
+
│ # useCancelSwap, useCreateLimitOrder, useCancelLimitOrder
|
|
252
|
+
├── mm/ # useSupply, useWithdraw, useBorrow, useRepay, useMMAllowance, useMMApprove,
|
|
253
|
+
│ # reserves data hooks
|
|
254
|
+
├── bridge/ # useBridge, useBridgeAllowance, useBridgeApprove, bridgeable amounts/tokens
|
|
255
|
+
├── staking/ # useStake, useUnstake, useInstantUnstake, useClaim, staking info hooks
|
|
256
|
+
├── dex/ # usePools, useDexDeposit, useDexWithdraw, liquidity hooks
|
|
257
|
+
├── bitcoin/ # useRadfiSession, fund/withdraw, UTXO management
|
|
258
|
+
├── backend/ # Intent tracking, swap submission, orderbook, money market position queries
|
|
259
|
+
├── partner/ # Partner fee claim, auto-swap preferences, token approval
|
|
260
|
+
├── recovery/ # useHubAssetBalances, useWithdrawHubAsset
|
|
261
|
+
└── migrate/ # useMigrateIcxToSoda, useRevertMigrateSodaToIcx, useMigratebnUSD,
|
|
262
|
+
# useMigrateBaln, useMigrationApprove, useMigrationAllowance
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Every mutation hook returns `SafeUseMutationResult` and is registered in `_mutationContract.test.ts`'s manifest. Adding a non-conformant hook is a CI failure.
|
|
266
|
+
|
|
267
|
+
## Cross-references
|
|
268
|
+
|
|
269
|
+
- [`recipes/setup.md`](recipes/setup.md) — install + wire providers (worked example).
|
|
270
|
+
- [`recipes/wallet-connectivity.md`](recipes/wallet-connectivity.md) — `useWalletProvider`, balances.
|
|
271
|
+
- [`recipes/mutation-error-handling.md`](recipes/mutation-error-handling.md) — picking call shapes (worked examples).
|
|
272
|
+
- [`recipes/observability.md`](recipes/observability.md) — `createSodaxQueryClient` deep-dive.
|
|
273
|
+
- [`recipes/invalidations.md`](recipes/invalidations.md) — composing your own `onSuccess`.
|
|
274
|
+
- [`reference/querykey-conventions.md`](reference/querykey-conventions.md) — full key tables.
|
|
275
|
+
- [`features/`](features/) — per-feature reference (hook tables, types, gotchas).
|
|
276
|
+
- [`@sodax/sdk`: `integration/architecture.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/skills/knowledge/sdk/integration/architecture.md) — the underlying SDK architecture (`Result<T>`, `SodaxError<C>`, `WalletProviderSlot<K, Raw>`).
|