@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.
Files changed (197) hide show
  1. package/.claude-plugin/plugin.json +13 -0
  2. package/AGENTS.md +81 -0
  3. package/LICENSE +21 -0
  4. package/README.md +49 -0
  5. package/knowledge/dapp-kit/AGENTS.md +50 -0
  6. package/knowledge/dapp-kit/integration/README.md +49 -0
  7. package/knowledge/dapp-kit/integration/ai-rules.md +80 -0
  8. package/knowledge/dapp-kit/integration/architecture.md +276 -0
  9. package/knowledge/dapp-kit/integration/features/README.md +29 -0
  10. package/knowledge/dapp-kit/integration/features/auxiliary-services.md +169 -0
  11. package/knowledge/dapp-kit/integration/features/bitcoin.md +87 -0
  12. package/knowledge/dapp-kit/integration/features/bridge.md +91 -0
  13. package/knowledge/dapp-kit/integration/features/dex.md +152 -0
  14. package/knowledge/dapp-kit/integration/features/migration.md +118 -0
  15. package/knowledge/dapp-kit/integration/features/money-market.md +144 -0
  16. package/knowledge/dapp-kit/integration/features/staking.md +123 -0
  17. package/knowledge/dapp-kit/integration/features/swap.md +101 -0
  18. package/knowledge/dapp-kit/integration/quickstart.md +188 -0
  19. package/knowledge/dapp-kit/integration/recipes/README.md +136 -0
  20. package/knowledge/dapp-kit/integration/recipes/backend-queries.md +157 -0
  21. package/knowledge/dapp-kit/integration/recipes/bitcoin.md +193 -0
  22. package/knowledge/dapp-kit/integration/recipes/bridge.md +174 -0
  23. package/knowledge/dapp-kit/integration/recipes/dex.md +204 -0
  24. package/knowledge/dapp-kit/integration/recipes/invalidations.md +115 -0
  25. package/knowledge/dapp-kit/integration/recipes/migration.md +212 -0
  26. package/knowledge/dapp-kit/integration/recipes/money-market.md +207 -0
  27. package/knowledge/dapp-kit/integration/recipes/mutation-error-handling.md +118 -0
  28. package/knowledge/dapp-kit/integration/recipes/observability.md +93 -0
  29. package/knowledge/dapp-kit/integration/recipes/setup.md +168 -0
  30. package/knowledge/dapp-kit/integration/recipes/staking.md +202 -0
  31. package/knowledge/dapp-kit/integration/recipes/swap.md +272 -0
  32. package/knowledge/dapp-kit/integration/recipes/wallet-connectivity.md +128 -0
  33. package/knowledge/dapp-kit/integration/reference/README.md +12 -0
  34. package/knowledge/dapp-kit/integration/reference/glossary.md +190 -0
  35. package/knowledge/dapp-kit/integration/reference/hooks-index.md +190 -0
  36. package/knowledge/dapp-kit/integration/reference/public-api.md +110 -0
  37. package/knowledge/dapp-kit/integration/reference/querykey-conventions.md +179 -0
  38. package/knowledge/dapp-kit/migration/README.md +60 -0
  39. package/knowledge/dapp-kit/migration/ai-rules.md +81 -0
  40. package/knowledge/dapp-kit/migration/breaking-changes/hook-signatures.md +233 -0
  41. package/knowledge/dapp-kit/migration/breaking-changes/querykey-conventions.md +108 -0
  42. package/knowledge/dapp-kit/migration/breaking-changes/result-handling.md +211 -0
  43. package/knowledge/dapp-kit/migration/breaking-changes/sdk-leakage.md +167 -0
  44. package/knowledge/dapp-kit/migration/checklist.md +89 -0
  45. package/knowledge/dapp-kit/migration/features/README.md +34 -0
  46. package/knowledge/dapp-kit/migration/features/auxiliary-services.md +114 -0
  47. package/knowledge/dapp-kit/migration/features/bitcoin.md +88 -0
  48. package/knowledge/dapp-kit/migration/features/bridge.md +160 -0
  49. package/knowledge/dapp-kit/migration/features/dex.md +101 -0
  50. package/knowledge/dapp-kit/migration/features/migration.md +120 -0
  51. package/knowledge/dapp-kit/migration/features/money-market.md +139 -0
  52. package/knowledge/dapp-kit/migration/features/staking.md +109 -0
  53. package/knowledge/dapp-kit/migration/features/swap.md +133 -0
  54. package/knowledge/dapp-kit/migration/recipes.md +185 -0
  55. package/knowledge/dapp-kit/migration/reference/README.md +15 -0
  56. package/knowledge/dapp-kit/migration/reference/deleted-hooks.md +110 -0
  57. package/knowledge/dapp-kit/migration/reference/error-shape-crosswalk.md +144 -0
  58. package/knowledge/dapp-kit/migration/reference/renamed-hooks.md +68 -0
  59. package/knowledge/sdk/AGENTS.md +41 -0
  60. package/knowledge/sdk/integration/README.md +41 -0
  61. package/knowledge/sdk/integration/ai-rules.md +75 -0
  62. package/knowledge/sdk/integration/architecture.md +533 -0
  63. package/knowledge/sdk/integration/chain-specifics.md +189 -0
  64. package/knowledge/sdk/integration/features/README.md +19 -0
  65. package/knowledge/sdk/integration/features/auxiliary-services.md +189 -0
  66. package/knowledge/sdk/integration/features/bridge.md +136 -0
  67. package/knowledge/sdk/integration/features/dex.md +182 -0
  68. package/knowledge/sdk/integration/features/icx-bnusd-baln.md +181 -0
  69. package/knowledge/sdk/integration/features/money-market.md +198 -0
  70. package/knowledge/sdk/integration/features/staking.md +166 -0
  71. package/knowledge/sdk/integration/features/swap.md +207 -0
  72. package/knowledge/sdk/integration/quickstart.md +213 -0
  73. package/knowledge/sdk/integration/recipes/README.md +21 -0
  74. package/knowledge/sdk/integration/recipes/backend-server-init.md +69 -0
  75. package/knowledge/sdk/integration/recipes/chain-key-narrowing.md +65 -0
  76. package/knowledge/sdk/integration/recipes/gas-estimation.md +33 -0
  77. package/knowledge/sdk/integration/recipes/initialize-sodax.md +78 -0
  78. package/knowledge/sdk/integration/recipes/raw-tx-flow.md +71 -0
  79. package/knowledge/sdk/integration/recipes/result-and-errors.md +104 -0
  80. package/knowledge/sdk/integration/recipes/signed-tx-flow.md +46 -0
  81. package/knowledge/sdk/integration/recipes/testing.md +101 -0
  82. package/knowledge/sdk/integration/reference/README.md +18 -0
  83. package/knowledge/sdk/integration/reference/chain-keys.md +67 -0
  84. package/knowledge/sdk/integration/reference/error-codes.md +165 -0
  85. package/knowledge/sdk/integration/reference/glossary.md +32 -0
  86. package/knowledge/sdk/integration/reference/public-api.md +138 -0
  87. package/knowledge/sdk/integration/reference/wallet-providers.md +62 -0
  88. package/knowledge/sdk/migration/README.md +58 -0
  89. package/knowledge/sdk/migration/ai-rules.md +80 -0
  90. package/knowledge/sdk/migration/breaking-changes/architecture.md +344 -0
  91. package/knowledge/sdk/migration/breaking-changes/result-and-errors.md +363 -0
  92. package/knowledge/sdk/migration/breaking-changes/type-system.md +341 -0
  93. package/knowledge/sdk/migration/checklist.md +67 -0
  94. package/knowledge/sdk/migration/features/README.md +35 -0
  95. package/knowledge/sdk/migration/features/auxiliary-services.md +156 -0
  96. package/knowledge/sdk/migration/features/bridge.md +128 -0
  97. package/knowledge/sdk/migration/features/dex.md +143 -0
  98. package/knowledge/sdk/migration/features/icx-bnusd-baln.md +151 -0
  99. package/knowledge/sdk/migration/features/money-market.md +214 -0
  100. package/knowledge/sdk/migration/features/staking.md +138 -0
  101. package/knowledge/sdk/migration/features/swap.md +198 -0
  102. package/knowledge/sdk/migration/recipes.md +350 -0
  103. package/knowledge/sdk/migration/reference/README.md +18 -0
  104. package/knowledge/sdk/migration/reference/deleted-exports.md +127 -0
  105. package/knowledge/sdk/migration/reference/error-code-crosswalk.md +104 -0
  106. package/knowledge/sdk/migration/reference/return-shapes.md +49 -0
  107. package/knowledge/sdk/migration/reference/sodax-config.md +145 -0
  108. package/knowledge/wallet-sdk-core/AGENTS.md +43 -0
  109. package/knowledge/wallet-sdk-core/integration/README.md +108 -0
  110. package/knowledge/wallet-sdk-core/integration/ai-rules.md +141 -0
  111. package/knowledge/wallet-sdk-core/integration/architecture.md +212 -0
  112. package/knowledge/wallet-sdk-core/integration/features/README.md +22 -0
  113. package/knowledge/wallet-sdk-core/integration/features/bitcoin.md +103 -0
  114. package/knowledge/wallet-sdk-core/integration/features/evm.md +102 -0
  115. package/knowledge/wallet-sdk-core/integration/features/icon.md +88 -0
  116. package/knowledge/wallet-sdk-core/integration/features/injective.md +92 -0
  117. package/knowledge/wallet-sdk-core/integration/features/near.md +92 -0
  118. package/knowledge/wallet-sdk-core/integration/features/solana.md +104 -0
  119. package/knowledge/wallet-sdk-core/integration/features/stacks.md +91 -0
  120. package/knowledge/wallet-sdk-core/integration/features/stellar.md +95 -0
  121. package/knowledge/wallet-sdk-core/integration/features/sui.md +96 -0
  122. package/knowledge/wallet-sdk-core/integration/quickstart.md +259 -0
  123. package/knowledge/wallet-sdk-core/integration/recipes/README.md +15 -0
  124. package/knowledge/wallet-sdk-core/integration/recipes/bridge-to-sdk.md +145 -0
  125. package/knowledge/wallet-sdk-core/integration/recipes/defaults-and-overrides.md +159 -0
  126. package/knowledge/wallet-sdk-core/integration/recipes/library-exports.md +129 -0
  127. package/knowledge/wallet-sdk-core/integration/recipes/setup-browser-extension.md +137 -0
  128. package/knowledge/wallet-sdk-core/integration/recipes/setup-private-key.md +115 -0
  129. package/knowledge/wallet-sdk-core/integration/recipes/sign-and-broadcast.md +201 -0
  130. package/knowledge/wallet-sdk-core/integration/recipes/testing.md +163 -0
  131. package/knowledge/wallet-sdk-core/integration/reference/README.md +13 -0
  132. package/knowledge/wallet-sdk-core/integration/reference/chain-support.md +65 -0
  133. package/knowledge/wallet-sdk-core/integration/reference/glossary.md +28 -0
  134. package/knowledge/wallet-sdk-core/integration/reference/interfaces.md +131 -0
  135. package/knowledge/wallet-sdk-core/integration/reference/provider-classes.md +54 -0
  136. package/knowledge/wallet-sdk-core/integration/reference/public-api.md +128 -0
  137. package/knowledge/wallet-sdk-core/migration/README.md +84 -0
  138. package/knowledge/wallet-sdk-core/migration/ai-rules.md +139 -0
  139. package/knowledge/wallet-sdk-core/migration/breaking-changes/README.md +14 -0
  140. package/knowledge/wallet-sdk-core/migration/breaking-changes/base-wallet-provider.md +52 -0
  141. package/knowledge/wallet-sdk-core/migration/breaking-changes/defaults-config.md +57 -0
  142. package/knowledge/wallet-sdk-core/migration/breaking-changes/folder-layout.md +99 -0
  143. package/knowledge/wallet-sdk-core/migration/breaking-changes/library-exports.md +58 -0
  144. package/knowledge/wallet-sdk-core/migration/checklist.md +62 -0
  145. package/knowledge/wallet-sdk-core/migration/recipes/README.md +12 -0
  146. package/knowledge/wallet-sdk-core/migration/recipes/adopt-defaults.md +84 -0
  147. package/knowledge/wallet-sdk-core/migration/recipes/adopt-library-exports.md +99 -0
  148. package/knowledge/wallet-sdk-core/migration/reference/README.md +12 -0
  149. package/knowledge/wallet-sdk-core/migration/reference/added-fields.md +71 -0
  150. package/knowledge/wallet-sdk-core/migration/reference/deleted-exports.md +35 -0
  151. package/knowledge/wallet-sdk-core/migration/reference/renamed-symbols.md +31 -0
  152. package/knowledge/wallet-sdk-core/migration/reference/return-shapes.md +23 -0
  153. package/knowledge/wallet-sdk-react/AGENTS.md +46 -0
  154. package/knowledge/wallet-sdk-react/integration/README.md +103 -0
  155. package/knowledge/wallet-sdk-react/integration/ai-rules.md +136 -0
  156. package/knowledge/wallet-sdk-react/integration/architecture.md +185 -0
  157. package/knowledge/wallet-sdk-react/integration/examples/01-minimal-evm.tsx +75 -0
  158. package/knowledge/wallet-sdk-react/integration/examples/02-multi-chain-modal.tsx +169 -0
  159. package/knowledge/wallet-sdk-react/integration/examples/03-nextjs-app-router.tsx +99 -0
  160. package/knowledge/wallet-sdk-react/integration/examples/04-walletconnect-setup.tsx +89 -0
  161. package/knowledge/wallet-sdk-react/integration/examples/README.md +29 -0
  162. package/knowledge/wallet-sdk-react/integration/recipes/batch-operations.md +224 -0
  163. package/knowledge/wallet-sdk-react/integration/recipes/bridge-to-sdk.md +165 -0
  164. package/knowledge/wallet-sdk-react/integration/recipes/chain-detection.md +259 -0
  165. package/knowledge/wallet-sdk-react/integration/recipes/connect-button.md +159 -0
  166. package/knowledge/wallet-sdk-react/integration/recipes/multi-chain-modal.md +203 -0
  167. package/knowledge/wallet-sdk-react/integration/recipes/setup.md +163 -0
  168. package/knowledge/wallet-sdk-react/integration/recipes/sign-message.md +138 -0
  169. package/knowledge/wallet-sdk-react/integration/recipes/sub-path-imports.md +97 -0
  170. package/knowledge/wallet-sdk-react/integration/recipes/switch-chain.md +144 -0
  171. package/knowledge/wallet-sdk-react/integration/recipes/walletconnect-setup.md +139 -0
  172. package/knowledge/wallet-sdk-react/integration/reference/api-surface.md +176 -0
  173. package/knowledge/wallet-sdk-react/integration/reference/chain-support.md +79 -0
  174. package/knowledge/wallet-sdk-react/integration/reference/connectors.md +75 -0
  175. package/knowledge/wallet-sdk-react/integration/reference/hooks.md +212 -0
  176. package/knowledge/wallet-sdk-react/integration/reference/wallet-brands.md +107 -0
  177. package/knowledge/wallet-sdk-react/migration/README.md +49 -0
  178. package/knowledge/wallet-sdk-react/migration/ai-rules.md +144 -0
  179. package/knowledge/wallet-sdk-react/migration/breaking-changes.md +310 -0
  180. package/knowledge/wallet-sdk-react/migration/checklist.md +159 -0
  181. package/knowledge/wallet-sdk-react/migration/recipes/connect-button.md +170 -0
  182. package/knowledge/wallet-sdk-react/migration/recipes/multi-chain-modal.md +245 -0
  183. package/knowledge/wallet-sdk-react/migration/recipes/ssr-setup.md +165 -0
  184. package/knowledge/wallet-sdk-react/migration/recipes/walletconnect-migration.md +170 -0
  185. package/knowledge/wallet-sdk-react/migration/reference/components.md +75 -0
  186. package/knowledge/wallet-sdk-react/migration/reference/config.md +339 -0
  187. package/knowledge/wallet-sdk-react/migration/reference/hooks.md +336 -0
  188. package/knowledge/wallet-sdk-react/migration/reference/imports.md +158 -0
  189. package/package.json +59 -0
  190. package/skills/sodax-dapp-kit-integration/SKILL.md +71 -0
  191. package/skills/sodax-dapp-kit-migration/SKILL.md +58 -0
  192. package/skills/sodax-sdk-integration/SKILL.md +66 -0
  193. package/skills/sodax-sdk-migration/SKILL.md +75 -0
  194. package/skills/sodax-wallet-sdk-core-integration/SKILL.md +55 -0
  195. package/skills/sodax-wallet-sdk-core-migration/SKILL.md +56 -0
  196. package/skills/sodax-wallet-sdk-react-integration/SKILL.md +80 -0
  197. package/skills/sodax-wallet-sdk-react-migration/SKILL.md +71 -0
