@sodax/sdk 1.5.7-beta → 2.0.0-rc.2

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 (57) hide show
  1. package/README.md +91 -7
  2. package/ai-exported/AGENTS.md +99 -0
  3. package/ai-exported/integration/README.md +41 -0
  4. package/ai-exported/integration/ai-rules.md +75 -0
  5. package/ai-exported/integration/architecture.md +519 -0
  6. package/ai-exported/integration/chain-specifics.md +189 -0
  7. package/ai-exported/integration/features/README.md +19 -0
  8. package/ai-exported/integration/features/auxiliary-services.md +189 -0
  9. package/ai-exported/integration/features/bridge.md +136 -0
  10. package/ai-exported/integration/features/dex.md +182 -0
  11. package/ai-exported/integration/features/icx-bnusd-baln.md +181 -0
  12. package/ai-exported/integration/features/money-market.md +198 -0
  13. package/ai-exported/integration/features/staking.md +166 -0
  14. package/ai-exported/integration/features/swap.md +207 -0
  15. package/ai-exported/integration/quickstart.md +213 -0
  16. package/ai-exported/integration/recipes/README.md +21 -0
  17. package/ai-exported/integration/recipes/backend-server-init.md +69 -0
  18. package/ai-exported/integration/recipes/chain-key-narrowing.md +65 -0
  19. package/ai-exported/integration/recipes/gas-estimation.md +33 -0
  20. package/ai-exported/integration/recipes/initialize-sodax.md +53 -0
  21. package/ai-exported/integration/recipes/raw-tx-flow.md +71 -0
  22. package/ai-exported/integration/recipes/result-and-errors.md +104 -0
  23. package/ai-exported/integration/recipes/signed-tx-flow.md +46 -0
  24. package/ai-exported/integration/recipes/testing.md +101 -0
  25. package/ai-exported/integration/reference/README.md +18 -0
  26. package/ai-exported/integration/reference/chain-keys.md +67 -0
  27. package/ai-exported/integration/reference/error-codes.md +165 -0
  28. package/ai-exported/integration/reference/glossary.md +32 -0
  29. package/ai-exported/integration/reference/public-api.md +138 -0
  30. package/ai-exported/integration/reference/wallet-providers.md +62 -0
  31. package/ai-exported/migration/README.md +58 -0
  32. package/ai-exported/migration/ai-rules.md +80 -0
  33. package/ai-exported/migration/breaking-changes/architecture.md +342 -0
  34. package/ai-exported/migration/breaking-changes/result-and-errors.md +363 -0
  35. package/ai-exported/migration/breaking-changes/type-system.md +321 -0
  36. package/ai-exported/migration/checklist.md +61 -0
  37. package/ai-exported/migration/features/README.md +35 -0
  38. package/ai-exported/migration/features/auxiliary-services.md +156 -0
  39. package/ai-exported/migration/features/bridge.md +125 -0
  40. package/ai-exported/migration/features/dex.md +143 -0
  41. package/ai-exported/migration/features/icx-bnusd-baln.md +151 -0
  42. package/ai-exported/migration/features/money-market.md +214 -0
  43. package/ai-exported/migration/features/staking.md +138 -0
  44. package/ai-exported/migration/features/swap.md +198 -0
  45. package/ai-exported/migration/recipes.md +288 -0
  46. package/ai-exported/migration/reference/README.md +18 -0
  47. package/ai-exported/migration/reference/deleted-exports.md +126 -0
  48. package/ai-exported/migration/reference/error-code-crosswalk.md +104 -0
  49. package/ai-exported/migration/reference/return-shapes.md +49 -0
  50. package/ai-exported/migration/reference/sodax-config.md +52 -0
  51. package/dist/index.cjs +32076 -31544
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +8604 -7136
  54. package/dist/index.d.ts +8604 -7136
  55. package/dist/index.mjs +31893 -31402
  56. package/dist/index.mjs.map +1 -1
  57. package/package.json +20 -12
