@sodax/skills 2.0.0-rc.7 → 2.0.0-rc.9

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.
Files changed (39) hide show
  1. package/.claude-plugin/plugin.json +9 -0
  2. package/AGENTS.md +15 -10
  3. package/package.json +1 -1
  4. package/skills/sodax-dapp-kit/integration/knowledge/features/migration.md +1 -1
  5. package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/features/migration.md +1 -1
  6. package/skills/sodax-sdk/SKILL.md +46 -47
  7. package/skills/sodax-sdk/backend-api/SKILL.md +52 -0
  8. package/skills/sodax-sdk/bridge/SKILL.md +49 -0
  9. package/skills/sodax-sdk/dex/SKILL.md +50 -0
  10. package/skills/sodax-sdk/integration/knowledge/README.md +4 -2
  11. package/skills/sodax-sdk/integration/knowledge/ai-rules.md +1 -1
  12. package/skills/sodax-sdk/integration/knowledge/architecture.md +2 -18
  13. package/skills/sodax-sdk/integration/knowledge/features/README.md +4 -2
  14. package/skills/sodax-sdk/integration/knowledge/features/backend-api.md +81 -0
  15. package/skills/sodax-sdk/integration/knowledge/features/bridge.md +36 -0
  16. package/skills/sodax-sdk/integration/knowledge/features/{icx-bnusd-baln.md → migration.md} +2 -2
  17. package/skills/sodax-sdk/integration/knowledge/features/money-market.md +1 -1
  18. package/skills/sodax-sdk/integration/knowledge/features/partner.md +63 -0
  19. package/skills/sodax-sdk/integration/knowledge/features/recovery.md +50 -0
  20. package/skills/sodax-sdk/integration/knowledge/features/staking.md +6 -1
  21. package/skills/sodax-sdk/integration/knowledge/features/swap.md +70 -4
  22. package/skills/sodax-sdk/integration/knowledge/reference/chain-keys.md +1 -1
  23. package/skills/sodax-sdk/migration/SKILL.md +65 -0
  24. package/skills/sodax-sdk/migration-v1-to-v2/knowledge/ai-rules.md +5 -9
  25. package/skills/sodax-sdk/migration-v1-to-v2/knowledge/checklist.md +1 -1
  26. package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/README.md +4 -2
  27. package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/backend-api.md +92 -0
  28. package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/{icx-bnusd-baln.md → migration.md} +2 -2
  29. package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/partner.md +59 -0
  30. package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/recovery.md +35 -0
  31. package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/staking.md +8 -3
  32. package/skills/sodax-sdk/migration-v1-to-v2/knowledge/reference/sodax-config.md +1 -1
  33. package/skills/sodax-sdk/money-market/SKILL.md +52 -0
  34. package/skills/sodax-sdk/partner/SKILL.md +51 -0
  35. package/skills/sodax-sdk/recovery/SKILL.md +49 -0
  36. package/skills/sodax-sdk/staking/SKILL.md +49 -0
  37. package/skills/sodax-sdk/swap/SKILL.md +67 -0
  38. package/skills/sodax-sdk/integration/knowledge/features/auxiliary-services.md +0 -189
  39. package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/auxiliary-services.md +0 -156
@@ -2,6 +2,15 @@
2
2
  "name": "sodax-skills",