@@ -0,0 +1,128 @@
1
+ # Bridge migration — v1 → v2
2
+
3
+ Pure-SDK migration playbook for `BridgeService`.
4
+
5
+ Pair: [`../../integration/features/bridge.md`](../../integration/features/bridge.md).
6
+
7
+ ## TL;DR
8
+
9
+ 1. **Drop `spokeProvider`. Pass `walletProvider` directly.**
10
+ 2. **Add `srcChainKey` + `srcAddress` to `CreateBridgeParams<K>`.** Generic added.
11
+ 3. **`bridge()` returns `Result<TxHashPair>`.** v1 returned a single `string` tx hash; v2 returns `{ srcChainTxHash, dstChainTxHash }` (the spoke + hub tx hashes) wrapped in `Result`.
12
+ 4. **`createBridgeIntent()` is spoke-only — no relay.** Same shape as the swap `createIntent`: returns `{ tx, intent, relayData }` for the spoke transaction. Useful when you need manual relay control.
13
+ 5. **Read methods reshaped.** `getBridgeableAmount` returns `Promise<Result<BridgeLimit>>` (was `Promise<bigint>`) and now takes two `XToken` objects. `getBridgeableTokens` is synchronous (was async) and takes `(from, to, token)`.
14
+ 6. **Errors → `SodaxError` + `Result<T>`.** v1's `BridgeError<BridgeErrorCode>` is gone.
15
+
16
+ ## Type / symbol cheat sheet
17
+
18
+ ### Field-level renames
19
+
20
+ | Type | v1 shape | v2 shape | Notes |
21
+ |---|---|---|---|
22
+ | `CreateBridgeIntentParams` | `{ srcChainId, srcAsset, amount, dstChainId, dstAsset, recipient }` | `{ srcChainKey, srcAddress, srcToken, amount, dstChainKey, dstToken, recipient }` | Now generic `<K>`. Renames: `srcChainId`/`dstChainId` → `srcChainKey`/`dstChainKey`; `srcAsset`/`dstAsset` → `srcToken`/`dstToken`. `recipient` is **unchanged**. NEW required: `srcAddress` (user's spoke-side sender, distinct from `recipient` which is the destination receiver). |
23
+ | Bridge action wrapper | `{ params, spokeProvider }` | `{ params, raw: false, walletProvider }` | Same as every feature. |
24
+ | `bridge` return | `Promise<string>` (tx hash, throws on error) | `Promise<Result<TxHashPair, SodaxError>>` | Tx-pair + Result. |
25
+ | `getBridgeableAmount` | `Promise<bigint>` | `Promise<Result<BridgeLimit, SodaxError>>` where `BridgeLimit = { amount, decimals, type }` | Result-wrapped + richer return shape. Now takes `(from: XToken, to: XToken)` (was `(srcChainId, srcToken, dstChainId, dstToken)`). |
26
+ | `getBridgeableTokens` | `Promise<XToken[]>` | `Result<XToken[], SodaxError>` (synchronous) | Sync now (config-derived). Takes `(from: SpokeChainKey, to: SpokeChainKey, token: string)` — was `(srcToken: XToken)`. |
27
+
28
+ ### Deleted symbols
29
+
30
+ - `BridgeError<BridgeErrorCode>` and `isBridgeError` — replaced by `SodaxError<C>` + `feature: 'bridge'`.
31
+
32
+ ### v1 → v2 error code crosswalk (bridge-specific)
33
+
34
+ | v1 `BridgeErrorCode` | v2 code + context |
35
+ |---|---|
36
+ | `BRIDGE_FAILED` | `EXECUTION_FAILED` (`action: 'bridge'`) |
37
+ | `CREATE_BRIDGE_INTENT_FAILED` | `INTENT_CREATION_FAILED` (`action: 'bridge'`) |
38
+ | `GET_BRIDGEABLE_AMOUNT_FAILED` | `LOOKUP_FAILED` (`method: 'getBridgeableAmount'`) |
39
+ | `GET_BRIDGEABLE_TOKENS_FAILED` | `LOOKUP_FAILED` (`method: 'getBridgeableTokens'`) |
40
+
41
+ ## Per-method delta
42
+
43
+ ### `bridge`
44
+
45
+ ```diff
46
+ - const txHash: string = await sodax.bridge.bridge({
47
+ - params: { srcAsset, amount, dstChainId, dstAsset, recipient },
48
+ - spokeProvider,
49
+ - });
50
+ + const result = await sodax.bridge.bridge({
51
+ + params: {
52
+ + srcChainKey: ChainKeys.ARBITRUM_MAINNET,
53
+ + srcAddress: '0x…', // NEW: required (your spoke-side sender)
54
+ + srcToken, // RENAMED from `srcAsset`
55
+ + amount,
56
+ + dstChainKey: ChainKeys.STELLAR_MAINNET,
57
+ + dstToken, // RENAMED from `dstAsset`
58
+ + recipient: 'G…', // UNCHANGED — destination receiver
59
+ + },
60
+ + raw: false,
61
+ + walletProvider,
62
+ + });
63
+ + // Type: Result<TxHashPair, BridgeOrchestrationError>
64
+ + // where TxHashPair = { srcChainTxHash: string; dstChainTxHash: string }
65
+ + if (!result.ok) return;
66
+ + const { srcChainTxHash, dstChainTxHash } = result.value;
67
+ ```
68
+
69
+ ### `createBridgeIntent`
70
+
71
+ ```diff
72
+ - await sodax.bridge.createBridgeIntent({ params, spokeProvider });
73
+ + const result = await sodax.bridge.createBridgeIntent({ params, raw: false, walletProvider });
74
+ + if (!result.ok) return;
75
+ + const { tx, intent, relayData } = result.value;
76
+ + // Submit relayData.payload via your custom relay if needed.
77
+ ```
78
+
79
+ ### `getBridgeableAmount` / `getBridgeableTokens`
80
+
81
+ ```diff
82
+ - const amount: bigint = await sodax.bridge.getBridgeableAmount(srcChainId, srcToken.address, dstChainId, dstToken.address);
83
+ + const result = await sodax.bridge.getBridgeableAmount(srcToken, dstToken); // both are XToken objects (each carries chainKey)
84
+ + // result.value is BridgeLimit = { amount, decimals, type }, not a raw bigint.
85
+ + if (!result.ok) return 0n;
86
+ + const amount = result.value;
87
+ ```
88
+
89
+ ### `approve` / `isAllowanceValid`
90
+
91
+ Standard pattern:
92
+
93
+ ```ts
94
+ await sodax.bridge.approve({
95
+ params: { srcChainKey, srcAddress, srcAsset, amount },
96
+ raw: false,
97
+ walletProvider,
98
+ });
99
+
100
+ const allowed = await sodax.bridge.isAllowanceValid({
101
+ params: { srcChainKey, srcAddress, srcAsset, amount },
102
+ raw: true, // read-only
103
+ });
104
+ ```
105
+
106
+ ## Pitfalls
107
+
108
+ Cross-cutting traps (Result destructuring, error-model migration, srcChain/dstChain renames, etc.) live in [`../ai-rules.md`](../ai-rules.md). The list below is feature-specific — typecheck fingerprints, return-shape diffs, and gotchas unique to this feature.
109
+
110
+ 1. **Treating `bridge` return as a string.** v2 returns `Result<TxHashPair>`. Destructure both elements; cast to string at the boundary if your downstream API expects a string.
111
+ 2. **`getBridgeableAmount` reshaped.** Resolves to `Result<BridgeLimit, SodaxError>` (with `BridgeLimit = { amount, decimals, type }`), not raw `Result<bigint>`. UI code that displayed the bigint directly needs `result.value.amount`.
112
+ 3. **`getBridgeableTokens` is synchronous now.** It returns `Result<XToken[]>` directly (no `await`). v1 was a `Promise`. `await` still typechecks but `.then(...)` is a runtime error.
113
+ 4. **Tokens are bridgeable iff they share the same vault.** Same chain pair, same underlying — but if you bridge USDC.e on chain A and the destination's USDC has a different vault, the call rejects with `VALIDATION_FAILED`. Use `getBridgeableTokens(srcChainKey, dstChainKey, srcAsset.address)` to enumerate compatible destinations.
114
+ 4. **`createBridgeIntent` is spoke-only — no relay.** If you call it expecting a finished bridge, you'll have a pending hub-side transfer that never executes. Either use `bridge()` for the full flow, or call the relay layer manually after `createBridgeIntent`.
115
+
116
+ ## Verification
117
+
118
+ ```bash
119
+ pnpm -C <your-app-dir> checkTs
120
+
121
+ grep -rE "spokeProvider:\s*\w+|isBridgeError\b|BridgeError\b" src/
122
+ ```
123
+
124
+ ## Cross-references
125
+
126
+ - v2 bridge usage: [`../../integration/features/bridge.md`](../../integration/features/bridge.md).
127
+ - Stellar destination trustline: [`../../integration/chain-specifics.md`](../../integration/chain-specifics.md).
128
+ - Cross-cutting prerequisites listed in [`../README.md`](../README.md).
@@ -0,0 +1,143 @@
1
+ # DEX migration — v1 → v2
2
+
3
+ Pure-SDK migration playbook for `DexService` (`AssetService` + `ClService`).
4
+
5
+ Pair: [`../../integration/features/dex.md`](../../integration/features/dex.md).
6
+
7
+ ## TL;DR
8
+
9
+ 1. **Drop `spokeProvider`. Pass `walletProvider` directly.** Same as every other feature.
10
+ 2. **Add `srcChainKey` + `srcAddress` to every action params.** All 6 DEX param types (`CreateAssetDepositParams`, `CreateAssetWithdrawParams`, `ClSupplyParams`, `ClIncreaseLiquidityParams`, `ClDecreaseLiquidityParams`, `ClClaimRewardsParams`) gained both fields and a `<K extends SpokeChainKey>` generic.
11
+ 3. **`getPools()` is synchronous in v2.** Was `Promise<PoolKey[]>`; now plain `PoolKey[]`. `.then(...)` is a runtime error.
12
+ 4. **`getAssetsForPool` is chain-key-first.** Was `getAssetsForPool(spokeProvider, poolKey)`; now `getAssetsForPool(srcChainKey, poolKey)`.
13
+ 5. **`getDeposit` is `Result`-wrapped.** Was `(token, spokeProvider) => Promise<bigint>`; now `(poolToken, walletAddress, chainKey) => Promise<Result<bigint>>`.
14
+ 6. **Read-only allowance checks pass `raw: true`.** `assetService.isAllowanceValid` requires the `WalletProviderSlot<K, Raw>` discriminator; the read doesn't actually consult the wallet provider, so `raw: true` is the contract for read-only access.
15
+ 7. **`getPoolData` and `getPositionInfo` use the hub publicClient.** Consumers can pass `sodax.hubProvider.publicClient` when needed.
16
+ 8. **Errors → `SodaxError` + `Result<T>`.** v1's `ConcentratedLiquidityError`, `AssetServiceError` and their type guards are gone.
17
+
18
+ ## Type / symbol cheat sheet
19
+
20
+ ### Field-level renames
21
+
22
+ | Type | v1 shape | v2 shape | Notes |
23
+ |---|---|---|---|
24
+ | `CreateAssetDepositParams` | `{ asset, amount, poolToken, dst? }` | `{ srcChainKey, srcAddress, asset, amount, poolToken, dst? }` | Now generic `<K>`. |
25
+ | `CreateAssetWithdrawParams` | same | same with `srcChainKey, srcAddress` | |
26
+ | `ClSupplyParams` | `{ poolKey, tickLower, tickUpper, liquidity, amount0Max, amount1Max, sqrtPriceX96 }` | + `srcChainKey, srcAddress` | |
27
+ | `ClIncreaseLiquidityParams` | `+ tokenId` | + `srcChainKey, srcAddress` | |
28
+ | `ClDecreaseLiquidityParams` | `{ poolKey, tokenId, liquidity, amount0Min, amount1Min }` | + `srcChainKey, srcAddress` | |
29
+ | `ClClaimRewardsParams` | `{ poolKey, tokenId, tickLower, tickUpper }` | + `srcChainKey, srcAddress` | |
30
+ | `getAssetsForPool` | `(spokeProvider, poolKey)` | `(srcChainKey, poolKey)` | Chain-key-first. Sync. |
31
+ | `getPools` | `Promise<PoolKey[]>` | `PoolKey[]` | Sync now. |
32
+ | `getDeposit` | `(token, spokeProvider) => Promise<bigint>` | `(poolToken, walletAddress, chainKey) => Promise<Result<bigint>>` | Result-wrapped. |
33
+
34
+ ### Deleted symbols
35
+
36
+ - `ConcentratedLiquidityError<ConcentratedLiquidityErrorCode>` and `AssetServiceError<AssetServiceErrorCode>` plus their type guards — replaced by `SodaxError<C>` + `feature: 'dex'`.
37
+ - v1 `getDeposit(token, spokeProvider)` overload — replaced by the chain-key-first signature.
38
+
39
+ ### v1 → v2 error code crosswalk (DEX-specific)
40
+
41
+ | v1 code | v2 code + context |
42
+ |---|---|
43
+ | `DEPOSIT_FAILED` | `EXECUTION_FAILED` (`action: 'deposit'`) |
44
+ | `WITHDRAW_FAILED` | `EXECUTION_FAILED` (`action: 'withdraw'`) |
45
+ | `SUPPLY_LIQUIDITY_FAILED` | `EXECUTION_FAILED` (`action: 'supplyLiquidity'`) |
46
+ | `INCREASE_LIQUIDITY_FAILED` | `EXECUTION_FAILED` (`action: 'increaseLiquidity'`) |
47
+ | `DECREASE_LIQUIDITY_FAILED` | `EXECUTION_FAILED` (`action: 'decreaseLiquidity'`) |
48
+ | `CLAIM_REWARDS_FAILED` | `EXECUTION_FAILED` (`action: 'claimRewards'`) |
49
+ | `GET_POOL_DATA_FAILED` | `LOOKUP_FAILED` (`method: 'getPoolData'`) |
50
+ | `GET_POSITION_INFO_FAILED` | `LOOKUP_FAILED` (`method: 'getPositionInfo'`) |
51
+
52
+ ## Per-method delta
53
+
54
+ ### `deposit` / `withdraw`
55
+
56
+ ```diff
57
+ - await sodax.dex.assetService.deposit({ params, spokeProvider });
58
+ + const result = await sodax.dex.assetService.deposit({
59
+ + params: { srcChainKey, srcAddress, asset, amount, poolToken },
60
+ + raw: false,
61
+ + walletProvider,
62
+ + });
63
+ + if (!result.ok) return;
64
+ + const { srcChainTxHash, dstChainTxHash } = result.value;
65
+ ```
66
+
67
+ ### `supplyLiquidity` (mint new) and `increaseLiquidity` (existing)
68
+
69
+ The pure-helper `createSupplyLiquidityParamsProps` returns the helper-relevant subset (no `srcChainKey`/`srcAddress`). Spread it at the call site:
70
+
71
+ ```diff
72
+ - const params = createSupplyLiquidityParamsProps({ /* … */ });
73
+ - await sodax.dex.clService.supplyLiquidity({ params, spokeProvider });
74
+ + const helperOutput = createSupplyLiquidityParamsProps({ /* … */ });
75
+ + const srcAddress = (await walletProvider.getWalletAddress()) as `0x${string}`;
76
+ + const params = { ...helperOutput, srcChainKey, srcAddress };
77
+ + const result = await sodax.dex.clService.supplyLiquidity({ params, raw: false, walletProvider });
78
+ + if (!result.ok) return;
79
+ + const { dstChainTxHash } = result.value;
80
+ ```
81
+
82
+ ### `getAssetsForPool`
83
+
84
+ ```diff
85
+ - const { token0, token1 } = sodax.dex.clService.getAssetsForPool(spokeProvider, poolKey);
86
+ + const { token0, token1 } = sodax.dex.clService.getAssetsForPool(srcChainKey, poolKey);
87
+ ```
88
+
89
+ ### `getPools`
90
+
91
+ ```diff
92
+ - const pools = await sodax.dex.clService.getPools();
93
+ + const pools = sodax.dex.clService.getPools(); // sync
94
+ ```
95
+
96
+ The `await` form still compiles (TS allows `await` on non-promises) but `.then(...)` is a runtime error.
97
+
98
+ ### `getDeposit`
99
+
100
+ ```diff
101
+ - const balance: bigint = await sodax.dex.assetService.getDeposit(poolToken, spokeProvider);
102
+ + const result = await sodax.dex.assetService.getDeposit(poolToken, walletAddress, chainKey);
103
+ + if (!result.ok) return 0n;
104
+ + const balance = result.value;
105
+ ```
106
+
107
+ ### Allowance (read-only `raw: true`)
108
+
109
+ ```diff
110
+ - const allowed = await sodax.dex.assetService.isAllowanceValid({ params, spokeProvider });
111
+ + const result = await sodax.dex.assetService.isAllowanceValid({ params, raw: true });
112
+ + if (!result.ok) return false;
113
+ + const allowed = result.value;
114
+ ```
115
+
116
+ ## Pitfalls
117
+
118
+ Cross-cutting traps (Result destructuring, error-model migration, srcChain/dstChain renames, etc.) live in [`../ai-rules.md`](../ai-rules.md). The list below is feature-specific — typecheck fingerprints, return-shape diffs, and gotchas unique to this feature.
119
+
120
+ 1. **Forgetting `raw: true` on `isAllowanceValid`.** TypeScript error: `Property 'walletProvider' is missing`.
121
+ 2. **Passing `spokeProvider` to `getAssetsForPool`.** Type error — pass `srcChainKey` instead.
122
+ 3. **`getPools().then(...)` runtime error** — sync now.
123
+ 4. **Reading `spokeProvider.chainConfig.chain.name` for display.** Gone. Use `baseChainInfo[chainKey]?.name` from `@sodax/sdk`.
124
+ 5. **Reading `spokeProvider.walletProvider.getWalletAddress()`.** Gone. The wallet provider you passed is the same one you read from — call its `.getWalletAddress()` directly.
125
+ 6. **`walletProvider.getWalletAddress()` returns `Promise<string>`, not the EVM-branded `` `0x${string}` ``.** SDK params want `GetAddressType<K>`, which for EVM resolves to `` `0x${string}` ``. Cast at the boundary: `(await walletProvider.getWalletAddress()) as \`0x${string}\``.
126
+ 7. **Mint-new vs increase-existing are two distinct SDK methods.** v2 has `clService.supplyLiquidity` (mint) and `clService.increaseLiquidity` (existing tokenId). Pick the right one at the call site based on whether you have an existing position id.
127
+ 8. **`assetService.deposit` and `withdraw` always relay to hub.** If you need spoke-only execution (custom orchestration), use `assetService.executeDeposit` directly — but it's not surfaced through the higher-level wrappers.
128
+
129
+ ## Verification
130
+
131
+ ```bash
132
+ pnpm -C <your-app-dir> checkTs
133
+
134
+ # Targeted scans:
135
+ grep -rE "spokeProvider:\s*\w+|getAssetsForPool\([^,]*Provider" src/
136
+ grep -rE "isConcentratedLiquidityError\b|ConcentratedLiquidityError\b|AssetServiceError\b" src/
137
+ grep -rE "getPools\(\)\.then\b" src/
138
+ ```
139
+
140
+ ## Cross-references
141
+
142
+ - v2 DEX usage: [`../../integration/features/dex.md`](../../integration/features/dex.md).
143
+ - Cross-cutting prerequisites listed in [`../README.md`](../README.md).
@@ -0,0 +1,151 @@
1
+ # Token migration (ICX/bnUSD/BALN) — v1 → v2
2
+
3
+ Pure-SDK migration playbook for `MigrationService` (the SDK module — not v1→v2 SDK porting).
4
+
5
+ Pair: [`../../integration/features/icx-bnusd-baln.md`](../../integration/features/icx-bnusd-baln.md).
6
+
7
+ ## TL;DR
8
+
9
+ 1. **Drop `spokeProvider`. Pass `walletProvider` directly.**
10
+ 2. **Add `srcChainKey` + `srcAddress` to every action params.** All migration param types (`MigrationParams<K>`, `UnifiedBnUSDMigrateParams<K>`, `IcxToSodaMigrateParams<K>`, `RevertSodaToIcxParams<K>`, `BalnSwapParams<K>`) gained both fields and a `<K>` generic.
11
+ 3. **All 4 orchestrator methods return `Result<TxHashPair>`.** v1 returned a string tx hash and threw on error.
12
+ 4. **`migratebnUSD` carries `direction` on error context** — `'forward'` (legacy → new) or `'reverse'` (new → legacy). The SDK detects direction from `(srcToken, dstToken)` addresses.
13
+ 5. **`BalnSwapService` lock-management methods STILL THROW.** `claim`, `claimUnstaked`, `stake`, `unstake`, `cancelUnstake`, `getDetailedUserLocks` — these 6 methods preserve the v1 throw-on-error contract. Wrap in `try/catch` until a future cleanup release converts them to `Result`.
14
+ 6. **Errors → `SodaxError` + `Result<T>`.** v1's `MigrationError<MigrationErrorCode>` is gone.
15
+
16
+ ## Type / symbol cheat sheet
17
+
18
+ ### Field-level renames
19
+
20
+ | Type | v1 shape | v2 shape | Notes |
21
+ |---|---|---|---|
22
+ | `MigrationParams` | non-generic | `MigrationParams<K extends SpokeChainKey>` with `srcChainKey`, `srcAddress`, `amount`, `dstAddress?` | Generic added. |
23
+ | `UnifiedBnUSDMigrateParams` | non-generic | `UnifiedBnUSDMigrateParams<K>` extends `MigrationParams<K>` with `srcToken`, `dstToken` | Generic added. |
24
+ | `BalnSwapParams` | `{ amount, lockPeriodMonths }` | `MigrationParams<K> & { lockPeriodMonths }` | Adds chain context. |
25
+
26
+ ### Deleted symbols
27
+
28
+ - `MigrationError<MigrationErrorCode>` and `isMigrationError` — replaced by `SodaxError<C>` + `feature: 'migration'`.
29
+ - The 6 v1 separate-method-per-direction names (`migrateBnUSDForward`, `migrateBnUSDReverse`, …) — collapsed into `migratebnUSD` with auto-direction detection on `error.context.direction`.
30
+
31
+ ### v1 → v2 error code crosswalk
32
+
33
+ | v1 `MigrationErrorCode` | v2 code + context |
34
+ |---|---|
35
+ | `MIGRATE_BNUSD_FORWARD_FAILED` | `EXECUTION_FAILED` (`action: 'migratebnUSD'`, `direction: 'forward'`) |
36
+ | `MIGRATE_BNUSD_REVERSE_FAILED` | `EXECUTION_FAILED` (`action: 'migratebnUSD'`, `direction: 'reverse'`) |
37
+ | `MIGRATE_ICX_TO_SODA_FAILED` | `EXECUTION_FAILED` (`action: 'migrateIcxToSoda'`) |
38
+ | `REVERT_MIGRATE_SODA_TO_ICX_FAILED` | `EXECUTION_FAILED` (`action: 'revertMigrateSodaToIcx'`) |
39
+ | `MIGRATE_BALN_FAILED` | `EXECUTION_FAILED` (`action: 'migrateBaln'`) |
40
+ | `GET_AVAILABLE_AMOUNT_FAILED` | `LOOKUP_FAILED` (`method: 'getAvailableAmount'`) |
41
+
42
+ `migratebnUSD` additionally has `phase: 'destinationExecution'` on errors from its secondary `waitUntilIntentExecuted` watcher (after the primary relay completes, bnUSD waits for the destination contract to finalize).
43
+
44
+ ## Per-method delta
45
+
46
+ ### `migratebnUSD` (replaces v1 forward + reverse methods)
47
+
48
+ ```diff
49
+ - // v1 had two methods:
50
+ - await sodax.migration.migrateBnUSDForward({ amount, /* … */ }, spokeProvider);
51
+ - await sodax.migration.migrateBnUSDReverse({ amount, /* … */ }, spokeProvider);
52
+
53
+ + // v2 has one method; SDK detects direction from (srcToken, dstToken):
54
+ + const result = await sodax.migration.migratebnUSD({
55
+ + params: {
56
+ + srcChainKey, srcAddress,
57
+ + srcToken, // legacy or new bnUSD
58
+ + dstToken, // the other one
59
+ + amount,
60
+ + dstAddress,
61
+ + },
62
+ + raw: false,
63
+ + walletProvider,
64
+ + });
65
+ + if (!result.ok) {
66
+ + const dir = result.error.context?.direction; // 'forward' | 'reverse'
67
+ + /* … */
68
+ + }
69
+ ```
70
+
71
+ ### `migrateIcxToSoda` / `revertMigrateSodaToIcx` / `migrateBaln`
72
+
73
+ Standard pattern:
74
+
75
+ ```diff
76
+ - await sodax.migration.migrateIcxToSoda({ amount }, spokeProvider);
77
+ + const result = await sodax.migration.migrateIcxToSoda({
78
+ + params: { srcChainKey: ChainKeys.ICON_MAINNET, srcAddress: 'hx…', amount },
79
+ + raw: false,
80
+ + walletProvider: iconWp,
81
+ + });
82
+ + if (!result.ok) return;
83
+ + const { srcChainTxHash, dstChainTxHash } = result.value;
84
+ ```
85
+
86
+ `migrateBaln` adds `lockPeriodMonths: 0 | 1 | 2 | 3 | 6 | 12 | 18 | 24` to the params. Reward multiplier ranges 0.5x (0 months) – 1.5x (24 months).
87
+
88
+ ### Approve / allowance — action-discriminated
89
+
90
+ ```ts
91
+ await sodax.migration.approve({
92
+ params: { srcChainKey, srcAddress, amount, action: 'migrateBaln' /* or migratebnUSD | migrateIcxToSoda | revertMigrateSodaToIcx */ },
93
+ raw: false,
94
+ walletProvider,
95
+ });
96
+
97
+ const allowed = await sodax.migration.isAllowanceValid({
98
+ params: { srcChainKey, srcAddress, amount, action: 'migrateBaln' },
99
+ raw: true, // read-only
100
+ });
101
+ ```
102
+
103
+ ### `getAvailableAmount` (claimable from partial migration)
104
+
105
+ ```diff
106
+ - const amount: bigint = await sodax.migration.icx.getAvailableAmount(spokeProvider);
107
+ + const result = await sodax.migration.icxMigration.getAvailableAmount(); // sub-service renamed; takes no args in v2
108
+ + if (!result.ok) return 0n;
109
+ + const amount = result.value;
110
+ ```
111
+
112
+ ### BALN lock management — STILL THROWS
113
+
114
+ ```diff
115
+ try {
116
+ - const tx = await sodax.migration.balnSwapService.stake({ amount, lockPeriod }, spokeProvider);
117
+ + const tx = await sodax.migration.balnSwapService.stake({
118
+ + params: { srcChainKey, srcAddress, amount, lockPeriodMonths },
119
+ + raw: false,
120
+ + walletProvider,
121
+ + });
122
+ /* … */
123
+ } catch (e) {
124
+ /* still v1-style: catch the throw */
125
+ }
126
+ ```
127
+
128
+ `claim`, `claimUnstaked`, `unstake`, `cancelUnstake`, `getDetailedUserLocks` follow the same pattern. They preserve the throw-on-error contract for now — future cleanup will Result-wrap them.
129
+
130
+ ## Pitfalls
131
+
132
+ Cross-cutting traps (Result destructuring, error-model migration, srcChain/dstChain renames, etc.) live in [`../ai-rules.md`](../ai-rules.md). The list below is feature-specific — typecheck fingerprints, return-shape diffs, and gotchas unique to this feature.
133
+
134
+ 1. **`migratebnUSD` direction detection.** v1 had explicit forward/reverse methods; v2 detects from `(srcToken, dstToken)`. If both are on the same side (both legacy or both new), the SDK rejects with `VALIDATION_FAILED`. Use the `direction` field on `error.context` to disambiguate in error messaging.
135
+ 2. **BALN lock methods don't return `Result`.** Be careful migrating wrappers — if your wrapper assumes Result-shape, lock methods will produce `undefined.ok` runtime errors. Keep the `try/catch` shape.
136
+ 3. **`lockPeriodMonths` is a literal union, not arbitrary `number`.** TypeScript rejects `lockPeriodMonths: 7`. Allowed values: `0 | 1 | 2 | 3 | 6 | 12 | 18 | 24`.
137
+ 4. **`getAvailableAmount` lives on the sub-service `sodax.migration.icxMigration` and takes no arguments.** v1 expected `(spokeProvider)`; v2 reads on-chain SODA liquidity directly from the hub provider, so the method needs no chain context. Sub-service field names: `sodax.migration.icxMigration`, `sodax.migration.bnUSDMigrationService`, `sodax.migration.balnSwapService`.
138
+ 5. **`destinationExecution` phase on bnUSD errors** — these errors land **after** the relay succeeds. The spoke and hub txs may already exist; the destination-side finalization is what failed. Distinguish from primary relay errors (`phase: 'relay'`) when surfacing UX.
139
+
140
+ ## Verification
141
+
142
+ ```bash
143
+ pnpm -C <your-app-dir> checkTs
144
+
145
+ grep -rE "spokeProvider:\s*\w+|migrateBnUSDForward\b|migrateBnUSDReverse\b|isMigrationError\b|MigrationError\b" src/
146
+ ```
147
+
148
+ ## Cross-references
149
+
150
+ - v2 token migration usage: [`../../integration/features/icx-bnusd-baln.md`](../../integration/features/icx-bnusd-baln.md).
151
+ - Cross-cutting prerequisites listed in [`../README.md`](../README.md).
@@ -0,0 +1,214 @@
1
+ # Money Market migration — v1 → v2
2
+
3
+ Pure-SDK migration playbook for `MoneyMarketService`.
4
+
5
+ Pair: [`../../integration/features/money-market.md`](../../integration/features/money-market.md).
6
+
7
+ ## TL;DR
8
+
9
+ 1. **Drop `spokeProvider` from every params object.** Pass `walletProvider` directly into the SDK call payload alongside `params` and `raw: false`.
10
+ 2. **Add `srcChainKey` + `srcAddress` to every action params object.** v2's `MoneyMarketParams<K>` requires both; v1 didn't have them at all.
11
+ 3. **Mutations resolve `Result<TxHashPair>`, not throw.** v1 mutation methods threw; v2 returns `{ ok: false, error }` on SDK-level failure. Branch on `result.ok`.
12
+ 4. **`MoneyMarketSupplyParams` etc. are now generic** (`MoneyMarketSupplyParams<K extends SpokeChainKey>`). Add a chain-key generic to your params variables, or let TS infer from a literal `srcChainKey`.
13
+ 5. **Replace `moneyMarketSupportedTokens[chainId]` with `sodax.moneyMarket.getSupportedTokensByChainId(chainKey)`.**
14
+ 6. **Replace `hubAssets[chainId][address]?.vault` with `token.vault`** (now baked into `XToken`). Same for `token.hubAsset`.
15
+ 7. **`sodax.moneyMarket.getAToken(...)` returns `Erc20Token & { chainKey }`, not a full `XToken`.** No `hubAsset` / `vault` on the result — look up the full `XToken` via `sodax.config.getMoneyMarketToken(chainKey, address)` if needed.
16
+ 8. **Errors → `SodaxError` + `Result<T>`.** v1's `MoneyMarketError<MoneyMarketErrorCode>` is gone. The CODE moved from `error.code` to `error.message`-style? **No** — it's still on `error.code`, but the union changed (see crosswalk below).
17
+
18
+ ## Type / symbol cheat sheet
19
+
20
+ ### Field-level renames
21
+
22
+ | Type | v1 shape | v2 shape | Notes |
23
+ |---|---|---|---|
24
+ | `MoneyMarketSupplyParams` | `{ token, amount, action }` | `{ srcChainKey, srcAddress, token, amount, action, dstChainKey?, dstAddress? }` | Same template for borrow / withdraw / repay. Now generic in `K extends SpokeChainKey`. |
25
+ | `MoneyMarketBorrowParams` | non-generic | `MoneyMarketBorrowParams<K>` | Optional `dstChainKey`/`dstAddress` for cross-chain delivery. |
26
+ | `MoneyMarketRepayParams` | non-generic | `MoneyMarketRepayParams<K>` | Optional `dstChainKey`/`dstAddress` for paying off debt on a different chain. |
27
+ | `XToken` | `xChainId` | `chainKey` | Type renamed `Token` → `XToken`. New fields `vault`, `hubAsset` baked in. |
28
+
29
+ ### Deleted symbols
30
+
31
+ - `moneyMarketSupportedTokens` — `Record<SpokeChainKey, XToken[]>` global. Use `sodax.moneyMarket.getSupportedTokensByChainId(chainKey)` / `getSupportedTokens()`.
32
+ - `hubAssets` — vault address lookup global. Use `XToken.vault` / `XToken.hubAsset` directly.
33
+ - `SodaTokens` — vault-validation registry. Use `sodax.config.getMoneyMarketReserveAssets()`.
34
+ - `MoneyMarketError<MoneyMarketErrorCode>` and `isMoneyMarketError` — replaced by `SodaxError<C>` + `isSodaxError(e) && e.feature === 'moneyMarket'`.
35
+
36
+ ### v1 → v2 error code crosswalk (money-market-specific)
37
+
38
+ | v1 `MoneyMarketErrorCode` | v2 code + context |
39
+ |---|---|
40
+ | `CREATE_SUPPLY_INTENT_FAILED` | `INTENT_CREATION_FAILED` (`action: 'supply'`) |
41
+ | `CREATE_BORROW_INTENT_FAILED` | `INTENT_CREATION_FAILED` (`action: 'borrow'`) |
42
+ | `CREATE_WITHDRAW_INTENT_FAILED` | `INTENT_CREATION_FAILED` (`action: 'withdraw'`) |
43
+ | `CREATE_REPAY_INTENT_FAILED` | `INTENT_CREATION_FAILED` (`action: 'repay'`) |
44
+ | `SUPPLY_FAILED` | `EXECUTION_FAILED` (`action: 'supply'`) |
45
+ | `BORROW_FAILED` | `EXECUTION_FAILED` (`action: 'borrow'`) |
46
+ | `WITHDRAW_FAILED` | `EXECUTION_FAILED` (`action: 'withdraw'`) |
47
+ | `REPAY_FAILED` | `EXECUTION_FAILED` (`action: 'repay'`) |
48
+ | `ALLOWANCE_CHECK_FAILED` | `ALLOWANCE_CHECK_FAILED` (unchanged) |
49
+ | `APPROVE_FAILED` | `APPROVE_FAILED` (unchanged) |
50
+ | `GAS_ESTIMATION_FAILED` | `GAS_ESTIMATION_FAILED` (unchanged) |
51
+
52
+ ## Per-method delta
53
+
54
+ ### `supply`
55
+
56
+ ```diff
57
+ - const params: MoneyMarketSupplyParams = {
58
+ - token: token.address,
59
+ - amount: parseUnits('100', 6),
60
+ - action: 'supply',
61
+ - };
62
+ - const result = await sodax.moneyMarket.supply({ params, spokeProvider });
63
+ - // result throws on failure, or returns the tx hash
64
+ + const params: MoneyMarketSupplyParams<typeof srcChainKey> = {
65
+ + srcChainKey: ChainKeys.ARBITRUM_MAINNET,
66
+ + srcAddress: '0x…',
67
+ + token: token.address,
68
+ + amount: parseUnits('100', 6),
69
+ + action: 'supply',
70
+ + };
71
+ + const result = await sodax.moneyMarket.supply({ params, raw: false, walletProvider });
72
+ + if (!result.ok) {
73
+ + // result.error: SodaxError with feature: 'moneyMarket'
74
+ + return;
75
+ + }
76
+ + const { srcChainTxHash, dstChainTxHash } = result.value;
77
+ ```
78
+
79
+ ### `borrow` — gain cross-chain delivery
80
+
81
+ If you ported a same-chain borrow, no new fields needed — just `srcChainKey` + `srcAddress`. For cross-chain delivery (which v1 didn't expose this cleanly), add `dstChainKey` and `dstAddress`:
82
+
83
+ ```ts
84
+ await sodax.moneyMarket.borrow({
85
+ params: {
86
+ srcChainKey: ChainKeys.ARBITRUM_MAINNET,
87
+ srcAddress,
88
+ token: USDC.address,
89
+ amount,
90
+ action: 'borrow',
91
+ dstChainKey: ChainKeys.STELLAR_MAINNET, // NEW in v2
92
+ dstAddress: 'G…', // NEW in v2
93
+ },
94
+ raw: false,
95
+ walletProvider,
96
+ });
97
+ ```
98
+
99
+ ### `repay` — pay from a different chain than the debt
100
+
101
+ Similar: v2 lets the spender chain (`srcChainKey`) differ from the debt chain (`dstChainKey`):
102
+
103
+ ```ts
104
+ await sodax.moneyMarket.repay({
105
+ params: {
106
+ srcChainKey: fromChain,
107
+ srcAddress: fromAddress,
108
+ token: tokenOnFromChain.address,
109
+ amount,
110
+ action: 'repay',
111
+ dstChainKey: debtChain,
112
+ dstAddress: debtAddress,
113
+ },
114
+ raw: false,
115
+ walletProvider: walletOnFromChain,
116
+ });
117
+ ```
118
+
119
+ ### `approve` / `isAllowanceValid`
120
+
121
+ ```diff
122
+ - const allowed = await sodax.moneyMarket.isAllowanceValid({ params, spokeProvider });
123
+ + const allowed = await sodax.moneyMarket.isAllowanceValid({
124
+ + params, // includes srcChainKey, srcAddress, action
125
+ + raw: true, // read-only — walletProvider not needed
126
+ + });
127
+ + if (!allowed.ok) return false;
128
+ + if (!allowed.value) await sodax.moneyMarket.approve({ params, raw: false, walletProvider });
129
+ ```
130
+
131
+ The `params.action` field discriminates which token gets approved (relevant for repay where the spent token may differ).
132
+
133
+ ## Replacing the static lookups
134
+
135
+ ```diff
136
+ - import { moneyMarketSupportedTokens, hubAssets } from '@sodax/types';
137
+ - const supplyTokens = moneyMarketSupportedTokens[chainId];
138
+ + const supplyTokens = sodax.moneyMarket.getSupportedTokensByChainId(chainKey);
139
+
140
+ - const allTokens = Object.entries(moneyMarketSupportedTokens)
141
+ - .flatMap(([chainId, tokens]) => tokens.map(t => ({ ...t, xChainId: chainId })));
142
+ + const allTokens = Object.entries(sodax.moneyMarket.getSupportedTokens())
143
+ + .flatMap(([_chainKey, tokens]) => tokens); // tokens already carry chainKey in v2
144
+ ```
145
+
146
+ ```diff
147
+ - const vault = hubAssets[chainId]?.[token.address]?.vault;
148
+ + const vault = token.vault; // baked into XToken
149
+ ```
150
+
151
+ ## Worked example — supply flow
152
+
153
+ A single supply call site, before and after. Shows every change in one place: spoke-provider drop, params shape, return shape, field rename.
154
+
155
+ ```diff
156
+ - const params: MoneyMarketSupplyParams = {
157
+ - token: token.address,
158
+ - amount: parseUnits(amount, token.decimals),
159
+ - action: 'supply',
160
+ - };
161
+ - const txHash = await sodax.moneyMarket.supply({ params, spokeProvider });
162
+ - // throws on failure
163
+ + const params: MoneyMarketSupplyParams<typeof srcChainKey> = {
164
+ + srcChainKey, // NEW: required
165
+ + srcAddress, // NEW: required (GetAddressType<K>)
166
+ + token: token.address,
167
+ + amount: parseUnits(amount, token.decimals),
168
+ + action: 'supply',
169
+ + };
170
+ + const result = await sodax.moneyMarket.supply({
171
+ + params,
172
+ + raw: false, // NEW: discriminator
173
+ + walletProvider, // NEW: was inside spokeProvider in v1
174
+ + });
175
+ + if (!result.ok) {
176
+ + // result.error: SodaxError with feature: 'moneyMarket', context.action: 'supply'
177
+ + return;
178
+ + }
179
+ + const { srcChainTxHash, dstChainTxHash } = result.value; // TxHashPair, not single hash
180
+
181
+ const successData: ActionSuccessData = {
182
+ /* … */
183
+ - destinationChainId: token.xChainId, // OLD field name
184
+ + destinationChainId: token.chainKey, // RENAMED
185
+ txHash: srcChainTxHash,
186
+ };
187
+ ```
188
+
189
+ ## Pitfalls
190
+
191
+ Cross-cutting traps (Result destructuring, error-model migration, srcChain/dstChain renames, etc.) live in [`../ai-rules.md`](../ai-rules.md). The list below is feature-specific — typecheck fingerprints, return-shape diffs, and gotchas unique to this feature.
192
+
193
+ 1. **Forgetting `srcChainKey` + `srcAddress` in params.** TypeScript surfaces this as `error TS1360: Type '{ token, amount, action }' does not satisfy the expected type 'MoneyMarketSupplyParams'`. Add both required fields.
194
+ 2. **Borrow/repay default delivery to source.** Omit `dstChainKey`/`dstAddress` if you want same-chain. Don't pass them as the same value as `srcChainKey` / `srcAddress` — let the default kick in.
195
+ 3. **`sodax.moneyMarket.getAToken(...)` returns a partial token.** `Erc20Token & { chainKey }`, not a full `XToken` — no `vault` / `hubAsset` on the result. Look up the full `XToken` via `sodax.config.getMoneyMarketToken(chainKey, address)` separately if you need those fields.
196
+ 4. **`hubAssets` is gone.** Anything that walked it for vault lookup must use `token.vault` directly.
197
+ 5. **`baseChainInfo[chain].id` is gone — entries have `.key`.** Common in `ChainSelector`-style components.
198
+ 6. **`spokeProvider.chainConfig.chain.type === 'EVM'`** is gone. Use `getChainType(chainKey) === 'EVM'` from `@sodax/sdk`.
199
+ 7. **`Number(chainKey)` returns `NaN` for non-numeric keys.** `ChainKeys.ICON_MAINNET` is `'0x1.icon'`; numeric coercions break.
200
+
201
+ ## Verification
202
+
203
+ ```bash
204
+ pnpm -C <your-app-dir> checkTs
205
+
206
+ # Targeted scans:
207
+ grep -rE "spokeProvider:\s*\w+|moneyMarketSupportedTokens|\bhubAssets\b" src/
208
+ grep -rE "isMoneyMarketError\b|MoneyMarketError\b" src/
209
+ ```
210
+
211
+ ## Cross-references
212
+
213
+ - v2 money market usage: [`../../integration/features/money-market.md`](../../integration/features/money-market.md).
214
+ - Cross-cutting prerequisites listed in [`../README.md`](../README.md).