@@ -0,0 +1,165 @@
1
+ # Error codes
2
+
3
+ All 13 codes the SDK can emit. Each error is `SodaxError<C>` where `C` is one of these. The producing feature is on `error.feature`.
4
+
5
+ | Code | Meaning | Common `error.context` fields | Retry advice |
6
+ |---|---|---|---|
7
+ | `VALIDATION_FAILED` | Pre-flight invariant tripped (input shape, unsupported chain, etc.). | `field`, `reason`, `phase: 'validate'` | No — fix the input. |
8
+ | `INTENT_CREATION_FAILED` | Building the intent / payload failed. | `phase: 'intentCreation'`, `action` | Sometimes — depends on root cause (`error.cause`). |
9
+ | `EXECUTION_FAILED` | Orchestrator-level catch-all (multi-step op didn't complete). | `action`, `phase: 'execution'` or `'postExecution'` | Sometimes — inspect cause. |
10
+ | `TX_VERIFICATION_FAILED` | Spoke `verifyTxHash` returned false / threw. | `phase: 'verify'`, `srcChainKey` | Sometimes — RPC / indexer issue is transient. |
11
+ | `TX_SUBMIT_FAILED` | Spoke tx landed; relay POST submit failed. | `phase: 'submit'`, `relayCode: 'SUBMIT_TX_FAILED'` | Yes — relay submit is retryable; backoff and re-run with the same payload. |
12
+ | `RELAY_TIMEOUT` | Destination packet didn't reach `executed` within timeout. | `phase: 'relay'`, `srcChainKey`, `dstChainKey`, `relayCode: 'RELAY_TIMEOUT'` | Yes — increase timeout or re-poll; the spoke tx already landed. |
13
+ | `RELAY_FAILED` | Relay polling outage / unrecognised relay error. | `phase: 'relay'`, `relayCode` | Yes — exponential backoff. |
14
+ | `APPROVE_FAILED` | Token approval call failed. | `phase: 'approve'` | Sometimes — gas / RPC issues are retryable. |
15
+ | `ALLOWANCE_CHECK_FAILED` | Reading on-chain allowance failed. | `phase: 'allowanceCheck'` | Yes — read-only retry is cheap. |
16
+ | `GAS_ESTIMATION_FAILED` | Gas estimation returned an error. | `phase: 'gasEstimation'` | Yes — re-estimate is the norm. |
17
+ | `LOOKUP_FAILED` | Read-only on-chain query / off-chain config fetch. | `method`, `phase: 'lookup'` | Yes — read-only retry is cheap. |
18
+ | `EXTERNAL_API_ERROR` | Upstream API call failed (solver, backend). | `api: 'solver' \| 'backend'`; for solver: `solverCode`, `solverDetail` | Sometimes — depends on `solverCode`. |
19
+ | `UNKNOWN` | Last-resort catch in an outer `try`. | (none guaranteed) | Treat as unrecoverable; surface the underlying cause. |
20
+
21
+ ### Features
22
+
23
+ ```ts
24
+ type SodaxFeature =
25
+ | 'swap'
26
+ | 'moneyMarket'
27
+ | 'bridge'
28
+ | 'staking'
29
+ | 'migration'
30
+ | 'dex'
31
+ | 'partner'
32
+ | 'recovery';
33
+ ```
34
+
35
+ The `(feature, code)` pair is the canonical discriminator. Loggers tag both fields; switch statements branch on both.
36
+
37
+ ### Phase tags (`error.context.phase`)
38
+
39
+ ```ts
40
+ type SodaxPhase =
41
+ | 'validate' // pre-flight invariant
42
+ | 'intentCreation' // building intent / payload
43
+ | 'verify' // spoke verifyTxHash
44
+ | 'submit' // spoke→relay submit
45
+ | 'relay' // primary relayTxAndWaitPacket wait
46
+ | 'destinationExecution' // secondary watcher (migration's bnUSD waitUntilIntentExecuted)
47
+ | 'execution' // orchestrator-level catch
48
+ | 'postExecution' // swap-only post-relay solver step
49
+ | 'approve' // ERC20 approval call
50
+ | 'allowanceCheck' // on-chain allowance read
51
+ | 'gasEstimation' // gas-estimation read
52
+ | 'lookup'; // generic read-only query
53
+ ```
54
+
55
+ ### `RelayCode` (`error.context.relayCode`)
56
+
57
+ ```ts
58
+ type RelayCode =
59
+ | 'SUBMIT_TX_FAILED'
60
+ | 'RELAY_TIMEOUT'
61
+ | 'RELAY_POLLING_FAILED'
62
+ | 'UNKNOWN';
63
+ ```
64
+
65
+ This is the lower-level relay-layer code that `mapRelayFailure` maps from. Surfaces on `error.context.relayCode` when the error originated in `IntentRelayApiService`.
66
+
67
+ ---
68
+
69
+
70
+ ## Per-method error codes
71
+
72
+ Narrow code unions per public method. Use these for exhaustive `switch` discrimination.
73
+
74
+ ### Common helper unions (used across features)
75
+
76
+ ```ts
77
+ // 'create*Intent' methods
78
+ type CreateIntentErrorCode = 'VALIDATION_FAILED' | 'INTENT_CREATION_FAILED' | 'UNKNOWN';
79
+
80
+ // 'approve' methods
81
+ type ApproveErrorCode = 'VALIDATION_FAILED' | 'APPROVE_FAILED' | 'UNKNOWN';
82
+
83
+ // 'isAllowanceValid' methods
84
+ type AllowanceCheckErrorCode = 'VALIDATION_FAILED' | 'ALLOWANCE_CHECK_FAILED' | 'UNKNOWN';
85
+
86
+ // 'estimateGas' methods
87
+ type GasEstimationErrorCode = 'VALIDATION_FAILED' | 'GAS_ESTIMATION_FAILED' | 'UNKNOWN';
88
+
89
+ // All read-only lookups
90
+ type LookupErrorCode = 'VALIDATION_FAILED' | 'LOOKUP_FAILED' | 'UNKNOWN';
91
+ ```
92
+
93
+ ### Swap (`feature: 'swap'`)
94
+
95
+ | Method | Narrow code union |
96
+ |---|---|
97
+ | `createIntent` | `CreateIntentErrorCode` |
98
+ | `swap` | All of {`VALIDATION_FAILED`, `INTENT_CREATION_FAILED`, `EXECUTION_FAILED`, `TX_VERIFICATION_FAILED`, `TX_SUBMIT_FAILED`, `RELAY_TIMEOUT`, `RELAY_FAILED`, `EXTERNAL_API_ERROR`, `UNKNOWN`} |
99
+ | `postExecution` | `EXECUTION_FAILED \| EXTERNAL_API_ERROR \| UNKNOWN` (with `phase: 'postExecution'`) |
100
+ | `createLimitOrder`, `createLimitOrderIntent` | `CreateIntentErrorCode` |
101
+ | `cancelIntent`, `cancelLimitOrder` | `EXECUTION_FAILED \| VALIDATION_FAILED \| UNKNOWN` |
102
+
103
+ ### Money Market (`feature: 'moneyMarket'`)
104
+
105
+ | Method | Narrow code union |
106
+ |---|---|
107
+ | `supply`, `borrow`, `withdraw`, `repay` | `VALIDATION_FAILED \| INTENT_CREATION_FAILED \| EXECUTION_FAILED \| TX_VERIFICATION_FAILED \| TX_SUBMIT_FAILED \| RELAY_TIMEOUT \| RELAY_FAILED \| UNKNOWN` (with `action` discriminator) |
108
+ | `createSupplyIntent`, `createBorrowIntent`, `createWithdrawIntent`, `createRepayIntent` | `CreateIntentErrorCode` |
109
+ | `approve` | `ApproveErrorCode` |
110
+ | `isAllowanceValid` | `AllowanceCheckErrorCode` |
111
+ | `estimateGas` | `GasEstimationErrorCode` |
112
+ | Read-only methods (reserves, user data, etc.) | `LookupErrorCode` |
113
+
114
+ ### Staking (`feature: 'staking'`)
115
+
116
+ | Method | Narrow code union |
117
+ |---|---|
118
+ | `stake` | All exec codes including `TX_VERIFICATION_FAILED` (only stake calls verifyTxHash). |
119
+ | `unstake`, `instantUnstake`, `claim`, `cancelUnstake` | All exec codes minus `TX_VERIFICATION_FAILED`. |
120
+ | `approve` | `ApproveErrorCode` |
121
+ | `isAllowanceValid` | `AllowanceCheckErrorCode` |
122
+ | `getStakingInfo`, `getUnstakingInfo`, `getStakingConfig`, `getStakeRatio`, `getInstantUnstakeRatio`, `getConvertedAssets`, `getUnstakingInfoWithPenalty`, `getStakingInfoFromSpoke` | `LookupErrorCode` (with `method` discriminator) |
123
+
124
+ ### Bridge (`feature: 'bridge'`)
125
+
126
+ | Method | Narrow code union |
127
+ |---|---|
128
+ | `bridge` | All exec codes. |
129
+ | `createBridgeIntent` | `CreateIntentErrorCode` |
130
+ | `approve` | `ApproveErrorCode` |
131
+ | `isAllowanceValid` | `AllowanceCheckErrorCode` |
132
+ | `getBridgeableAmount`, `getBridgeableTokens` | `LookupErrorCode` (with `method` discriminator) |
133
+
134
+ ### DEX (`feature: 'dex'`)
135
+
136
+ | Method | Narrow code union |
137
+ |---|---|
138
+ | `assetService.deposit`, `assetService.withdraw` | All exec codes. |
139
+ | `clService.supplyLiquidity`, `clService.increaseLiquidity`, `clService.decreaseLiquidity`, `clService.claimRewards` | All exec codes. |
140
+ | `assetService.approve` | `ApproveErrorCode` |
141
+ | `assetService.isAllowanceValid` | `AllowanceCheckErrorCode` |
142
+ | `clService.getPoolData`, `clService.getPositionInfo`, `assetService.getDeposit` | `LookupErrorCode` |
143
+
144
+ ### Migration (`feature: 'migration'`)
145
+
146
+ | Method | Narrow code union |
147
+ |---|---|
148
+ | `migratebnUSD` | All exec codes; `direction: 'forward' \| 'reverse'` on context. |
149
+ | `migrateIcxToSoda`, `revertMigrateSodaToIcx`, `migrateBaln` | All exec codes. |
150
+ | `createXxxIntent` (4 of these) | `CreateIntentErrorCode` |
151
+ | `approve` | `ApproveErrorCode` |
152
+ | `isAllowanceValid` | `AllowanceCheckErrorCode` |
153
+ | `getAvailableAmount` | `LookupErrorCode` |
154
+
155
+ ### Partner (`feature: 'partner'`) and Recovery (`feature: 'recovery'`)
156
+
157
+ Both follow the same shape: action methods get the full exec union (`'EXECUTION_FAILED' \| 'INTENT_CREATION_FAILED' \| ...`), read methods get `LookupErrorCode`, approve methods get `ApproveErrorCode`.
158
+
159
+ ---
160
+
161
+
162
+ ## Cross-references
163
+
164
+ - [`README.md`](README.md) — reference index.
165
+ - [`../architecture.md`](../architecture.md) § 7–8 — error model concepts.
@@ -0,0 +1,32 @@
1
+ # Glossary
2
+
3
+ | Term | Definition |
4
+ |---|---|
5
+ | **Hub** | Sonic. The single chain through which every cross-chain operation routes. Hosts the asset manager, wallet abstraction, and vault contracts. |
6
+ | **Spoke** | Any of the 19 non-hub chains. Cross-chain operations enter and exit the system through spokes. |
7
+ | **Spoke service** | An internal SDK service (e.g. `EvmSpokeService`) that owns the chain-family-specific logic. Owned by `SpokeService` (singular, the router). Consumers never construct one. |
8
+ | **Chain key** | A string identifier for a chain (e.g. `'ethereum'`, `'0xa4b1.arbitrum'`). Type: `ChainKey` (full set) or `SpokeChainKey` (spoke chains only). Listed under `ChainKeys.*`. |
9
+ | **Chain family** | The class of chain (`'EVM'`, `'BITCOIN'`, `'SOLANA'`, …). Resolved via `getChainType(chainKey)`. |
10
+ | **Wallet provider** | A chain-specific signer/broadcaster (`IEvmWalletProvider`, etc.). Constructed by the consumer; passed into SDK calls. |
11
+ | **Intent** | A user-signed declaration of intended cross-chain action. The unit of solver-mediated swap. |
12
+ | **Solver** | An off-chain market maker that fulfills swap intents. The `SwapService` coordinates with the solver via `SolverApiService`. |
13
+ | **Relay** | The off-chain layer that propagates spoke→hub transactions. Public surface: `relayTxAndWaitPacket` and `submitTransaction` top-level functions (re-exported from `@sodax/sdk`). |
14
+ | **Relay chain id** | A bigint identifier used internally by the relay layer. **Different** from `ChainKey`. Convert via `sodax.config.getSpokeChainKeyFromIntentRelayChainId(BigInt(...))`. |
15
+ | **Vault** | Hub-side ERC4626 contract that holds wrapped/unified spoke tokens. Each `XToken` carries its `vault` address directly. |
16
+ | **Hub asset** | Hub-side token address representing a spoke asset on the hub chain. Each `XToken` carries its `hubAsset` address directly. |
17
+ | **Hub wallet abstraction** | A user-specific contract on the hub that holds funds during cross-chain ops. Resolved via `EvmHubProvider.getUserHubWalletAddress(...)`. |
18
+ | **`Result<T>`** | The `{ ok: true; value: T } \| { ok: false; error: E }` discriminated union returned by every async public method. |
19
+ | **`SodaxError<C>`** | The canonical error class. Discriminated by `(feature, code)`. |
20
+ | **Code (`SodaxErrorCode`)** | One of 13 reason-only error codes. See § 3. |
21
+ | **Feature (`SodaxFeature`)** | One of 8 producing features (`'swap'`, `'moneyMarket'`, …). |
22
+ | **Phase (`SodaxPhase`)** | The orchestration step at which an error occurred. See § 3. |
23
+ | **Action (`error.context.action`)** | The user-facing operation that triggered the error (`'supply'`, `'stake'`, `'migrateBaln'`, …). |
24
+ | **`raw: true / false`** | The discriminator on `WalletProviderSlot<K, Raw>`. `true` = build unsigned tx; `false` = sign and broadcast. |
25
+
26
+ ---
27
+
28
+
29
+ ## Cross-references
30
+
31
+ - [`README.md`](README.md) — reference index.
32
+ - [`../architecture.md`](../architecture.md) — concepts behind these tables.
@@ -0,0 +1,138 @@
1
+ # Public API surface
2
+
3
+ Import everything from `@sodax/sdk`. The barrel re-exports the entire `@sodax/types` surface — you don't need a separate `@sodax/types` dependency.
4
+
5
+ ### Top-level exports
6
+
7
+ ```ts
8
+ import {
9
+ // Main entry
10
+ Sodax,
11
+ type SodaxConfig,
12
+ type DeepPartial,
13
+
14
+ // Chain keys + narrowing
15
+ ChainKeys,
16
+ type ChainKey,
17
+ type SpokeChainKey,
18
+ type HubChainKey,
19
+ type EvmChainKey,
20
+ getChainType,
21
+ isEvmChainKeyType,
22
+ isSolanaChainKeyType,
23
+ isStellarChainKeyType,
24
+ isSuiChainKeyType,
25
+ isIconChainKeyType,
26
+ isInjectiveChainKeyType,
27
+ isStacksChainKeyType,
28
+ isNearChainKeyType,
29
+ isBitcoinChainKeyType,
30
+ isHubChainKeyType,
31
+ type GetChainType,
32
+ type GetWalletProviderType,
33
+ type GetAddressType,
34
+
35
+ // Type system primitives
36
+ type Result,
37
+ type WalletProviderSlot,
38
+ type TxReturnType,
39
+ type EvmRawTransaction,
40
+ type SolanaRawTransaction,
41
+ // …per-chain raw-tx types
42
+
43
+ // Errors
44
+ SodaxError,
45
+ type SodaxErrorCode,
46
+ type SodaxFeature,
47
+ type SodaxPhase,
48
+ type SodaxErrorContext,
49
+ type RelayCode,
50
+ isSodaxError,
51
+ isFeatureError,
52
+ isCodeMember,
53
+ sodaxInvariant,
54
+ swapInvariant,
55
+ mmInvariant,
56
+ bridgeInvariant,
57
+ stakingInvariant,
58
+ migrationInvariant,
59
+ dexInvariant,
60
+ partnerInvariant,
61
+ recoveryInvariant,
62
+ mapRelayFailure,
63
+
64
+ // Tokens
65
+ type XToken,
66
+ type BtcAddressType,
67
+
68
+ // Service classes (constructed by Sodax — usually you don't import these directly)
69
+ // …
70
+
71
+ // Wallet provider interfaces
72
+ type IWalletProvider,
73
+ type IEvmWalletProvider,
74
+ type ISolanaWalletProvider,
75
+ type ISuiWalletProvider,
76
+ type IStellarWalletProvider,
77
+ type IIconWalletProvider,
78
+ type IInjectiveWalletProvider,
79
+ type IStacksWalletProvider,
80
+ type INearWalletProvider,
81
+ type IBitcoinWalletProvider,
82
+
83
+ // Param types (per feature)
84
+ type CreateIntentParams,
85
+ type CreateLimitOrderParams,
86
+ type MoneyMarketSupplyParams,
87
+ type MoneyMarketBorrowParams,
88
+ type MoneyMarketWithdrawParams,
89
+ type MoneyMarketRepayParams,
90
+ type StakeParams,
91
+ type UnstakeParams,
92
+ type InstantUnstakeParams,
93
+ type ClaimParams,
94
+ type CancelUnstakeParams,
95
+ type CreateAssetDepositParams,
96
+ type CreateAssetWithdrawParams,
97
+ type ClSupplyParams,
98
+ type ClIncreaseLiquidityParams,
99
+ type ClDecreaseLiquidityParams,
100
+ type ClClaimRewardsParams,
101
+ type MigrationParams,
102
+ type UnifiedBnUSDMigrateParams,
103
+ // …
104
+
105
+ // Backend / relay
106
+ type IConfigApi,
107
+ type SubmitSwapTxRequest,
108
+ type SubmitSwapTxResponse,
109
+ relayTxAndWaitPacket, // function — runs spoke→hub relay submit + wait
110
+ submitTransaction, // function — relay submit ack only
111
+ type RelayExtraData,
112
+ type IntentRelayChainId,
113
+
114
+ // Read shapes
115
+ type Intent,
116
+ type IntentResponse,
117
+ type SwapResponse,
118
+ type CreateIntentResult,
119
+ type TxHashPair,
120
+ } from '@sodax/sdk';
121
+ ```
122
+
123
+ This is a partial list — see `src/index.ts` of the published tarball for the authoritative barrel.
124
+
125
+ ### Rules
126
+
127
+ - **Import only from `@sodax/sdk` root.** No deep imports from `dist/...`.
128
+ - **Do not depend on `@sodax/types` separately.** It's a transitive of `@sodax/sdk` (bundled via tsup `noExternal`); declaring it as a direct dependency invites version skew.
129
+ - **Stable contract:** every export above is part of the public API. Anything not exported from the root barrel is internal — don't reach for it via `dist` paths.
130
+ - **Tarball contents:** `dist/` (compiled JS + types) and `ai-exported/` (this docs tree). Nothing else ships.
131
+
132
+ ---
133
+
134
+
135
+ ## Cross-references
136
+
137
+ - [`README.md`](README.md) — reference index.
138
+ - [`../architecture.md`](../architecture.md) — concepts behind these tables.
@@ -0,0 +1,62 @@
1
+ # Wallet provider interfaces
2
+
3
+ Every chain family has an `I*WalletProvider` interface. Each declares a `readonly chainType: '<NAME>'` literal field for runtime discrimination.
4
+
5
+ | Family | Interface | `chainType` literal | Implementation |
6
+ |---|---|---|---|
7
+ | EVM | `IEvmWalletProvider` | `'EVM'` | `EvmWalletProvider` (private-key or browser-extension) |
8
+ | Solana | `ISolanaWalletProvider` | `'SOLANA'` | `SolanaWalletProvider` |
9
+ | Sui | `ISuiWalletProvider` | `'SUI'` | `SuiWalletProvider` |
10
+ | Stellar | `IStellarWalletProvider` | `'STELLAR'` | `StellarWalletProvider` |
11
+ | ICON | `IIconWalletProvider` | `'ICON'` | `IconWalletProvider` (uses Hana-extension helper functions for browser; see `../chain-specifics.md` § 4) |
12
+ | Injective | `IInjectiveWalletProvider` | `'INJECTIVE'` | `InjectiveWalletProvider` |
13
+ | Stacks | `IStacksWalletProvider` | `'STACKS'` | `StacksWalletProvider` |
14
+ | NEAR | `INearWalletProvider` | `'NEAR'` | `NearWalletProvider` |
15
+ | Bitcoin | `IBitcoinWalletProvider` | `'BITCOIN'` | `BTCWalletProvider` (PSBT) |
16
+
17
+ ### Common methods
18
+
19
+ Every `I*WalletProvider` has:
20
+
21
+ ```ts
22
+ getWalletAddress(): Promise<string>;
23
+ // Returns the chain-specific address (typed as `0x${string}` for EVM, base58 for Solana, etc.).
24
+ readonly chainType: '<FAMILY>';
25
+ ```
26
+
27
+ Plus chain-specific signing/broadcasting methods. Each interface declares the methods consumers must implement to satisfy it; consumers usually don't call these methods directly — they pass the provider object to SDK methods. **Implementations are not part of `@sodax/sdk`** — write your own to satisfy the interface, or use `@sodax/wallet-sdk-core` (a separate SODAX package, install separately) which ships ready-made implementations for all 9 chain families with both private-key (Node) and browser-extension (dApp) modes.
28
+
29
+ ### `GetWalletProviderType<K>`
30
+
31
+ Given a chain key literal `K`, resolves to the exact wallet provider interface for that chain:
32
+
33
+ ```ts
34
+ GetWalletProviderType<typeof ChainKeys.ETHEREUM_MAINNET> // IEvmWalletProvider
35
+ GetWalletProviderType<typeof ChainKeys.SOLANA_MAINNET> // ISolanaWalletProvider
36
+ GetWalletProviderType<typeof ChainKeys.BITCOIN_MAINNET> // IBitcoinWalletProvider
37
+ GetWalletProviderType<SpokeChainKey> // IWalletProvider (broad union)
38
+ ```
39
+
40
+ ### `IWalletProvider` (broad union)
41
+
42
+ The discriminated union of all 9 `I*WalletProvider` interfaces. Useful when a function accepts any chain's wallet provider:
43
+
44
+ ```ts
45
+ import type { IWalletProvider } from '@sodax/sdk';
46
+
47
+ function logChain(wp: IWalletProvider) {
48
+ console.log(wp.chainType);
49
+ }
50
+ ```
51
+
52
+ ### Implementing the interfaces
53
+
54
+ Each `I*WalletProvider` interface defines the methods consumers must implement; credentials, RPC clients, and browser-extension wiring are implementation concerns and intentionally outside the SDK. The SODAX-provided reference implementations in `@sodax/wallet-sdk-core` (separate package) accept either `{ privateKey, rpcUrl }` for Node / scripts or chain-specific browser-extension shapes (`{ walletClient }` for EVM via viem, `{ adapter }` for Solana, etc.) — refer to that package's documentation for specifics.
55
+
56
+ ---
57
+
58
+
59
+ ## Cross-references
60
+
61
+ - [`README.md`](README.md) — reference index.
62
+ - [`../architecture.md`](../architecture.md) — concepts behind these tables.
@@ -0,0 +1,58 @@
1
+ # Migration — `@sodax/sdk` v1 → v2
2
+
3
+ This tree is the v1 → v2 migration playbook for **existing consumers**. If you're starting fresh on v2 with no v1 code to port, skip to [`../integration/README.md`](../integration/README.md).
4
+
5
+ ## What v2 changes (the 30-second version)
6
+
7
+ v2 was a deep architectural reshape, not a feature release. Five orthogonal changes account for ~95% of the breakage your typecheck will surface:
8
+
9
+ 1. **Per-chain `*SpokeProvider` classes are gone.** Routing is by chain key (`srcChainKey: ChainKeys.ETHEREUM_MAINNET`). The SDK dispatches to the right per-chain spoke service internally; consumers pass `walletProvider` directly into payloads.
10
+ 2. **`Result<T>` everywhere.** Every async public method on every service returns `Promise<Result<T, SodaxError<C>>>`. v1 throw-on-error patterns are gone.
11
+ 3. **One canonical error class.** `SodaxError<C>` with a closed 13-code vocabulary plus `feature: 'swap' | 'moneyMarket' | …`. The per-module typed error unions (`MoneyMarketError<Code>`, `IntentError<Code>`, `StakingError<Code>`, `BridgeError<Code>`, `MigrationError<Code>`, `AssetServiceError<Code>`, `ConcentratedLiquidityError<Code>`, partner errors, …) are deleted.
12
+ 4. **`WalletProviderSlot<K, Raw>` is the discriminated union.** Every signed-execution method takes `{ raw: false, walletProvider }` (chain-narrowed via `GetWalletProviderType<K>`); every raw-tx-building method takes `{ raw: true }` (no wallet provider). Compile-time enforced.
13
+ 5. **`ConfigService` replaces static lookups.** Globals like `hubAssets`, `moneyMarketSupportedTokens`, `SodaTokens`, and the `*_MAINNET_CHAIN_ID` constants are gone. Lookups go through `sodax.config.*` (which loads from the backend API with a packaged-defaults fallback).
14
+
15
+ The remainder is per-feature (return shape diffs, field renames, new required params like `srcAddress`).
16
+
17
+ ## Reading order
18
+
19
+ Read in this order. Each step builds on the last.
20
+
21
+ 1. **[`ai-rules.md`](ai-rules.md)** — DO / DO NOT / workflow / stop-conditions. Read first, then dive in.
22
+ 2. **This file.** Cross-cutting glossary below + reference list of breaking-changes / features / checklist.
23
+ 3. **[`checklist.md`](checklist.md)** — the 17-step cross-cutting migration checklist. Walk top-down, mark items off as you go.
24
+ 4. **[`breaking-changes/type-system.md`](breaking-changes/type-system.md)** — fix every import + type-level error first. Once your imports compile, the rest is tractable.
25
+ 5. **[`breaking-changes/architecture.md`](breaking-changes/architecture.md)** — `*SpokeProvider` deletion, `ConfigService` replacing static lookups, relay-flow reshape, `sodaxInvariant` + per-feature aliases.
26
+ 6. **[`breaking-changes/result-and-errors.md`](breaking-changes/result-and-errors.md)** — convert call-site error handling, then run the v1↔v2 error-code crosswalk.
27
+ 7. **[`features/<x>.md`](features/)** — port the call sites for each feature you use. Pair with [`../integration/features/<x>.md`](../integration/features/) (same filename) when you need the v2 design context.
28
+ 8. **[`recipes.md`](recipes.md)** — codemods and adapters when full conversion in one pass isn't realistic.
29
+
30
+ ## v1 ↔ v2 glossary (terms that changed meaning)
31
+
32
+ Same word, different concept across versions. Skim before reading the breaking-changes files — this dictionary prevents the most common porting confusions.
33
+
34
+ | Term | v1 meaning | v2 meaning |
35
+ |---|---|---|
36
+ | **spoke provider** | A per-chain class instance (`EvmSpokeProvider`, `SolanaSpokeProvider`, …) consumers constructed and passed into every SDK call. | A per-chain-family service inside the SDK, owned by `SpokeService` and routed to via `getSpokeService(chainKey)`. Consumers never construct one. |
37
+ | **chain id** | Numeric or string identifier varying by chain family. v1 had `*_MAINNET_CHAIN_ID` constants, often unifying as `SpokeChainId`. | A string literal from `ChainKeys.*` (the value union is `SpokeChainKey`). `ChainKeys.ICON_MAINNET` is `'0x1.icon'` (a string), not a number. |
38
+ | **error / `*Error<Code>`** | One typed-error union per module: `MoneyMarketError<MoneyMarketErrorCode>`, `IntentError<IntentErrorCode>`, etc. Discriminated by `error.code`. | One canonical class `SodaxError<C>` for all features. 13-code reason vocabulary. Discriminated by `(error.feature, error.code)`; the producing feature is a first-class field. |
39
+ | **chain narrowing** | A combination of `instanceof EvmSpokeProvider` and string equality on `chainConfig.chain.type`. | Pure type-level narrowing via `GetChainType<K>` and `GetWalletProviderType<K>` flowing from a literal `srcChainKey` generic. Runtime variant: `walletProvider.chainType === 'EVM'` (every `I*WalletProvider` declares a `readonly chainType` literal). |
40
+ | **raw tx** | An ad-hoc method on each spoke provider, sometimes named `executeXxx`, returning a chain-specific payload. | The discriminator `{ raw: true }` on the standard SDK call shape. Return type narrows via `TxReturnType<K, true>` (`EvmRawTransaction`, `SolanaRawTransaction`, …). |
41
+ | **config** | A `SodaxConfig` object passed at construction with hard-coded chain/token tables. Solver endpoints lived under `SodaxConfig.swaps`. | A `Sodax` instance owns a `ConfigService` that loads from the backend API, with packaged defaults as fallback. `sodax.config.*` is the lookup surface. **Solver endpoints moved to `SodaxConfig.solver`** (not `swaps`); `swaps` is `SwapsConfig` (supported tokens). |
42
+ | **`xChainId` field on tokens** | Field name on the `Token` type. | Renamed: `XToken.chainKey`. Type also renamed: `Token` → `XToken`. |
43
+ | **`hubAssets` / `moneyMarketSupportedTokens`** | Static `Record` global maps imported and walked. | Gone. Use `sodax.config.*` and `sodax.moneyMarket.getSupportedTokens*()`. Each `XToken` now carries `vault` and `hubAsset` directly. |
44
+ | **`SubmitSwapTxRequest.srcChainId`** | Numeric chain id field on the backend submit-swap request. | Renamed: `srcChainKey: SpokeChainKey`. |
45
+ | **`Intent.srcChain` / `Intent.dstChain`** | Read shape: `IntentRelayChainId` (bigint). | **Unchanged.** This is the relay chain id, not a spoke chain key. A blanket grep-replace `srcChain`→`srcChainKey` will break this. |
46
+ | **`AddressType`** | Bitcoin-specific address-type union. | Renamed: `BtcAddressType`. (Generic name freed up.) |
47
+
48
+ ## Cross-references to integration
49
+
50
+ Every breaking-change file in this tree has a v2-design counterpart in `../integration/`. Follow the link when "what does v2 expect instead?" comes up:
51
+
52
+ - [`breaking-changes/type-system.md`](breaking-changes/type-system.md) ↔ [`../integration/architecture.md`](../integration/architecture.md) (§ ChainKeys, WalletProviderSlot, Result, SodaxError) and [`../integration/reference/`](../integration/reference/) (chain-key + error-code tables).
53
+ - [`breaking-changes/architecture.md`](breaking-changes/architecture.md) ↔ [`../integration/architecture.md`](../integration/architecture.md) (§ SpokeService, Sodax facade, ConfigService, relay layer).
54
+ - [`breaking-changes/result-and-errors.md`](breaking-changes/result-and-errors.md) ↔ [`../integration/recipes/`](../integration/recipes/) (§ Result handling, error discrimination).
55
+ - [`features/<x>.md`](features/) ↔ [`../integration/features/<x>.md`](../integration/features/) (same filename).
56
+ - [`recipes.md`](recipes.md) ↔ no integration counterpart (migration-only patterns).
57
+
58
+ The pair-completeness rule: every file in `migration/features/` has a sibling in `integration/features/` with the same filename. Use this when you're stuck in one and want the other view.
@@ -0,0 +1,80 @@
1
+ # AI rules — `@sodax/sdk` v1 → v2 migration
2
+
3
+ DO / DO NOT / workflow / stop conditions for AI agents porting v1 `@sodax/sdk` consumer code to v2. Read this **before** the per-feature migration files — these rules prevent the most common porting mistakes.
4
+
5
+ ## Workflow (do these in order)
6
+
7
+ 1. **Survey the consumer.** Grep for v1 fingerprints to scope the migration:
8
+
9
+ ```bash
10
+ pnpm tsc --noEmit > /tmp/v1-errors.log 2>&1 # baseline error population
11
+ grep -rE '_MAINNET_CHAIN_ID\b|\bSpokeProvider\b|\bxChainId\b|\bSpokeChainId\b|hubAssets|moneyMarketSupportedTokens' src/
12
+ grep -rE 'instanceof (MoneyMarketError|IntentError|StakingError|BridgeError|MigrationError|AssetServiceError|ConcentratedLiquidityError|RelayError)' src/
13
+ ```
14
+
15
+ 2. **Read the cross-cutting docs first.** [`README.md`](README.md) → [`breaking-changes/type-system.md`](breaking-changes/type-system.md) → [`breaking-changes/architecture.md`](breaking-changes/architecture.md) → [`breaking-changes/result-and-errors.md`](breaking-changes/result-and-errors.md). Then [`features/<x>.md`](features/) for each feature you use.
16
+ 3. **Apply changes in order: type-level first, runtime second.** Type-level renames don't affect behavior; runtime patterns (Result branching, error model) require thinking. Doing them in the wrong order means the typecheck stays noisy and you can't see the real problems.
17
+ 4. **Re-run `pnpm tsc --noEmit` after every step.** Each step should reduce the error count. If errors grow, you've introduced something — back out and try again.
18
+
19
+ ## DO
20
+
21
+ - **DO** start with mechanical type renames:
22
+ - `*_MAINNET_CHAIN_ID` → `ChainKeys.*` (regex: `(\w+)_MAINNET_CHAIN_ID` → `ChainKeys.$1_MAINNET`).
23
+ - `xChainId` → `chainKey` (on `XToken` and tokens-likes).
24
+ - `SpokeChainId` / `ChainId` → `SpokeChainKey`.
25
+ - `Token` → `XToken`.
26
+ - `AddressType` → `BtcAddressType` (only at `@sodax/types` import sites).
27
+ - **DO** add `srcChainKey` + `srcAddress` to every action params object (every `MoneyMarketSupplyParams`, `StakeParams`, `CreateAssetDepositParams`, etc. now requires both).
28
+ - **DO** add the `raw: false` (or `raw: true`) discriminator to every signed call shape that previously took `{ intentParams, spokeProvider }`. Also rename `intentParams` → `params` and drop `spokeProvider` in favor of `walletProvider`.
29
+ - **DO** convert v1 `try/catch` to `result.ok` branching last — touching every call site is the biggest commit, easiest to do once the type-level changes settled.
30
+ - **DO** treat the `Result<T>` ↔ `try/catch` migration as the *highest-leverage* change. If you stop early, ensure result branching is at least in place even if the surrounding error UX is rough.
31
+ - **DO** use `isSodaxError(e)` over bare `instanceof SodaxError` in the new error-handling branches. `instanceof` is fragile across bundle copies.
32
+ - **DO** branch on `(error.feature, error.code)` for fine-grained UX. The narrow per-method code unions enable exhaustive `switch`.
33
+
34
+ ## DO NOT
35
+
36
+ - **DO NOT** grep-replace `srcChain` → `srcChainKey` blindly. The `Intent` *read* shape (returned from `createIntent` / `getIntentByHash` / etc.) keeps `srcChain` and `dstChain` as `IntentRelayChainId` (bigint) — those did **not** rename. Only **request** types changed (`CreateIntentParams`, `CreateLimitOrderParams`, `SubmitSwapTxRequest`).
37
+ - **DO NOT** treat `instanceof MoneyMarketError` (or any other module-error class) as still working. Those classes are deleted. Replace with `isSodaxError(e) && e.feature === 'moneyMarket'`.
38
+ - **DO NOT** destructure cross-chain mutation results as arrays. v1 had `bridge()` returning a string and others returning tuples; v2 returns `TxHashPair = { srcChainTxHash, dstChainTxHash }` for **every** cross-chain mutation (bridge, staking, dex, MM, migration). Destructure as `{ srcChainTxHash, dstChainTxHash } = result.value`.
39
+ - **DO NOT** assume `BalnSwapService` lock-management methods (`stake`, `unstake`, `claim`, `claimUnstaked`, `cancelUnstake`, `getDetailedUserLocks`) return `Result<T>`. They still throw — known carve-out. Keep `try/catch` for those specific calls.
40
+ - **DO NOT** keep `try/catch` blocks expecting them to catch SDK-level failures from non-Baln methods. v2 mutation methods resolve `{ ok: false, error }` rather than throwing — `catch` only fires for synchronous wrapper exceptions (e.g. missing `walletProvider`).
41
+ - **DO NOT** call `getStakingInfo(hubAddress)` in v2. It's `getStakingInfoFromSpoke(srcAddress, srcChainKey)` now. `getStakingInfo` is not a public method.
42
+ - **DO NOT** import `@sodax/types` as a peer dependency. It's bundled into `@sodax/sdk`'s public surface; declaring it separately invites version skew.
43
+ - **DO NOT** keep `try { await sodax.swaps.createIntent(...) } catch` and expect to inspect `e.code === 'CREATE_INTENT_FAILED'`. The v2 code is `INTENT_CREATION_FAILED` and lives on `result.error.code` (Result branch), not on a thrown error. See [`reference/error-code-crosswalk.md`](reference/error-code-crosswalk.md) for the full v1 → v2 code crosswalk.
44
+
45
+ ## Stop conditions (defer to user)
46
+
47
+ | Signal | Why stop |
48
+ |---|---|
49
+ | v1 code uses framework-layer wrapper hooks (any `use*` identifier that wraps SDK calls rather than calling `@sodax/sdk` directly) | This migration tree covers Core SDK call sites only. Framework-layer migrations belong to separate ai-exported trees in their own packages. Tell the user to consult those. |
50
+ | v1 code uses `@sodax/wallet-sdk-core` classes | Those classes still exist in v2 of that separate package. Their constructor shapes may have changed — refer to that package's docs, not this tree. |
51
+ | Consumer wants to skip the `Result<T>` migration | Explain that v2 SDK calls don't throw for SDK-level failures; without `result.ok` branching the consumer silently swallows errors. Don't silently skip. |
52
+ | Consumer maintains a `*SpokeProvider` wrapper / shim | Don't try to recreate a v1-shaped wrapper in v2 — pass `walletProvider` directly into call payloads. The wrapper isn't doing useful work in v2's design. |
53
+
54
+ ## Verification protocol
55
+
56
+ ```bash
57
+ # 1. Typecheck must reach zero errors.
58
+ pnpm tsc --noEmit
59
+
60
+ # 2. No leftover v1 fingerprints.
61
+ grep -rE '_MAINNET_CHAIN_ID\b|\bxChainId\b|\bSpokeChainId\b|\bSpokeProvider\b|hubAssets|moneyMarketSupportedTokens' src/ # should be empty
62
+
63
+ # 3. No leftover v1 error type imports.
64
+ grep -rE 'MoneyMarketError|IntentError|StakingError|BridgeError|MigrationError|AssetServiceError|ConcentratedLiquidityError|RelayError' src/ # should be empty
65
+
66
+ # 4. No leftover try/catch around SDK calls expecting to catch SDK-level failures.
67
+ # (Manual review — heuristic, not mechanical.)
68
+ grep -rB1 -A3 'try {' src/ | grep -A2 'await sodax\.' # eyeball each match
69
+ ```
70
+
71
+ ## Done criteria
72
+
73
+ - [ ] `pnpm tsc --noEmit` returns 0 errors.
74
+ - [ ] No `*_MAINNET_CHAIN_ID` references remain.
75
+ - [ ] No `xChainId` field accesses remain.
76
+ - [ ] No `SpokeProvider` / `*SpokeProvider` references remain.
77
+ - [ ] No imports of `MoneyMarketError`, `IntentError`, `StakingError`, etc.
78
+ - [ ] Every `await sodax.<feature>.<method>(...)` call site has `if (!result.ok)` branching.
79
+ - [ ] `instanceof SodaxError` is replaced with `isSodaxError(e)` in cross-bundle code.
80
+ - [ ] `BalnSwapService` lock methods are wrapped in `try/catch` (still-throws carve-out).