3
3
  "skills": [
4
4
  "./skills/sodax-sdk",
5
+ "./skills/sodax-sdk/swap",
6
+ "./skills/sodax-sdk/money-market",
7
+ "./skills/sodax-sdk/bridge",
8
+ "./skills/sodax-sdk/staking",
9
+ "./skills/sodax-sdk/dex",
10
+ "./skills/sodax-sdk/migration",
11
+ "./skills/sodax-sdk/partner",
12
+ "./skills/sodax-sdk/recovery",
13
+ "./skills/sodax-sdk/backend-api",
5
14
  "./skills/sodax-wallet-sdk-core",
6
15
  "./skills/sodax-wallet-sdk-react",
7
16
  "./skills/sodax-dapp-kit"
package/AGENTS.md CHANGED
@@ -4,14 +4,16 @@
4
4
 
5
5
  ## What's here
6
6
 
7
- This package ships **four mode-gated skills** (`skills/<name>/SKILL.md`) — one per SODAX SDK package. Each skill bundles two long-form **knowledge** subtrees: `integration/knowledge/` (writing new v2 code) and `migration-v1-to-v2/knowledge/` (porting v1 → v2). Skills are action-oriented (when to use, workflow, anti-patterns, links into knowledge); knowledge is the reference material your workflow points at. SKILL.md gates by mode at the top — pick integration or migration based on the consumer signal.
7
+ This package ships **four mode-gated broad skills** (`skills/<name>/SKILL.md`) — one per SODAX SDK package — plus **nested granular per-feature skills** under `sodax-sdk` (one per Core SDK feature service). Each broad skill bundles two long-form **knowledge** subtrees: `integration/knowledge/` (writing new v2 code) and `migration-v1-to-v2/knowledge/` (porting v1 → v2). Granular skills are single-file SKILL.md that link into their parent's knowledge tree. Skills are action-oriented (when to use, workflow, anti-patterns, links into knowledge); knowledge is the reference material your workflow points at. SKILL.md gates by mode at the top — pick integration or migration based on the consumer signal.
8
8
 
9
- | SDK package | Skill |
10
- |---|---|
11
- | `@sodax/sdk` | `sodax-sdk` |
12
- | `@sodax/wallet-sdk-core` | `sodax-wallet-sdk-core` |
13
- | `@sodax/wallet-sdk-react` | `sodax-wallet-sdk-react` |
14
- | `@sodax/dapp-kit` | `sodax-dapp-kit` |
9
+ | SDK package | Broad skill | Granular per-feature skills |
10
+ |---|---|---|
11
+ | `@sodax/sdk` | `sodax-sdk` | `sodax-sdk/swap`, `sodax-sdk/money-market`, `sodax-sdk/bridge`, `sodax-sdk/staking`, `sodax-sdk/dex`, `sodax-sdk/migration`, `sodax-sdk/partner`, `sodax-sdk/recovery`, `sodax-sdk/backend-api` |
12
+ | `@sodax/wallet-sdk-core` | `sodax-wallet-sdk-core` | — |
13
+ | `@sodax/wallet-sdk-react` | `sodax-wallet-sdk-react` | — |
14
+ | `@sodax/dapp-kit` | `sodax-dapp-kit` | — |
15
+
16
+ **When to prefer a granular skill:** if the consumer has already picked a feature (e.g. *"swap with Sodax"*, *"supply on money market"*), load the matching granular skill — it's ~3 KB vs `sodax-sdk`'s ~13 KB and points at exactly the knowledge files needed for that feature. Load the broad `sodax-sdk` skill when the feature is undecided, the task spans multiple features, or the consumer is porting a full v1 codebase.
15
17
 
16
18
  > **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
19
 
@@ -21,6 +23,7 @@ Pick the consumer's situation, load the listed skills in order. Each entry names
21
23
 
22
24
  | Consumer is… | Load skills (mode) |
23
25
  |---|---|
26
+ | **Scaffolding ONE specific Core SDK feature** (swap, money-market, bridge, staking, dex, migration, partner, recovery, backend-api) | `sodax-sdk/<feature>` (granular, covers both modes via internal links). Add `sodax-wallet-sdk-core` (integration) if it signs and lives outside React. Skip the broad `sodax-sdk` skill |
24
27
  | **Building a NEW React dapp** | `sodax-wallet-sdk-react` (integration) → `sodax-dapp-kit` (integration) → (`sodax-sdk` (integration) only if dropping below dapp-kit) |
25
28
  | **Building a NEW React app, no dapp-kit** (calling the SDK directly) | `sodax-wallet-sdk-react` (integration) → `sodax-sdk` (integration) |
26
29
  | **Building a NEW Node / backend service or script** | `sodax-sdk` (integration) → `sodax-wallet-sdk-core` (integration; only if it signs) |
@@ -49,9 +52,11 @@ Each `SKILL.md` is short on purpose. Follow it like a procedure:
49
52
  ```
50
53
  packages/skills/
51
54
  ├── AGENTS.md # You are here
52
- ├── .claude-plugin/plugin.json # Skill registry (4 entries)
53
- └── skills/ # Each skill is mode-gated: SKILL.md + two knowledge subtrees
54
- ├── sodax-sdk/ {SKILL.md, integration/knowledge/, migration-v1-to-v2/knowledge/}
55
+ ├── .claude-plugin/plugin.json # Skill registry (broad + nested granular paths)
56
+ └── skills/ # Each broad skill is mode-gated; some have nested granular children
57
+ ├── sodax-sdk/ {SKILL.md, integration/knowledge/, migration-v1-to-v2/knowledge/,
58
+ │ <feature>/SKILL.md ×9 — swap, money-market, bridge, staking, dex,
59
+ │ migration, partner, recovery, backend-api}
55
60
  ├── sodax-wallet-sdk-core/ {SKILL.md, integration/knowledge/, migration-v1-to-v2/knowledge/}
56
61
  ├── sodax-wallet-sdk-react/ {SKILL.md, integration/knowledge/, migration-v1-to-v2/knowledge/ — incl. 4 .tsx example apps under integration/knowledge/examples/}
57
62
  └── sodax-dapp-kit/ {SKILL.md, integration/knowledge/, migration-v1-to-v2/knowledge/}
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "2.0.0-rc.7",
7
+ "version": "2.0.0-rc.9",
8
8
  "license": "MIT",
9
9
  "description": "AI-agent skills and knowledge for consumers of @sodax/* SDKs (Claude Code, Codex, Cursor, …)",
10
10
  "keywords": [
@@ -115,4 +115,4 @@ await approve({ params: bnUSDParams, walletProvider, action: 'migrate' });
115
115
 
116
116
  - [`../recipes/migration.md`](../recipes/migration.md) — full worked examples.
117
117
  - [`features/migration.md`](../../../migration-v1-to-v2/knowledge/features/migration.md) — v1 → v2 porting (the v1 dapp-kit had a single `useMigrate(spokeProvider)`-style hook; v2 split into 6).
118
- - `sodax-sdk`: `integration/knowledge/features/icx-bnusd-baln.md` — underlying SDK migration surface.
118
+ - `sodax-sdk`: `integration/knowledge/features/migration.md` — underlying SDK migration surface.
@@ -117,4 +117,4 @@ The biggest single API change in dapp-kit v2: v1 had a single `useMigrate(spokeP
117
117
 
118
118
  - [`features/migration.md`](../../../integration/knowledge/features/migration.md) — v2 reference.
119
119
  - [`recipes/migration.md`](../../../integration/knowledge/recipes/migration.md) — full v2 worked examples (ICX, BALN, bnUSD, revert).
120
- - `sodax-sdk`: `migration-v1-to-v2/knowledge/features/icx-bnusd-baln.md` — underlying SDK migration migration.
120
+ - `sodax-sdk`: `migration-v1-to-v2/knowledge/features/migration.md` — underlying SDK migration migration.
@@ -15,6 +15,46 @@ AGENTS.md routes you here when you're working with `@sodax/sdk` v2 — either wr
15
15
 
16
16
  For React dapps using hooks → use `sodax-dapp-kit` instead (this skill is still relevant for any unwrapped SDK call).
17
17
 
18
+ ## Prefer a granular skill if the feature is known
19
+
20
+ If the user has already picked a single feature, load the matching granular skill instead of this broad one — it loads ~3 KB of focused workflow vs this file's ~13 KB and links directly into the right knowledge files. The granular skills sit in the same family (`sdk`) and cover both integration and migration via internal cross-links.
21
+
22
+ | Feature | Granular skill | Trigger phrases |
23
+ |---|---|---|
24
+ | Intent-based swap (market + limit orders) | [`./swap/SKILL.md`](./swap/SKILL.md) | "swap with Sodax", "limit order", "cancel intent" |
25
+ | Cross-chain lending / borrowing | [`./money-market/SKILL.md`](./money-market/SKILL.md) | "supply", "borrow", "withdraw collateral", "repay" |
26
+ | Direct token bridge via vault | [`./bridge/SKILL.md`](./bridge/SKILL.md) | "bridge tokens", "cross-chain transfer" |
27
+ | SODA ↔ xSoda staking | [`./staking/SKILL.md`](./staking/SKILL.md) | "stake SODA", "instant unstake", "claim staking rewards" |
28
+ | Concentrated-liquidity LP | [`./dex/SKILL.md`](./dex/SKILL.md) | "LP position", "concentrated liquidity", "deposit hub assets" |
29
+ | ICX / bnUSD / BALN token migration to SODAX | [`./migration/SKILL.md`](./migration/SKILL.md) | "migrate ICX", "legacy bnUSD", "BALN lockup" (NOT v1→v2 SDK porting) |
30
+ | Partner fees | [`./partner/SKILL.md`](./partner/SKILL.md) | "claim partner fee", "partner auto-swap preference", "approve partner fee token" |
31
+ | Stuck-asset recovery | [`./recovery/SKILL.md`](./recovery/SKILL.md) | "recover stuck assets on Sonic", "RecoveryService", "withdrawHubAsset" |
32
+ | Backend HTTP client (intents, orderbook, MM reads) | [`./backend-api/SKILL.md`](./backend-api/SKILL.md) | "submit swap tx to backend", "getIntentByHash", "Sodax backend API", "custom IConfigApi" |
33
+
34
+ Load this broad skill (keep reading below) when:
35
+
36
+ - The feature is not yet decided.
37
+ - The task spans **multiple** features (e.g. swap + money-market in one flow).
38
+ - The consumer is doing a **full v1 → v2 port** of an existing codebase.
39
+
40
+ ## Out of scope
41
+
42
+ This skill documents the **SDK call sites** — what to import, how to construct `Sodax`, which method to call, and how to handle the `Result<T>`. It does **not** prescribe application-layer concerns.
43
+
44
+ ### Where to go for the things this skill does NOT cover
45
+
46
+ - **Wallet provider implementations** (`IEvmWalletProvider`, `ISolanaWalletProvider`, etc.) → **load the `sodax-wallet-sdk-core` skill** (integration mode). It ships ready-made provider classes for all 9 chain families, both private-key (Node / scripts) and browser-extension modes. This skill only treats wallet providers as a contract (`declare const evmWallet: IEvmWalletProvider`).
47
+ - **React hooks wrapping the SDK** → **load the `sodax-dapp-kit` skill** instead of this one.
48
+ - **Browser wallet connectivity** (connect / disconnect / chain switching for React apps) → **load the `sodax-wallet-sdk-react` skill**.
49
+
50
+ ### App-layer concerns the SDK is intentionally silent on
51
+
52
+ - **Multi-user state** (Telegram bot per-user wallets, dApp session storage, custodial vs non-custodial design). Hold one wallet-provider instance per user/chain at the app layer and pass it into each call — the SDK is stateless.
53
+ - **UI**, framework wiring, route handlers, webhooks. Pick your own framework (telegraf/grammy for bots, Next.js / Vite for web, etc.) — the SDK has no opinion.
54
+ - **Token discovery beyond `sodax.config`**. The SDK exposes `sodax.config.findSupportedTokenBySymbol(chainKey, symbol)` for per-chain lookups and `sodax.bridge.getBridgeableTokens(from, to, srcAddress)` / `sodax.bridge.isBridgeable({ from, to })` for vault-pair checks. There is no exhaustive "all bridgeable pairs across all chains" table — derive it at runtime if needed.
55
+
56
+ If the consumer needs a runnable end-to-end app (Node bot, CLI, full dApp), the right combination is: this skill (for SDK call sites) + `sodax-wallet-sdk-core` (for wallet providers) + the consumer's chosen framework code. The SDK does not ship an app skeleton.
57
+
18
58
  ---
19
59
 
20
60
  ## Integration mode (writing new v2 code)
@@ -31,7 +71,7 @@ Follow in order. Skipping `ai-rules.md` is the most common cause of agents rever
31
71
 
32
72
  1. Read [`integration/knowledge/ai-rules.md`](./integration/knowledge/ai-rules.md) — DO / DO NOT / workflow / stop conditions.
33
73
  2. Read [`integration/knowledge/quickstart.md`](./integration/knowledge/quickstart.md) — install, initialize, first-run troubleshooting.
34
- 3. For your feature, read [`integration/knowledge/features/`](./integration/knowledge/features/) — `swap.md`, `money-market.md`, `staking.md`, `bridge.md`, `dex.md`, `icx-bnusd-baln.md`, `auxiliary-services.md`.
74
+ 3. For your feature, read [`integration/knowledge/features/`](./integration/knowledge/features/) — `swap.md`, `money-market.md`, `staking.md`, `bridge.md`, `dex.md`, `migration.md`, `partner.md`, `recovery.md`, `backend-api.md`.
35
75
  4. For specific patterns (init, raw vs signed, chain narrowing, gas, testing, errors), read [`integration/knowledge/recipes/`](./integration/knowledge/recipes/).
36
76
  5. Lookups (chain keys, error codes, public API surface, wallet provider types, glossary) → [`integration/knowledge/reference/`](./integration/knowledge/reference/).
37
77
  6. Non-EVM quirks (Stellar trustline, BTC PSBT, Solana PDA, ICON, NEAR) → [`integration/knowledge/chain-specifics.md`](./integration/knowledge/chain-specifics.md).
@@ -44,29 +84,9 @@ Follow in order. Skipping `ai-rules.md` is the most common cause of agents rever
44
84
  4. **Signed vs raw is a discriminated union.** `WalletProviderSlot<K, Raw>` enforces at compile time: `{ raw: false, walletProvider }` for signing, `{ raw: true }` for unsigned-tx building. Mixing them is a TypeScript error.
45
85
  5. **Config is dynamic; overrides only land on `sodax.config`.** Always read via `sodax.config.*` (e.g. `sodax.config.spokeChainConfig[chainKey]`). Direct imports of `spokeChainConfig` / `sodaxConfig` from `@sodax/types` / `@sodax/sdk` are packaged-default snapshots and silently miss both `await sodax.config.initialize()` updates and `new Sodax(config)` overrides.
46
86
 
47
- ### Top traps to avoid (integration)
48
-
49
- 1. **Reaching for a `*SpokeProvider`.** They're deleted. Pass an object satisfying the chain-specific `I*WalletProvider` interface directly into the SDK call payload. Implementations come from your application — write your own or install `@sodax/wallet-sdk-core`.
50
- 2. **Forgetting `raw: false`.** Without the discriminator, `walletProvider` is rejected with "Object literal may only specify known properties." Add `raw: false` for signed flows; `raw: true` for unsigned-tx building.
51
- 3. **Importing from `@sodax/types` directly.** `@sodax/sdk` re-exports the entire `@sodax/types` surface. Add `@sodax/sdk` as your only dependency; importing `@sodax/types` separately risks version skew.
52
- 4. **Treating `Result<T>` as throw-on-failure.** v2 mutation methods do **not** throw on SDK-level failure — they resolve `{ ok: false, error }`. A `try/catch` only catches *exceptions* from inside `mutationFn` (e.g. missing `walletProvider`); it will **not** catch `RELAY_TIMEOUT` or `EXECUTION_FAILED`. Branch on `.ok`.
53
- 5. **Reading `xToken.xChainId` or hard-coding `*_MAINNET_CHAIN_ID`.** Renamed: `XToken.chainKey` and `ChainKeys.*`. v1 numeric/string chain-id constants are gone.
54
-
55
- ### Conventions agents must follow (integration)
87
+ ### Top traps, conventions, verification
56
88
 
57
- - **`Result<T>` discrimination on `.ok`.** Always branch on `result.ok` before reading `.value` or `.error`. Forward sub-Results without re-wrapping (`if (!sub.ok) return sub`).
58
- - **`(feature, code)` for error switching.** Use `isSodaxError(e)`, then `e.feature` and `e.code` for routing logic. Don't string-match on `e.message`.
59
- - **`ChainKeys.*` over hard-coded strings.** The set of supported chains evolves per release.
60
- - **No `as unknown as <Type>` double-casts.** v2 type narrowing makes them unnecessary — chain-key generic flow + `GetWalletProviderType<K>` resolves to the exact interface.
61
- - **Don't generate `try { await sodax.<method>(...) } catch` for SDK-level failures.** That catch never fires for `Result.!ok`. Branch on `result.ok`.
62
- - Import only from the package root: `import { Sodax, ChainKeys, type SpokeChainKey } from '@sodax/sdk'`. Don't deep-import from `dist/...`.
63
-
64
- ### Verification (integration)
65
-
66
- 1. `pnpm tsc --noEmit` from the consumer repo — must exit clean.
67
- 2. Every `await sodax.<feature>.<method>(...)` call site has `if (!result.ok)` branching.
68
- 3. No `xToken.xChainId`, no `*_MAINNET_CHAIN_ID`, no `*SpokeProvider` references.
69
- 4. `isSodaxError(e)` (not bare `instanceof SodaxError`) in cross-bundle code.
89
+ The DO / DO NOT / verification checklist lives in [`integration/knowledge/ai-rules.md`](./integration/knowledge/ai-rules.md) — read it before writing any call site. The biggest source of generated v1-style code is skipping it.
70
90
 
71
91
  ---
72
92
 
@@ -89,7 +109,7 @@ If the consumer has v1 fingerprints AND also wants new features: **do migration
89
109
  - [`breaking-changes/type-system.md`](./migration-v1-to-v2/knowledge/breaking-changes/type-system.md) — renames at `@sodax/types`, `ChainKeys`, `WalletProviderSlot`, `RpcConfig`, `IConfigApi` Result.
90
110
  - [`breaking-changes/architecture.md`](./migration-v1-to-v2/knowledge/breaking-changes/architecture.md) — `*SpokeProvider` deletion, `ConfigService`, relay reshape.
91
111
  - [`breaking-changes/result-and-errors.md`](./migration-v1-to-v2/knowledge/breaking-changes/result-and-errors.md) — throws → `Result<T>`; module errors → `SodaxError<C>`; v1↔v2 code crosswalk.
92
- 4. **Per-feature playbooks** under [`features/`](./migration-v1-to-v2/knowledge/features/) — `swap.md`, `money-market.md`, `staking.md`, `bridge.md`, `dex.md`, `icx-bnusd-baln.md`, `auxiliary-services.md` — read only the ones the consumer uses.
112
+ 4. **Per-feature playbooks** under [`features/`](./migration-v1-to-v2/knowledge/features/) — `swap.md`, `money-market.md`, `staking.md`, `bridge.md`, `dex.md`, `migration.md`, `partner.md`, `recovery.md`, `backend-api.md` — read only the ones the consumer uses.
93
113
  5. **Codemods + adapters** for mechanical replacement → [`recipes.md`](./migration-v1-to-v2/knowledge/recipes.md).
94
114
  6. **Cross-check** symbols in [`reference/`](./migration-v1-to-v2/knowledge/reference/) — `deleted-exports.md`, `error-code-crosswalk.md`, `return-shapes.md`, `sodax-config.md`.
95
115
 
@@ -107,30 +127,9 @@ Apply in this order — type-level changes don't affect behavior; runtime patter
107
127
 
108
128
  Then on every signed-call payload: drop `spokeProvider`, add `walletProvider`, add `raw: false` discriminator, rename `intentParams` → `params`. Plus add `srcChainKey` + `srcAddress` to every action params object (MM, staking, deposit, …).
109
129
 
110
- ### Top traps to avoid (migration)
111
-
112
- 1. **Reaching for a `*SpokeProvider`.** They're deleted. Pass `walletProvider` (an `I*WalletProvider` impl) directly in the call payload.
113
- 2. **`instanceof MoneyMarketError` (and other module error classes).** Deleted. Replace with `isSodaxError(e) && e.feature === 'moneyMarket'`.
114
- 3. **Destructuring cross-chain results as arrays.** v1 had `bridge()` returning a string and others returning tuples; v2 returns `TxHashPair = { srcChainTxHash, dstChainTxHash }` for **every** cross-chain mutation. Destructure as `{ srcChainTxHash, dstChainTxHash } = result.value`.
115
- 4. **Keeping `try/catch` to inspect v1 error codes.** v2 returns `Result<T>` — failure lives on `result.error.code`, not on a thrown error. The v2 code names changed too — see `reference/error-code-crosswalk.md`.
116
- 5. **Calling `getStakingInfo(hubAddress)`.** Renamed to `getStakingInfoFromSpoke(srcAddress, srcChainKey)`. `getStakingInfo` is not a public method anymore.
117
-
118
- ### DO NOT
119
-
120
- - Grep-replace `srcChain` → `srcChainKey` blindly. The `Intent` read shape keeps `srcChain` / `dstChain` as `IntentRelayChainId` (bigint). Only **request** types changed.
121
- - Assume `BalnSwapService` lock methods (`stake`, `unstake`, `claim`, `claimUnstaked`, `cancelUnstake`, `getDetailedUserLocks`) return `Result<T>`. They still throw — known carve-out. Keep `try/catch` for those specific calls.
122
- - Add `@sodax/types` as a peer dependency. It's bundled into `@sodax/sdk`'s public surface.
123
-
124
- ### Verification (migration)
125
-
126
- ```bash
127
- pnpm tsc --noEmit # must exit clean
128
- # No leftover v1 fingerprints:
129
- grep -rE '_MAINNET_CHAIN_ID\b|\bxChainId\b|\bSpokeChainId\b|\bSpokeProvider\b|hubAssets|moneyMarketSupportedTokens' src/ # empty
130
- grep -rE 'MoneyMarketError|IntentError|StakingError|BridgeError|MigrationError|AssetServiceError|ConcentratedLiquidityError|RelayError' src/ # empty
131
- ```
130
+ ### Top traps, DO NOT, verification
132
131
 
133
- Every `await sodax.<feature>.<method>(...)` call site must have `if (!result.ok)` branching (highest-leverage change — if you stop early, ensure result branching is at least in place).
132
+ The full DO / DO NOT list, mode-specific pitfalls, and verification protocol live in [`migration-v1-to-v2/knowledge/ai-rules.md`](./migration-v1-to-v2/knowledge/ai-rules.md) — read it before touching any call site. Highest-leverage rule: every `await sodax.<feature>.<method>(...)` call site must have `if (!result.ok)` branching.
134
133
 
135
134
  ---
136
135
 
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: sodax-sdk-backend-api
3
+ description: 'Granular skill for the @sodax/sdk v2 BackendApiService — HTTP client to the SODAX backend for intent lookup, swap-tx submission, solver orderbook, money-market position/reserve reads, and (internally) config fetching. Use when the task touches a backend read or write (e.g. "submit swap tx to Sodax backend", "Sodax getIntentByHash", "fetch money market position from Sodax backend", "Sodax orderbook", "Sodax BackendApiService", "implement custom IConfigApi sandbox"). Covers BOTH integration and the load-bearing v1 → v2 Result-wrapping migration. Skill links into the parent sodax-sdk knowledge tree.'
4
+ ---
5
+
6
+ # Backend API (Core SDK granular skill)
7
+
8
+ Granular skill for `BackendApiService` — `sodax.backendApi`. HTTP client used by every feature for reads + swap-tx submission. **Feature tag for errors** varies by call site (e.g. `'swap'` for `submitSwapTx`, `'moneyMarket'` for MM reads); errors always carry `error.context.api: 'backend'`.
9
+
10
+ ## Step 1 — Clarify with user before coding
11
+
12
+ 1. **New code or v1 → v2 port?** Note: v2's load-bearing change is `Result`-wrapping every method (v1 threw on failure).
13
+ 2. **Which category?**
14
+ - **Swap-related reads / writes:** `submitSwapTx`, `getSubmitSwapTxStatus`, `getOrderbook`, `getIntentByHash`, `getIntentByTxHash`, `getUserIntents`.
15
+ - **Money-market position reads:** `getMoneyMarketPosition`, `getAllMoneyMarketAssets`, `getMoneyMarketAsset`, `getMoneyMarketAssetBorrowers`, `getMoneyMarketAssetSuppliers`, `getAllMoneyMarketBorrowers`.
16
+ - **Config-API methods (implements `IConfigApi`):** `getAllConfig`, `getChains`, `getSwapTokens`, `getSwapTokensByChainId`, `getMoneyMarketTokens`, `getMoneyMarketReserveAssets`, `getMoneyMarketTokensByChainId`, `getRelayChainIdMap`.
17
+ 3. **Custom `IConfigApi` for sandbox / fixtures?** Every method must return `Promise<Result<T>>` in v2.
18
+
19
+ ## Integration workflow
20
+
21
+ 1. [`../integration/knowledge/ai-rules.md`](../integration/knowledge/ai-rules.md).
22
+ 2. [`../integration/knowledge/features/backend-api.md`](../integration/knowledge/features/backend-api.md) — `BackendApiService` API + `submitSwapTx` call shape + custom-backend pattern.
23
+ 3. For the `submitSwapTx` + `createIntent` flow → also load [`../swap/SKILL.md`](../swap/SKILL.md) or read [`../integration/knowledge/features/swap.md`](../integration/knowledge/features/swap.md) § "Backend submit-tx flow".
24
+ 4. Errors carry `error.context.api === 'backend'` → [`../integration/knowledge/recipes/result-and-errors.md`](../integration/knowledge/recipes/result-and-errors.md) and [`../integration/knowledge/reference/error-codes.md`](../integration/knowledge/reference/error-codes.md).
25
+
26
+ ### Backend-API-specific anti-patterns
27
+
28
+ - **Passing the `RelayExtraData` object** to `submitSwapTx.relayData`. The field is now `string` — pass `relayData.payload`.
29
+ - **Using v1 `srcChainId` (numeric)** on `SubmitSwapTxRequest`. Renamed to `srcChainKey: SpokeChainKey`.
30
+ - **Implementing `IConfigApi` with throw-on-error semantics.** v2 interface requires `Promise<Result<T>>` — every method.
31
+ - **Reading money-market position from `MoneyMarketService`.** Those reads live here on `BackendApiService`.
32
+
33
+ ## Migration workflow (v1 → v2)
34
+
35
+ 1. [`../migration-v1-to-v2/knowledge/ai-rules.md`](../migration-v1-to-v2/knowledge/ai-rules.md).
36
+ 2. [`../migration-v1-to-v2/knowledge/features/backend-api.md`](../migration-v1-to-v2/knowledge/features/backend-api.md) — the load-bearing change: every method now returns `Promise<Result<T>>`. Includes the `submitSwapTx` request-shape changes (`srcChainId` → `srcChainKey`, `relayData` object → string) and the `IConfigApi` sandbox-impl change.
37
+ 3. Cross-cutting `IConfigApi` Result-wrapping note → [`../migration-v1-to-v2/knowledge/breaking-changes/type-system.md`](../migration-v1-to-v2/knowledge/breaking-changes/type-system.md) § 6.
38
+
39
+ ## Verification
40
+
41
+ 1. `pnpm tsc --noEmit` clean.
42
+ 2. Every `await sodax.backendApi.<method>(...)` has `if (!result.ok)`.
43
+ 3. `SubmitSwapTxRequest` uses `srcChainKey` (not `srcChainId`) and `relayData: relayData.payload` (string).
44
+ 4. Any custom `IConfigApi` implementation returns `Promise<Result<T>>` from every method.
45
+
46
+ ## Related granular skills (same family)
47
+
48
+ - [`../swap/SKILL.md`](../swap/SKILL.md) — `submitSwapTx` is the backend half of the step-by-step swap flow.
49
+ - [`../money-market/SKILL.md`](../money-market/SKILL.md) — `BackendApiService` is the canonical source of MM position reads.
50
+ - [`../partner/SKILL.md`](../partner/SKILL.md), [`../recovery/SKILL.md`](../recovery/SKILL.md) — diagnostics for failures via intent / tx lookups.
51
+
52
+ For multi-feature tasks, load the broad [`sodax-sdk` skill](../SKILL.md).
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: sodax-sdk-bridge
3
+ description: 'Granular skill for the @sodax/sdk v2 bridge feature only — cross-chain token transfer via vault. Use when the task is specifically bridging (e.g. "bridge tokens cross-chain with Sodax", "Sodax bridge", "transfer USDC from Arbitrum to Stellar via Sodax", "check bridgeable amount"). The bridge() method returns `TxHashPair = { srcChainTxHash, dstChainTxHash }` for every cross-chain mutation. Covers BOTH integration (new v2 code) and migration (port v1 BridgeService). Skill links into the parent sodax-sdk knowledge tree. For React dapps, prefer sodax-dapp-kit.'
4
+ ---
5
+
6
+ # Bridge (Core SDK granular skill)
7
+
8
+ Granular skill for `BridgeService` — `sodax.bridge`. Feature tag: `'bridge'`.
9
+
10
+ ## Step 1 — Clarify with user before coding
11
+
12
+ 1. **New code or v1 → v2 port?**
13
+ 2. **Signed flow (frontend) or unsigned-tx (backend)?**
14
+ 3. **Need a bridgeable-amount precheck?** Vault deposit limits may cap the transfer; `getBridgeableAmount` (or equivalent) read tells you the cap before submitting.
15
+ 4. **Source / destination chains** — confirm both are supported spoke chains, and the destination address format matches the chain (vd Stellar address starts with `G`, Solana base58, Bitcoin specific encodings).
16
+
17
+ ## Integration workflow
18
+
19
+ 1. [`../integration/knowledge/ai-rules.md`](../integration/knowledge/ai-rules.md).
20
+ 2. [`../integration/knowledge/features/bridge.md`](../integration/knowledge/features/bridge.md) — API surface, `TxHashPair` return shape, bridgeable-amount reads.
21
+ 3. Path-specific recipe:
22
+ - Signed → [`../integration/knowledge/recipes/signed-tx-flow.md`](../integration/knowledge/recipes/signed-tx-flow.md)
23
+ - Unsigned → [`../integration/knowledge/recipes/raw-tx-flow.md`](../integration/knowledge/recipes/raw-tx-flow.md)
24
+ 4. Destination-chain quirks (Stellar trustline, BTC PSBT, Solana PDA) → [`../integration/knowledge/chain-specifics.md`](../integration/knowledge/chain-specifics.md).
25
+ 5. Errors (`feature: 'bridge'`) → [`../integration/knowledge/reference/error-codes.md`](../integration/knowledge/reference/error-codes.md).
26
+
27
+ ### Bridge-specific anti-patterns
28
+
29
+ - **Destructuring the return as an array or single hash.** v2 ALWAYS returns `{ srcChainTxHash, dstChainTxHash }` for cross-chain mutations — destructure by name.
30
+ - **Skipping the bridgeable-amount check.** Submitting an amount over the vault cap returns `EXECUTION_FAILED`; cheaper to check first.
31
+
32
+ ## Migration workflow (v1 → v2)
33
+
34
+ 1. [`../migration-v1-to-v2/knowledge/ai-rules.md`](../migration-v1-to-v2/knowledge/ai-rules.md).
35
+ 2. [`../migration-v1-to-v2/knowledge/features/bridge.md`](../migration-v1-to-v2/knowledge/features/bridge.md) — v1 `bridge()` returned a string; v2 returns `TxHashPair`. Update all destructuring sites.
36
+ 3. v1 `BridgeError` → v2 `SodaxError<C>` with `feature: 'bridge'`.
37
+
38
+ ## Verification
39
+
40
+ 1. `pnpm tsc --noEmit` clean.
41
+ 2. Every `await sodax.bridge.<method>(...)` has `if (!result.ok)`.
42
+ 3. No string-typed return destructuring at `bridge()` call sites.
43
+
44
+ ## Related granular skills (same family)
45
+
46
+ - [`../swap/SKILL.md`](../swap/SKILL.md) — for intent-based cross-chain swaps (different from a direct bridge: swap goes via a solver).
47
+ - [`../recovery/SKILL.md`](../recovery/SKILL.md) — `RecoveryService` for stuck assets on the hub.
48
+
49
+ For multi-feature tasks, load the broad [`sodax-sdk` skill](../SKILL.md).
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: sodax-sdk-dex
3
+ description: 'Granular skill for the @sodax/sdk v2 DEX feature only — Uniswap-V3-style concentrated liquidity positions on the hub, plus AssetService for hub-asset deposit/withdraw. Use when the task is LP positions (e.g. "Sodax concentrated liquidity", "create LP position on Sodax", "increase liquidity", "decrease liquidity", "claim LP fees", "deposit hub assets for LP"). Covers BOTH integration and migration. Skill links into the parent sodax-sdk knowledge tree. For React dapps, prefer sodax-dapp-kit.'
4
+ ---
5
+
6
+ # DEX (Core SDK granular skill)
7
+
8
+ Granular skill for `DexService` — facade owning `clService: ClService` (concentrated liquidity) and `assetService: AssetService` (hub-asset deposit/withdraw). Access via `sodax.dex.clService` and `sodax.dex.assetService`. Feature tag for errors: `'dex'`.
9
+
10
+ ## Step 1 — Clarify with user before coding
11
+
12
+ 1. **New code or v1 → v2 port?**
13
+ 2. **Which operation?**
14
+ - LP: `createPosition`, `increaseLiquidity`, `decreaseLiquidity`, `claimFees`, `closePosition`.
15
+ - Assets: `deposit` (spoke → hub-asset wrapper), `withdraw` (hub → spoke).
16
+ 3. **Does the position require an asset deposit first?** LP positions hold hub assets; the user must deposit from a spoke chain before opening a position.
17
+ 4. **Signed or unsigned-tx flow?**
18
+
19
+ ## Integration workflow
20
+
21
+ 1. [`../integration/knowledge/ai-rules.md`](../integration/knowledge/ai-rules.md).
22
+ 2. [`../integration/knowledge/features/dex.md`](../integration/knowledge/features/dex.md) — `ClService` + `AssetService` APIs, position lifecycle, tick math notes.
23
+ 3. Path-specific recipe:
24
+ - Signed → [`../integration/knowledge/recipes/signed-tx-flow.md`](../integration/knowledge/recipes/signed-tx-flow.md)
25
+ - Unsigned → [`../integration/knowledge/recipes/raw-tx-flow.md`](../integration/knowledge/recipes/raw-tx-flow.md)
26
+ 4. Errors (`feature: 'dex'`) → [`../integration/knowledge/reference/error-codes.md`](../integration/knowledge/reference/error-codes.md).
27
+
28
+ ### DEX-specific anti-patterns
29
+
30
+ - **Reaching for `sodax.cl` / `sodax.assets`.** Wrong paths — both services are reached via `sodax.dex` (i.e. `sodax.dex.clService.*` and `sodax.dex.assetService.*`). The `Sodax` facade exposes only `dex`.
31
+ - **Skipping `assetService.deposit` before opening a position.** LP positions reference hub-asset addresses; without deposit there's nothing to provide.
32
+ - **Confusing pool addresses on Sonic with spoke token addresses.** CL pools live on Sonic; the user-facing tokens live on spokes.
33
+
34
+ ## Migration workflow (v1 → v2)
35
+
36
+ 1. [`../migration-v1-to-v2/knowledge/ai-rules.md`](../migration-v1-to-v2/knowledge/ai-rules.md).
37
+ 2. [`../migration-v1-to-v2/knowledge/features/dex.md`](../migration-v1-to-v2/knowledge/features/dex.md) — v1 `ConcentratedLiquidityError` / `AssetServiceError` → v2 `SodaxError<C>` with the appropriate `feature` tag.
38
+
39
+ ## Verification
40
+
41
+ 1. `pnpm tsc --noEmit` clean.
42
+ 2. Every `await sodax.dex.clService.<method>(...)` and `await sodax.dex.assetService.<method>(...)` has `if (!result.ok)`.
43
+ 3. No `instanceof ConcentratedLiquidityError` / `AssetServiceError`.
44
+
45
+ ## Related granular skills (same family)
46
+
47
+ - [`../recovery/SKILL.md`](../recovery/SKILL.md) — `RecoveryService` for stuck hub-wallet LP assets.
48
+ - [`../backend-api/SKILL.md`](../backend-api/SKILL.md) — `BackendApiService` for position reads if surfaced there.
49
+
50
+ For multi-feature tasks, load the broad [`sodax-sdk` skill](../SKILL.md).
@@ -13,8 +13,10 @@ This tree documents v2 of the SDK for **new consumers** building against it. If
13
13
  | [`features/staking.md`](features/staking.md) | `StakingService`: SODA → xSoda — stake, unstake, instant unstake, claim, cancel; ratio + info reads. |
14
14
  | [`features/bridge.md`](features/bridge.md) | `BridgeService`: cross-chain token transfer via vault — `bridge`, `createBridgeIntent`, `getBridgeableAmount`, `getBridgeableTokens`. |
15
15
  | [`features/dex.md`](features/dex.md) | `ClService` (concentrated liquidity) + `AssetService`: position lifecycle (mint/increase/decrease), claim rewards, asset deposit/withdraw. |
16
- | [`features/icx-bnusd-baln.md`](features/icx-bnusd-baln.md) | `MigrationService` (the SDK module): ICX, bnUSD, BALN sub-services + lock management. |
17
- | [`features/auxiliary-services.md`](features/auxiliary-services.md) | `PartnerService` + `RecoveryService` + `BackendApiService` small APIs grouped together. |
16
+ | [`features/migration.md`](features/migration.md) | `MigrationService` (the SDK module): ICX, bnUSD, BALN sub-services + lock management. |
17
+ | [`features/partner.md`](features/partner.md) | `PartnerService` — partner-fee handling. |
18
+ | [`features/recovery.md`](features/recovery.md) | `RecoveryService` — withdraw stuck hub-wallet assets. |
19
+ | [`features/backend-api.md`](features/backend-api.md) | `BackendApiService` — HTTP client for backend reads + swap-tx submission. |
18
20
  | [`recipes/`](recipes/) | Copy-pasteable patterns: SDK initialization, `Result` + error discrimination, raw-tx flow, signed-tx flow, chain-key narrowing + cast-at-boundary, testing (mocks/stubs), gas estimation, backend-server init. |
19
21
  | [`reference/`](reference/) | Lookup tables: 20-chain `ChainKeys` table with family + relay id, `I*WalletProvider` interfaces, 13 `SodaxErrorCode` meanings + per-feature narrow unions, public API surface (incl. `@sodax/types` re-export rule), glossary. |
20
22
  | [`chain-specifics.md`](chain-specifics.md) | Non-EVM quirks — Stellar trustline check/request, Bitcoin PSBT + Radfi auth/session, Solana PDA derivation, ICON Hana wallet + chain-key string, NEAR connector discovery. |
@@ -32,7 +32,7 @@ DO / DO NOT / workflow / stop conditions for AI agents writing `@sodax/sdk` v2 c
32
32
  - **DO NOT** import from `@sodax/sdk/dist/...`. Deep imports are unstable across releases; only the package root barrel is the public contract.
33
33
  - **DO NOT** add `@sodax/types` as a separate dependency. It's bundled / re-exported via `@sodax/sdk`. Adding it independently invites version skew.
34
34
  - **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 `bridge.bridge`, `staking.{stake,unstake,instantUnstake,claim,cancelUnstake}`, `dex.assetService.{deposit,withdraw}`, `dex.clService.{supplyLiquidity,increaseLiquidity,decreaseLiquidity,claimRewards}`, `moneyMarket.{supply,borrow,withdraw,repay}`, `migration.{migratebnUSD,migrateIcxToSoda,revertMigrateSodaToIcx,migrateBaln}` — all of them.
35
- - **DO NOT** treat method names from `MoneyMarketService` as the source of MM reads. `getReservesData`, `getUserReservesData`, `getATokensBalances`, etc. live on `sodax.backendApi`, not `sodax.moneyMarket`. See [`features/auxiliary-services.md`](features/auxiliary-services.md) § "BackendApiService".
35
+ - **DO NOT** treat method names from `MoneyMarketService` as the source of MM reads. `getReservesData`, `getUserReservesData`, `getATokensBalances`, etc. live on `sodax.backendApi`, not `sodax.moneyMarket`. See [`features/backend-api.md`](features/backend-api.md).
36
36
  - **DO NOT** reach for an `intentRelayApi` property on the `Sodax` instance — there is no such property. The relay layer is exposed as two top-level functions, `relayTxAndWaitPacket` and `submitTransaction` (re-exported from `@sodax/sdk`). Call them directly if you need custom relay orchestration.
37
37
  - **DO NOT** call `getStakeRatio` and treat its return as `Result<bigint>`. It's `Result<[xSodaAmount, previewDepositAmount]>` — a tuple of two bigints.
38
38
  - **DO NOT** assume `BalnSwapService` lock-management methods (`stake`, `unstake`, `claim`, `claimUnstaked`, `cancelUnstake`, `getDetailedUserLocks`) return `Result<T>`. They still throw on error in v2 — known carve-out. Wrap them in `try/catch`.
@@ -356,23 +356,7 @@ class SodaxError<C extends SodaxErrorCode = SodaxErrorCode> extends Error {
356
356
 
357
357
  ### The 13 codes
358
358
 
359
- | Code | Meaning |
360
- |---|---|
361
- | `VALIDATION_FAILED` | Pre-flight invariant tripped. |
362
- | `INTENT_CREATION_FAILED` | Building the intent / payload failed. |
363
- | `EXECUTION_FAILED` | Orchestrator-level catch-all for multi-step ops. |
364
- | `TX_VERIFICATION_FAILED` | Spoke-side `verifyTxHash` returned false / threw. |
365
- | `TX_SUBMIT_FAILED` | Spoke tx landed; relay POST submit failed. |
366
- | `RELAY_TIMEOUT` | Destination packet didn't reach `executed` within timeout. |
367
- | `RELAY_FAILED` | Relay polling outage / unrecognised relay error. |
368
- | `APPROVE_FAILED` | Token approval call failed. |
369
- | `ALLOWANCE_CHECK_FAILED` | Reading on-chain allowance failed. |
370
- | `GAS_ESTIMATION_FAILED` | Gas estimation returned an error. |
371
- | `LOOKUP_FAILED` | Read-only on-chain query / off-chain config fetch. |
372
- | `EXTERNAL_API_ERROR` | Upstream API call failed (solver, backend). |
373
- | `UNKNOWN` | Last-resort catch in an outer `try`. Should be rare. |
374
-
375
- The full per-code semantics, common context fields, per-feature narrow unions, and retry guidance are in [`reference/`](reference/) § "Error codes".
359
+ The closed code vocabulary is the same 13 names across every feature — see [`reference/error-codes.md`](reference/error-codes.md) for the full table, per-code semantics, common `context` field shapes, per-feature narrow unions, and retry guidance.
376
360
 
377
361
  ### `(feature, code)` discrimination
378
362
 
@@ -518,7 +502,7 @@ You drop down to the relay layer only when:
518
502
 
519
503
  ### Cross-references
520
504
 
521
- - `RecoveryService` for pulling stuck hub-wallet assets back to a spoke chain: see [`features/auxiliary-services.md`](features/auxiliary-services.md).
505
+ - `RecoveryService` for pulling stuck hub-wallet assets back to a spoke chain: see [`features/recovery.md`](features/recovery.md).
522
506
  - Per-feature error codes related to relay (e.g. `'TX_SUBMIT_FAILED'`, `'RELAY_TIMEOUT'`): [`reference/`](reference/) § "Error codes".
523
507
 
524
508
  ---
@@ -9,8 +9,10 @@ One file per feature service. Each file documents the v2 API surface, common cal
9
9
  | [`staking.md`](staking.md) | `StakingService` | SODA → xSoda staking via ERC-4626 vault. Stake, unstake (with penalty curve), instant unstake (slippage), claim, cancel. |
10
10
  | [`bridge.md`](bridge.md) | `BridgeService` | Cross-chain token transfer via vault. `bridge` returns `TxHashPair = { srcChainTxHash, dstChainTxHash }`. Bridgeable-amount queries respect vault deposit limits. |
11
11
  | [`dex.md`](dex.md) | `ClService` + `AssetService` | Uniswap-V3-style concentrated liquidity positions. Asset deposit/withdraw. Increase/decrease/claim flows. |
12
- | [`icx-bnusd-baln.md`](icx-bnusd-baln.md) | `MigrationService` (the SDK module — not v1→v2 porting) | Legacy ICON ecosystem token migration. ICX ↔ SODA, legacy bnUSD ↔ new bnUSD, BALN → SODA with lockup multipliers. |
13
- | [`auxiliary-services.md`](auxiliary-services.md) | `PartnerService` + `RecoveryService` + `BackendApiService` | Three small APIs grouped together: partner-fee claiming, hub-wallet asset recovery, backend HTTP client. |
12
+ | [`migration.md`](migration.md) | `MigrationService` (the SDK module — not v1→v2 porting) | Legacy ICON ecosystem token migration. ICX ↔ SODA, legacy bnUSD ↔ new bnUSD, BALN → SODA with lockup multipliers. |
13
+ | [`partner.md`](partner.md) | `PartnerService` | Partner-fee handling: token approval, auto-swap preferences, fee-claim flows. |
14
+ | [`recovery.md`](recovery.md) | `RecoveryService` | Withdraw stuck hub-wallet assets back to a spoke chain. |
15
+ | [`backend-api.md`](backend-api.md) | `BackendApiService` | HTTP client for backend services: swap-tx submission, intent / orderbook lookups, money-market reads. |
14
16
 
15
17
  All feature services are constructed and wired by the `Sodax` facade. You don't instantiate them directly — access them via `sodax.swaps`, `sodax.moneyMarket`, etc. See [`../architecture.md`](../architecture.md) for the service graph.
16
18
 
@@ -0,0 +1,81 @@
1
+ # Backend API — `BackendApiService`
2
+
3
+ HTTP client for backend services. Provides intent lookup, swap-tx submission, solver orderbook queries, money-market position/reserve reads, and (internally) config fetching. Most consumer-side code uses just `submitSwapTx`, `getIntentByHash` / `getIntentByTxHash`, and the money-market read methods.
4
+
5
+ Access: `sodax.backendApi`. Service class: `BackendApiService`. **Feature tag for errors:** appears under multiple features depending on the call site (`'swap'` for `submitSwapTx`, `'moneyMarket'` for MM-related reads, etc.); errors carry `error.context.api: 'backend'`.
6
+
7
+ ## Methods
8
+
9
+ ```ts
10
+ // Swap-related
11
+ sodax.backendApi.submitSwapTx(request, config?): Promise<Result<SubmitSwapTxResponse>>;
12
+ sodax.backendApi.getSubmitSwapTxStatus(...): Promise<Result<...>>;
13
+ sodax.backendApi.getOrderbook(...): Promise<Result<OrderbookEntry[]>>;
14
+ sodax.backendApi.getIntentByHash(intentHash, config?): Promise<Result<IntentResponse>>;
15
+ sodax.backendApi.getIntentByTxHash(txHash, config?): Promise<Result<IntentResponse>>;
16
+ sodax.backendApi.getUserIntents(...): Promise<Result<IntentResponse[]>>;
17
+
18
+ // Money-market reads (these are the canonical reads for MM positions/reserves;
19
+ // MoneyMarketService does NOT expose getReservesData / getUserReservesData / etc.)
20
+ sodax.backendApi.getMoneyMarketPosition(...): Promise<Result<...>>;
21
+ sodax.backendApi.getAllMoneyMarketAssets(config?): Promise<Result<MoneyMarketAsset[]>>;
22
+ sodax.backendApi.getMoneyMarketAsset(reserveAddress, config?): Promise<Result<MoneyMarketAsset>>;
23
+ sodax.backendApi.getMoneyMarketAssetBorrowers(...): Promise<Result<...>>;
24
+ sodax.backendApi.getMoneyMarketAssetSuppliers(...): Promise<Result<...>>;
25
+ sodax.backendApi.getAllMoneyMarketBorrowers(...): Promise<Result<...>>;
26
+
27
+ // Config-API methods (used internally by ConfigService — implements `IConfigApi`)
28
+ sodax.backendApi.getAllConfig(config?): Promise<Result<GetAllConfigApiResponse>>;
29
+ sodax.backendApi.getChains(config?): Promise<Result<GetChainsApiResponse>>;
30
+ sodax.backendApi.getSwapTokens(config?): Promise<Result<GetSwapTokensApiResponse>>;
31
+ sodax.backendApi.getSwapTokensByChainId(...): Promise<Result<XToken[]>>;
32
+ sodax.backendApi.getMoneyMarketTokens(config?): Promise<Result<GetMoneyMarketTokensApiResponse>>;
33
+ sodax.backendApi.getMoneyMarketReserveAssets(...): Promise<Result<...>>;
34
+ sodax.backendApi.getMoneyMarketTokensByChainId(...): Promise<Result<XToken[]>>;
35
+ sodax.backendApi.getRelayChainIdMap(config?): Promise<Result<GetRelayChainIdMapApiResponse>>;
36
+ ```
37
+
38
+ All methods return `Result<T, SodaxError>` where the error carries `feature: 'swap' | 'moneyMarket' | …` (depending on call site) and `error.context.api === 'backend'`.
39
+
40
+ ## Common call shape — `submitSwapTx`
41
+
42
+ After `sodax.swaps.createIntent({ params, raw: false, walletProvider })` returns:
43
+
44
+ ```ts
45
+ const submitResult = await sodax.backendApi.submitSwapTx({
46
+ txHash: spokeTxHash as string,
47
+ srcChainKey: src.chain,
48
+ walletAddress: '0x…',
49
+ intent: swapIntentData,
50
+ relayData: relayData.payload, // string, not the RelayExtraData object
51
+ });
52
+
53
+ if (!submitResult.ok) return;
54
+ ```
55
+
56
+ ## Custom backend (sandbox / fixtures)
57
+
58
+ `SodaxConfig` does not expose a typed slot to inject a custom `IConfigApi` implementation at construction. Two supported patterns:
59
+
60
+ 1. **Point at a local mock backend** via `SodaxConfig.api.baseURL`:
61
+
62
+ ```ts
63
+ const sodax = new Sodax({
64
+ api: { baseURL: 'http://localhost:4000' },
65
+ });
66
+ await sodax.config.initialize();
67
+ ```
68
+
69
+ `SodaxConfig.api` is `ApiConfig` (`{ baseURL, timeout, headers }`) — pass any subset via `DeepPartial`.
70
+
71
+ 2. **Inject your own `BackendApiService`-compatible mock at the app layer** (dependency-injected where you control the `Sodax` instance), rather than via the constructor.
72
+
73
+ The `IConfigApi` interface itself still matters for both patterns — every method returns `Promise<Result<T>>` in v2, so any mock or local server must conform. See [`../architecture.md`](../architecture.md) § 4 "Custom backend" for the authoritative reference.
74
+
75
+ ## Cross-references
76
+
77
+ - v1 → v2 migration of `BackendApiService` (the load-bearing change: every method now returns `Promise<Result<T>>`): [`features/backend-api.md`](../../../migration-v1-to-v2/knowledge/features/backend-api.md).
78
+ - The full `submitSwapTx` flow with `createIntent` upstream: [`./swap.md`](swap.md) § "Backend submit-tx flow".
79
+ - Partner-fee handling (separate service): [`./partner.md`](partner.md).
80
+ - Stuck-asset recovery (separate service): [`./recovery.md`](recovery.md).
81
+ - Error model context fields (`error.context.api`, `error.context.method`): [`../reference/`](../reference/) § 3.
@@ -76,6 +76,42 @@ const { tx, intent, relayData } = result.value;
76
76
  // Submit relayData.payload via your own relay infrastructure if needed.
77
77
  ```
78
78
 
79
+ ### Hub as source (Sonic → spoke)
80
+
81
+ `srcChainKey` accepts `ChainKeys.SONIC_MAINNET` too — the SDK routes through the user's hub-wallet abstraction (instead of a spoke deposit) and then triggers the destination withdrawal. The call shape is the same; only the chain key changes:
82
+
83
+ ```ts
84
+ const sodaSonic = sodax.config.findSupportedTokenBySymbol(ChainKeys.SONIC_MAINNET, 'SODA');
85
+ const sodaBase = sodax.config.findSupportedTokenBySymbol(ChainKeys.BASE_MAINNET, 'SODA');
86
+ if (!sodaSonic || !sodaBase) throw new Error('SODA missing from config');
87
+
88
+ // 1. Confirm the pair is vault-bridgeable (synchronous, config-derived).
89
+ if (!sodax.bridge.isBridgeable({ from: sodaSonic, to: sodaBase })) {
90
+ // Fall back to swap if needed — different vaults aren't bridgeable.
91
+ return;
92
+ }
93
+
94
+ // 2. (Optional) check the vault-side cap.
95
+ const limit = await sodax.bridge.getBridgeableAmount(sodaSonic, sodaBase);
96
+
97
+ // 3. Execute. srcChainKey is the hub.
98
+ const result = await sodax.bridge.bridge({
99
+ params: {
100
+ srcChainKey: ChainKeys.SONIC_MAINNET,
101
+ srcAddress: (await evmWp.getWalletAddress()) as `0x${string}`,
102
+ srcAsset: sodaSonic.address,
103
+ amount: parseUnits('1', sodaSonic.decimals),
104
+ dstChainKey: ChainKeys.BASE_MAINNET,
105
+ dstAddress: recipientOnBase,
106
+ dstAsset: sodaBase.address,
107
+ },
108
+ raw: false,
109
+ walletProvider: evmWp,
110
+ });
111
+ ```
112
+
113
+ Internally `bridge()` branches on `isHubChainKeyType(srcChainKey)` and uses the user's hub wallet abstraction as the spender (the assetManager spoke address is used for non-hub sources). For allowance and approval flows, treat Sonic-as-source the same as any other EVM source — `isAllowanceValid` and `approve` use the same parameter shape.
114
+
79
115
  ### Bridgeable-amount check
80
116
 
81
117
  Respects vault deposit limits (spoke→hub) and asset-manager balance (hub→spoke). Pass the source and destination tokens as full `XToken` objects (each carries its own `chainKey`):
@@ -8,7 +8,7 @@ Migration of legacy ICON ecosystem tokens to the SODAX hub. Three sub-services:
8
8
 
9
9
  Access: `sodax.migration`. Service class: `MigrationService` (with sub-services `sodax.migration.icxMigration`, `sodax.migration.bnUSDMigrationService`, `sodax.migration.balnSwapService`). Feature tag for errors: `'migration'`.
10
10
 
11
- > Don't confuse this feature (the `MigrationService` SDK module) with the v1 → v2 SDK port itself. They share the word "migration" but are independent concerns. The v1 → v2 port playbook lives at [`features/icx-bnusd-baln.md`](../../../migration-v1-to-v2/knowledge/features/icx-bnusd-baln.md).
11
+ > Don't confuse this feature (the `MigrationService` SDK module) with the v1 → v2 SDK port itself. They share the word "migration" but are independent concerns. The v1 → v2 port playbook lives at [`features/migration.md`](../../../migration-v1-to-v2/knowledge/features/migration.md).
12
12
 
13
13
  ## How it works
14
14
 
@@ -177,5 +177,5 @@ try {
177
177
 
178
178
  ## Cross-references
179
179
 
180
- - v1 → v2 migration of this feature: [`features/icx-bnusd-baln.md`](../../../migration-v1-to-v2/knowledge/features/icx-bnusd-baln.md).
180
+ - v1 → v2 migration of this feature: [`features/migration.md`](../../../migration-v1-to-v2/knowledge/features/migration.md).
181
181
  - Architecture (relay layer's `phase: 'destinationExecution'` for bnUSD): [`../architecture.md`](../architecture.md) § 9.