@sodax/sdk 2.0.0-rc.2 → 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 (57) hide show
  1. package/README.md +8 -60
  2. package/dist/index.cjs +28 -39
  3. package/dist/index.d.cts +21 -108
  4. package/dist/index.d.ts +21 -108
  5. package/dist/index.mjs +34 -43
  6. package/package.json +22 -21
  7. package/ai-exported/AGENTS.md +0 -99
  8. package/ai-exported/integration/README.md +0 -41
  9. package/ai-exported/integration/ai-rules.md +0 -75
  10. package/ai-exported/integration/architecture.md +0 -519
  11. package/ai-exported/integration/chain-specifics.md +0 -189
  12. package/ai-exported/integration/features/README.md +0 -19
  13. package/ai-exported/integration/features/auxiliary-services.md +0 -189
  14. package/ai-exported/integration/features/bridge.md +0 -136
  15. package/ai-exported/integration/features/dex.md +0 -182
  16. package/ai-exported/integration/features/icx-bnusd-baln.md +0 -181
  17. package/ai-exported/integration/features/money-market.md +0 -198
  18. package/ai-exported/integration/features/staking.md +0 -166
  19. package/ai-exported/integration/features/swap.md +0 -207
  20. package/ai-exported/integration/quickstart.md +0 -213
  21. package/ai-exported/integration/recipes/README.md +0 -21
  22. package/ai-exported/integration/recipes/backend-server-init.md +0 -69
  23. package/ai-exported/integration/recipes/chain-key-narrowing.md +0 -65
  24. package/ai-exported/integration/recipes/gas-estimation.md +0 -33
  25. package/ai-exported/integration/recipes/initialize-sodax.md +0 -53
  26. package/ai-exported/integration/recipes/raw-tx-flow.md +0 -71
  27. package/ai-exported/integration/recipes/result-and-errors.md +0 -104
  28. package/ai-exported/integration/recipes/signed-tx-flow.md +0 -46
  29. package/ai-exported/integration/recipes/testing.md +0 -101
  30. package/ai-exported/integration/reference/README.md +0 -18
  31. package/ai-exported/integration/reference/chain-keys.md +0 -67
  32. package/ai-exported/integration/reference/error-codes.md +0 -165
  33. package/ai-exported/integration/reference/glossary.md +0 -32
  34. package/ai-exported/integration/reference/public-api.md +0 -138
  35. package/ai-exported/integration/reference/wallet-providers.md +0 -62
  36. package/ai-exported/migration/README.md +0 -58
  37. package/ai-exported/migration/ai-rules.md +0 -80
  38. package/ai-exported/migration/breaking-changes/architecture.md +0 -342
  39. package/ai-exported/migration/breaking-changes/result-and-errors.md +0 -363
  40. package/ai-exported/migration/breaking-changes/type-system.md +0 -321
  41. package/ai-exported/migration/checklist.md +0 -61
  42. package/ai-exported/migration/features/README.md +0 -35
  43. package/ai-exported/migration/features/auxiliary-services.md +0 -156
  44. package/ai-exported/migration/features/bridge.md +0 -125
  45. package/ai-exported/migration/features/dex.md +0 -143
  46. package/ai-exported/migration/features/icx-bnusd-baln.md +0 -151
  47. package/ai-exported/migration/features/money-market.md +0 -214
  48. package/ai-exported/migration/features/staking.md +0 -138
  49. package/ai-exported/migration/features/swap.md +0 -198
  50. package/ai-exported/migration/recipes.md +0 -288
  51. package/ai-exported/migration/reference/README.md +0 -18
  52. package/ai-exported/migration/reference/deleted-exports.md +0 -126
  53. package/ai-exported/migration/reference/error-code-crosswalk.md +0 -104
  54. package/ai-exported/migration/reference/return-shapes.md +0 -49
  55. package/ai-exported/migration/reference/sodax-config.md +0 -52
  56. package/dist/index.cjs.map +0 -1
  57. package/dist/index.mjs.map +0 -1
@@ -1,166 +0,0 @@
1
- # Staking — `StakingService`
2
-
3
- SODA token staking via an ERC4626 vault (xSoda). Stake, unstake (with penalty curve), instant unstake (slippage), claim, cancel-unstake. All operations are cross-chain — staking writes happen on the hub even when the user is on a spoke chain.
4
-
5
- Access: `sodax.staking`. Service class: `StakingService`. Feature tag for errors: `'staking'`.
6
-
7
- ## How it works
8
-
9
- - **SODA** (the staked asset) → **xSoda** (ERC4626 vault shares, proportional to current exchange rate).
10
- - **Unstake** has a configurable waiting period with linear penalty (max 1–100%).
11
- - **Instant unstake** bypasses the waiting period but pays slippage (via `StakingRouter`).
12
- - **Claim** redeems SODA after the unstaking period expires.
13
- - **Cancel unstake** restores xSoda from a pending unstake request before claim.
14
-
15
- ## Public methods
16
-
17
- ```ts
18
- sodax.staking.stake<K>(action: StakeAction<K, false>): Promise<Result<TxHashPair, SodaxError>>;
19
- sodax.staking.unstake<K>(action: UnstakeAction<K, false>): Promise<Result<TxHashPair, SodaxError>>;
20
- sodax.staking.instantUnstake<K>(action: InstantUnstakeAction<K, false>): Promise<Result<TxHashPair, SodaxError>>;
21
- sodax.staking.claim<K>(action: ClaimAction<K, false>): Promise<Result<TxHashPair, SodaxError>>;
22
- sodax.staking.cancelUnstake<K>(action: CancelUnstakeAction<K, false>): Promise<Result<TxHashPair, SodaxError>>;
23
-
24
- sodax.staking.createStakeIntent<K, Raw>(...): Promise<Result<...>>;
25
- // + the 4 other createXxxIntent methods
26
-
27
- sodax.staking.approve<K, Raw>(args): Promise<Result<TxReturnType<K, Raw>, SodaxError>>;
28
- sodax.staking.isAllowanceValid<K, Raw>(args): Promise<Result<boolean, SodaxError>>;
29
-
30
- // Reads (hub-only — no chain context needed):
31
- sodax.staking.getStakingConfig(): Promise<Result<StakingConfig, SodaxError>>;
32
- sodax.staking.getStakeRatio(amount): Promise<Result<[bigint, bigint], SodaxError>>;
33
- // value: [xSodaAmount, previewDepositAmount]
34
- sodax.staking.getInstantUnstakeRatio(amount): Promise<Result<bigint, SodaxError>>;
35
- sodax.staking.getConvertedAssets(amount): Promise<Result<bigint, SodaxError>>;
36
-
37
- // Reads (cross-chain — derive hub wallet from src chain):
38
- sodax.staking.getStakingInfoFromSpoke(srcAddress, srcChainKey): Promise<Result<StakingInfo, SodaxError>>;
39
- sodax.staking.getUnstakingInfo(srcAddress, srcChainKey): Promise<Result<UnstakingInfo, SodaxError>>;
40
- // value: { userUnstakeSodaRequests: UserUnstakeInfo[]; totalUnstaking: bigint }
41
- sodax.staking.getUnstakingInfoWithPenalty(srcAddress, srcChainKey): Promise<Result<UnstakingInfo & { requestsWithPenalty: UnstakeRequestWithPenalty[] }, SodaxError>>;
42
- // each request adds penalty, penaltyPercentage, claimableAmount
43
- ```
44
-
45
- ## Action params shape
46
-
47
- ```ts
48
- type StakeParams<K extends SpokeChainKey> = {
49
- srcChainKey: K;
50
- srcAddress: GetAddressType<K>;
51
- amount: bigint;
52
- minReceive: bigint; // min xSoda after slippage; gate against bad rates
53
- action: 'stake';
54
- };
55
-
56
- type UnstakeParams<K> = { srcChainKey: K; srcAddress; amount: bigint; action: 'unstake' };
57
- type InstantUnstakeParams<K> = { srcChainKey: K; srcAddress; amount: bigint; minAmount: bigint; action: 'instantUnstake' };
58
- type ClaimParams<K> = { srcChainKey: K; srcAddress; requestId: bigint; amount: bigint; action: 'claim' };
59
- type CancelUnstakeParams<K> = { srcChainKey: K; srcAddress; requestId: bigint; action: 'cancelUnstake' };
60
- ```
61
-
62
- `StakingParamsUnion<K, Raw>` is the union of all 5; consumed by `staking.approve` and `staking.isAllowanceValid` (action-discriminated).
63
-
64
- ## Common call shapes
65
-
66
- ### Stake
67
-
68
- ```ts
69
- const result = await sodax.staking.stake({
70
- params: {
71
- srcChainKey: ChainKeys.ARBITRUM_MAINNET,
72
- srcAddress: '0x…',
73
- amount: parseUnits('100', 18), // 100 SODA
74
- minReceive: parseUnits('99', 18), // expect ~1% slippage tolerance
75
- action: 'stake',
76
- },
77
- raw: false,
78
- walletProvider: evmWp,
79
- });
80
-
81
- if (!result.ok) return;
82
- const { srcChainTxHash, dstChainTxHash } = result.value;
83
- ```
84
-
85
- ### Unstake (with penalty curve)
86
-
87
- ```ts
88
- await sodax.staking.unstake({
89
- params: { srcChainKey, srcAddress, amount: xSodaAmount, action: 'unstake' },
90
- raw: false,
91
- walletProvider,
92
- });
93
- ```
94
-
95
- Creates a pending unstake request. After the staking period expires, call `claim`. Use `getUnstakingInfoWithPenalty` to see the current penalty for early withdrawal.
96
-
97
- ### Instant unstake
98
-
99
- ```ts
100
- await sodax.staking.instantUnstake({
101
- params: {
102
- srcChainKey, srcAddress,
103
- amount: xSodaAmount,
104
- minAmount: minSodaAfterSlippage,
105
- action: 'instantUnstake',
106
- },
107
- raw: false,
108
- walletProvider,
109
- });
110
- ```
111
-
112
- Bypasses the waiting period; pays slippage via `StakingRouter`.
113
-
114
- ### Approve / allowance — action-discriminated
115
-
116
- The `approve` method routes by `params.action` to approve the right token (SODA for `stake`, xSoda for `unstake` and `instantUnstake`):
117
-
118
- ```ts
119
- await sodax.staking.approve({
120
- params: { srcChainKey, srcAddress, amount, action: 'stake' /* or 'unstake' or 'instantUnstake' */ },
121
- raw: false,
122
- walletProvider,
123
- });
124
-
125
- const allowed = await sodax.staking.isAllowanceValid({
126
- params: { srcChainKey, srcAddress, amount, action: 'stake' },
127
- raw: true, // read-only
128
- });
129
- ```
130
-
131
- ## Return shapes
132
-
133
- | Method | Success type |
134
- |---|---|
135
- | `stake`, `unstake`, `instantUnstake`, `claim`, `cancelUnstake` | `TxHashPair` |
136
- | `create*Intent` | `CreateIntentResult<K, Raw>` |
137
- | `approve` | `TxReturnType<K, Raw>` |
138
- | `isAllowanceValid` | `boolean` |
139
- | `getStakingConfig` | `{ unstakingPeriod, maxPenalty, minPenalty, /* … */ }` |
140
- | `getStakeRatio` | `[xSodaAmount: bigint, previewDepositAmount: bigint]` (estimated xSoda shares + vault's `previewDeposit` preview) |
141
- | `getInstantUnstakeRatio` | `bigint` |
142
- | `getConvertedAssets` | `bigint` (SODA per xSoda) |
143
- | `getStakingInfoFromSpoke` | `StakingInfo` (xSoda balance, accrued, etc.) |
144
- | `getUnstakingInfo` | `UnstakingInfo` (object; carries `userUnstakeSodaRequests` array + aggregate amount) |
145
- | `getUnstakingInfoWithPenalty` | `UnstakingInfo & { requestsWithPenalty: UnstakeRequestWithPenalty[] }` (each entry adds `penalty`, `penaltyPercentage`, `claimableAmount`) |
146
-
147
- > All 5 mutation methods return `TxHashPair = { srcChainTxHash, dstChainTxHash }` because the SDK relays spoke→hub internally. When the user is already on the hub, both fields hold the same hash.
148
-
149
- ## Error codes
150
-
151
- `feature: 'staking'`. Per-method narrow unions:
152
-
153
- | Method | Codes | Action |
154
- |---|---|---|
155
- | `stake` | full exec set incl. `TX_VERIFICATION_FAILED` (only stake calls verifyTxHash) | `'stake'` |
156
- | `unstake`, `instantUnstake`, `claim`, `cancelUnstake` | full exec set minus `TX_VERIFICATION_FAILED` | matches action |
157
- | `approve` | `VALIDATION_FAILED`, `APPROVE_FAILED`, `UNKNOWN` | matches action |
158
- | `isAllowanceValid` | `VALIDATION_FAILED`, `ALLOWANCE_CHECK_FAILED`, `UNKNOWN` | matches action |
159
- | Read methods (8 of them) | `VALIDATION_FAILED`, `LOOKUP_FAILED`, `UNKNOWN` | (use `error.context.method`) |
160
-
161
- `StakingLogic` (a static utility class for contract encoding and on-chain reads) keeps its throw-on-error contract — wrapping happens only in `StakingService` public methods.
162
-
163
- ## Cross-references
164
-
165
- - v1 → v2 staking migration: [`../../migration/features/staking.md`](../../migration/features/staking.md).
166
- - ERC4626 vault concept (xSoda): see SODAX docs site or `@sodax/sdk` source.
@@ -1,207 +0,0 @@
1
- # Swap — `SwapService`
2
-
3
- Intent-based swaps via a solver. Cross-chain by default.
4
-
5
- Access: `sodax.swaps`. Service class: `SwapService`. Feature tag for errors: `'swap'`.
6
-
7
- ## How it works
8
-
9
- 1. **Build an intent** — `createIntent` signs a spoke transaction encoding the swap declaration.
10
- 2. **Relay to hub** — handled internally; the spoke tx propagates to Sonic.
11
- 3. **Solver fulfillment** — an off-chain solver picks up the intent and fills it on the destination chain.
12
- 4. **Post-execution settlement** — `postExecution` finalizes the user's side once the solver completes.
13
-
14
- Two execution paths:
15
-
16
- - **`swap`** — full flow in one call. Wraps `createIntent` + relay + `postExecution`. Returns `SwapResponse` on success.
17
- - **`createIntent` + backend submit** — break it apart for custom relay handling. `createIntent` returns `{ tx, intent, relayData }`; submit `relayData.payload` to the backend swap-tx endpoint via `BackendApiService.submitSwapTx`.
18
-
19
- ## Public methods
20
-
21
- ```ts
22
- sodax.swaps.swap<K extends SpokeChainKey>(action: SwapActionParams<K, false>): Promise<Result<SwapResponse, SodaxError>>;
23
-
24
- sodax.swaps.createIntent<K extends SpokeChainKey, Raw extends boolean>(
25
- action: SwapActionParams<K, Raw>,
26
- ): Promise<Result<CreateIntentResult<K, Raw>, SodaxError>>;
27
-
28
- sodax.swaps.postExecution(
29
- args: { intent, relayData },
30
- ): Promise<Result<SwapResponse, SodaxError>>;
31
-
32
- sodax.swaps.createLimitOrder<K, Raw>(
33
- action: LimitOrderActionParams<K, Raw>,
34
- ): Promise<Result<CreateIntentResult<K, Raw>, SodaxError>>;
35
-
36
- sodax.swaps.createLimitOrderIntent<K, Raw>(/* same as createIntent shape with limit-order params */): /* same return */;
37
-
38
- sodax.swaps.cancelIntent<K, Raw>(/* … */): Promise<Result<TxReturnType<K, Raw>, SodaxError>>;
39
- sodax.swaps.cancelLimitOrder<K, Raw>(/* … */): Promise<Result<TxReturnType<K, Raw>, SodaxError>>;
40
-
41
- sodax.swaps.approve<K, Raw>(/* … */): Promise<Result<TxReturnType<K, Raw>, SodaxError>>;
42
- sodax.swaps.isAllowanceValid<K, Raw>(/* … */): Promise<Result<boolean, SodaxError>>;
43
- ```
44
-
45
- ## Action params shape
46
-
47
- Generic `K extends SpokeChainKey` carries the literal source chain key. `WalletProviderSlot<K, Raw>` is intersected:
48
-
49
- ```ts
50
- type SwapActionParams<K extends SpokeChainKey, Raw extends boolean> = {
51
- params: CreateIntentParams<K>;
52
- skipSimulation?: boolean;
53
- timeout?: number;
54
- fee?: PartnerFee;
55
- } & WalletProviderSlot<K, Raw>;
56
- ```
57
-
58
- `CreateIntentParams<K>`:
59
-
60
- ```ts
61
- type CreateIntentParams<K extends SpokeChainKey> = {
62
- srcChainKey: K;
63
- dstChainKey: SpokeChainKey;
64
- srcAddress: GetAddressType<K>;
65
- dstAddress: string; // chain-specific format on the destination side
66
- inputToken: XToken; // must have chainKey === srcChainKey
67
- outputToken: XToken; // must have chainKey === dstChainKey
68
- inputAmount: bigint;
69
- minOutputAmount: bigint;
70
- deadline: bigint; // unix seconds
71
- allowPartialFill: boolean;
72
- solver: `0x${string}`; // solver address; '0x0…0' for default
73
- data: `0x${string}`; // arbitrary calldata; '0x' for default
74
- };
75
- ```
76
-
77
- `CreateLimitOrderParams<K>` is `Omit<CreateIntentParams<K>, 'deadline'>` (limit orders have a different expiry mechanism).
78
-
79
- ## Common call shapes
80
-
81
- ### Signed swap (full flow)
82
-
83
- ```ts
84
- const result = await sodax.swaps.swap({
85
- params: {
86
- srcChainKey: ChainKeys.ARBITRUM_MAINNET,
87
- dstChainKey: ChainKeys.STELLAR_MAINNET,
88
- srcAddress: '0x…',
89
- dstAddress: 'G…',
90
- inputToken: USDC_ARBITRUM, // XToken with chainKey === ARBITRUM_MAINNET
91
- outputToken: XLM, // XToken with chainKey === STELLAR_MAINNET
92
- inputAmount: 1_000_000n, // 1 USDC (6 decimals)
93
- minOutputAmount: 500_0000000n, // 50 XLM (7 decimals)
94
- deadline: BigInt(Math.floor(Date.now() / 1000) + 300),
95
- allowPartialFill: false,
96
- solver: '0x0000000000000000000000000000000000000000',
97
- data: '0x',
98
- },
99
- raw: false,
100
- walletProvider: evmWp,
101
- });
102
-
103
- if (!result.ok) return;
104
- const { solverExecutionResponse, intent, intentDeliveryInfo } = result.value;
105
- // SwapResponse: { solverExecutionResponse, intent, intentDeliveryInfo }
106
- // Use `intentDeliveryInfo` for spoke / hub tx hashes; `solverExecutionResponse` for solver-side outcome.
107
- ```
108
-
109
- ### Create intent only (custom relay)
110
-
111
- ```ts
112
- const result = await sodax.swaps.createIntent({
113
- params: { /* … */ },
114
- raw: false,
115
- walletProvider: evmWp,
116
- });
117
- if (!result.ok) return;
118
-
119
- const { tx: spokeTxHash, intent, relayData } = result.value;
120
- // tx is the spoke tx hash (TxReturnType<K, false>) for raw: false
121
- // relayData is { payload: string }; submit relayData.payload to your backend
122
- ```
123
-
124
- ### Backend submit-tx flow
125
-
126
- ```ts
127
- const submitResult = await sodax.backendApi.submitSwapTx({
128
- txHash: spokeTxHash as string,
129
- srcChainKey: ChainKeys.ARBITRUM_MAINNET,
130
- walletAddress: '0x…',
131
- intent: /* SwapIntentData built from CreateIntentResult.value.intent */,
132
- relayData: relayData.payload, // string (not the object)
133
- });
134
-
135
- if (!submitResult.ok) {
136
- // submitResult.error.code: 'EXTERNAL_API_ERROR' with context.api: 'backend'
137
- return;
138
- }
139
- ```
140
-
141
- ### Raw-tx flow
142
-
143
- ```ts
144
- const result = await sodax.swaps.createIntent({
145
- params: { /* … */ },
146
- raw: true,
147
- // walletProvider is forbidden here
148
- });
149
- if (!result.ok) return;
150
- const { tx, intent, relayData } = result.value;
151
- // tx: chain-specific raw-tx payload (EvmRawTransaction, SolanaRawTransaction, …)
152
- ```
153
-
154
- ### Cancel intent
155
-
156
- ```ts
157
- await sodax.swaps.cancelIntent({
158
- params: { srcChainKey, intent /* the full Intent struct */ },
159
- raw: false,
160
- walletProvider: evmWp,
161
- });
162
- ```
163
-
164
- ## Return shapes
165
-
166
- | Method | Success type |
167
- |---|---|
168
- | `swap` | `SwapResponse` = `{ solverExecutionResponse, intent, intentDeliveryInfo }` |
169
- | `createIntent` | `CreateIntentResult<K, Raw>` = `{ tx: TxReturnType<K, Raw>, intent: Intent & FeeAmount, relayData: RelayExtraData }` |
170
- | `postExecution` | `SwapResponse` |
171
- | `createLimitOrder` / `createLimitOrderIntent` | Same as `createIntent` |
172
- | `cancelIntent` / `cancelLimitOrder` | `TxReturnType<K, Raw>` |
173
- | `approve` | `TxReturnType<K, Raw>` |
174
- | `isAllowanceValid` | `boolean` |
175
-
176
- `RelayExtraData`:
177
-
178
- ```ts
179
- type RelayExtraData = {
180
- payload: string; // pass this string to backend submit-tx as `relayData`
181
- };
182
- ```
183
-
184
- ## Error codes
185
-
186
- `feature: 'swap'`. Per-method narrow unions:
187
-
188
- | Method | Codes |
189
- |---|---|
190
- | `createIntent`, `createLimitOrderIntent` | `VALIDATION_FAILED`, `INTENT_CREATION_FAILED`, `UNKNOWN` |
191
- | `swap`, `createLimitOrder` | `VALIDATION_FAILED`, `INTENT_CREATION_FAILED`, `EXECUTION_FAILED`, `TX_VERIFICATION_FAILED`, `TX_SUBMIT_FAILED`, `RELAY_TIMEOUT`, `RELAY_FAILED`, `EXTERNAL_API_ERROR`, `UNKNOWN` |
192
- | `postExecution` | `EXECUTION_FAILED` (with `phase: 'postExecution'`), `EXTERNAL_API_ERROR` (with `api: 'solver'`), `UNKNOWN` |
193
- | `cancelIntent`, `cancelLimitOrder` | `VALIDATION_FAILED`, `EXECUTION_FAILED`, `UNKNOWN` |
194
- | `approve` | `VALIDATION_FAILED`, `APPROVE_FAILED`, `UNKNOWN` |
195
- | `isAllowanceValid` | `VALIDATION_FAILED`, `ALLOWANCE_CHECK_FAILED`, `UNKNOWN` |
196
-
197
- Solver-specific context on `EXTERNAL_API_ERROR`:
198
-
199
- - `error.context.api === 'solver'`
200
- - `error.context.solverCode` — the solver's own error code (e.g. `'INSUFFICIENT_LIQUIDITY'`)
201
- - `error.context.solverDetail` — the solver's human-readable message
202
-
203
- ## Cross-references
204
-
205
- - v1 → v2 swap migration: [`../../migration/features/swap.md`](../../migration/features/swap.md).
206
- - Error model: [`../architecture.md`](../architecture.md) § 8 and [`../reference/`](../reference/) § 3.
207
- - Stellar destinations require a trustline first: [`../chain-specifics.md`](../chain-specifics.md) § "Stellar trustline".
@@ -1,213 +0,0 @@
1
- # Quickstart — `@sodax/sdk` v2
2
-
3
- Get a `Sodax` instance running in your project. This guide is **`@sodax/sdk`-only**: no other SODAX packages are imported. Where the SDK needs an `I*WalletProvider` instance, examples use a TypeScript `declare` placeholder so the surface stays Core-SDK-clean.
4
-
5
- ## Section index
6
-
7
- 1. [Installation](#1-installation)
8
- 2. [TypeScript](#2-typescript)
9
- 3. [The wallet-provider contract](#3-the-wallet-provider-contract)
10
- 4. [Where to get wallet-provider implementations](#4-where-to-get-wallet-provider-implementations)
11
- 5. [Construct + initialize](#5-construct--initialize)
12
- 6. [Reads without a wallet](#6-reads-without-a-wallet)
13
- 7. [Build raw transactions (no wallet)](#7-build-raw-transactions-no-wallet)
14
- 8. [Calling methods that sign](#8-calling-methods-that-sign)
15
- 9. [First-time troubleshooting](#9-first-time-troubleshooting)
16
-
17
- ---
18
-
19
- ## 1. Installation
20
-
21
- ```bash
22
- pnpm add @sodax/sdk
23
- # or
24
- npm install @sodax/sdk
25
- # or
26
- yarn add @sodax/sdk
27
- ```
28
-
29
- **Don't add `@sodax/types` separately.** `@sodax/sdk` re-exports the entire types surface from its barrel. Adding `@sodax/types` as a direct dependency invites version skew on the next minor bump.
30
-
31
- ## 2. TypeScript
32
-
33
- Targets Node 18+ and modern browsers. The package ships dual ESM (`.mjs`) + CJS (`.cjs`) + DTS, with `"type": "module"`. No additional TypeScript config needed — the package's `exports` field handles resolution for both `tsc` and `bundler` `moduleResolution` modes.
34
-
35
- If you're on `moduleResolution: 'node'` (legacy), upgrade to `'bundler'` or `'node16'` / `'nodenext'` — `'node'` doesn't read the `exports` field and will fall back to `main` / `module` (which still work, but you may see resolution warnings).
36
-
37
- ## 3. The wallet-provider contract
38
-
39
- Methods that sign and broadcast take a `walletProvider` parameter typed as the chain-specific `I*WalletProvider` interface (`IEvmWalletProvider`, `ISolanaWalletProvider`, `ISuiWalletProvider`, `IStellarWalletProvider`, `IIconWalletProvider`, `IInjectiveWalletProvider`, `IStacksWalletProvider`, `INearWalletProvider`, `IBitcoinWalletProvider`). All nine interfaces are exported from `@sodax/sdk`.
40
-
41
- `@sodax/sdk` does **not** ship implementations of these interfaces. Read methods (`sodax.config.*`, `sodax.bridge.getBridgeableAmount`, `sodax.staking.getStakingConfig`, etc.) and `raw: true` flows do not require a `walletProvider`.
42
-
43
- ## 4. Where to get wallet-provider implementations
44
-
45
- Two options:
46
-
47
- 1. **Implement the interface yourself.** Each `I*WalletProvider` is a small set of methods (`getWalletAddress`, plus chain-specific signing / broadcasting). Wrap whatever wallet abstraction your app already owns (`viem`'s `WalletClient` for EVM, `@solana/web3.js` keypairs for Solana, `@stellar/stellar-sdk` for Stellar, etc.) in an object literal that satisfies the interface.
48
- 2. **Use `@sodax/wallet-sdk-core`** — a separate SODAX package (not part of `@sodax/sdk`, not a transitive dependency — install it separately) that ships ready-made `I*WalletProvider` implementations for all 9 chain families with both private-key (Node / scripts) and browser-extension (dApp) modes. Refer to that package's own documentation for usage.
49
-
50
- Examples in this guide use TypeScript `declare const` placeholders so the surface stays Core-SDK-only — substitute your own object regardless of which option you chose.
51
-
52
- ## 5. Construct + initialize
53
-
54
- ```ts
55
- import { Sodax } from '@sodax/sdk';
56
-
57
- const sodax = new Sodax();
58
- await sodax.config.initialize(); // load fresh config from backend; falls back to packaged defaults
59
-
60
- // All feature services are wired and ready:
61
- // sodax.swaps, sodax.moneyMarket, sodax.bridge, sodax.staking,
62
- // sodax.dex, sodax.migration, sodax.partners, sodax.recovery,
63
- // sodax.config, sodax.backendApi, sodax.hubProvider, sodax.spoke
64
- ```
65
-
66
- `new Sodax()` accepts an optional `DeepPartial<SodaxConfig>` for custom RPC endpoints, solver / backend URLs, etc. — see [`recipes/`](recipes/) § "Initialize Sodax". `initialize()` is idempotent.
67
-
68
- ## 6. Reads without a wallet
69
-
70
- Many SDK calls are pure reads — no wallet provider, no signing. They're the cheapest path to verifying an integration:
71
-
72
- ```ts
73
- import { Sodax, ChainKeys } from '@sodax/sdk';
74
-
75
- const sodax = new Sodax();
76
- await sodax.config.initialize();
77
-
78
- // Config / token lookups
79
- const usdc = sodax.config.findSupportedTokenBySymbol(ChainKeys.ARBITRUM_MAINNET, 'USDC');
80
- const isValid = sodax.config.isValidSpokeChainKey(ChainKeys.ARBITRUM_MAINNET);
81
-
82
- // Money market
83
- const supplyTokens = sodax.moneyMarket.getSupportedTokensByChainId(ChainKeys.ARBITRUM_MAINNET);
84
-
85
- // Bridge
86
- const limit = await sodax.bridge.getBridgeableAmount(USDC_ARBITRUM, USDC_STELLAR);
87
- // limit.value: BridgeLimit = { amount, decimals, type }
88
-
89
- // Staking (hub-only reads — no chain context needed)
90
- const stakingConfig = await sodax.staking.getStakingConfig();
91
-
92
- // DEX
93
- const pools = sodax.dex.clService.getPools(); // synchronous in v2
94
- ```
95
-
96
- ## 7. Build raw transactions (no wallet)
97
-
98
- For sign-elsewhere flows (gnosis safe, hardware wallet, custom multi-sig), use `raw: true`. The SDK builds the unsigned payload; your application signs and broadcasts:
99
-
100
- ```ts
101
- import { Sodax, ChainKeys } from '@sodax/sdk';
102
-
103
- const sodax = new Sodax();
104
- await sodax.config.initialize();
105
-
106
- const result = await sodax.swaps.createIntent({
107
- params: {
108
- srcChainKey: ChainKeys.ARBITRUM_MAINNET,
109
- dstChainKey: ChainKeys.STELLAR_MAINNET,
110
- /* … rest of intent params */
111
- },
112
- raw: true,
113
- // walletProvider is FORBIDDEN when raw: true — TypeScript rejects it.
114
- });
115
-
116
- if (!result.ok) {
117
- console.error(result.error.toJSON());
118
- return;
119
- }
120
- const { tx, intent, relayData } = result.value;
121
- // tx: chain-specific raw-tx payload (EvmRawTransaction, SolanaRawTransaction, …)
122
- // Sign and broadcast `tx` with whatever signer your application owns.
123
- ```
124
-
125
- ## 8. Calling methods that sign
126
-
127
- For signed flows, supply an `I*WalletProvider`. The example uses a TypeScript `declare` placeholder — at runtime, substitute an object your application owns (one you implemented to satisfy the interface, or one constructed via `@sodax/wallet-sdk-core`).
128
-
129
- ```ts
130
- import { Sodax, ChainKeys, type IEvmWalletProvider } from '@sodax/sdk';
131
-
132
- declare const evmWallet: IEvmWalletProvider;
133
- // ↑ At runtime, replace with your application's wallet-provider object.
134
- // Any object that satisfies IEvmWalletProvider works.
135
-
136
- const sodax = new Sodax();
137
- await sodax.config.initialize();
138
-
139
- const result = await sodax.swaps.createIntent({
140
- params: {
141
- srcChainKey: ChainKeys.ARBITRUM_MAINNET,
142
- dstChainKey: ChainKeys.STELLAR_MAINNET,
143
- srcAddress: (await evmWallet.getWalletAddress()) as `0x${string}`,
144
- /* … rest of intent params */
145
- },
146
- raw: false,
147
- walletProvider: evmWallet,
148
- });
149
-
150
- if (!result.ok) {
151
- console.error(result.error.toJSON());
152
- return;
153
- }
154
-
155
- console.log('intent created:', result.value.tx);
156
- ```
157
-
158
- The chain key on the payload (`ChainKeys.ARBITRUM_MAINNET`) is what TypeScript narrows the wallet-provider parameter against — passing a Solana wallet would be a compile-time error. See [`architecture.md`](architecture.md) § 6 for the `WalletProviderSlot<K, Raw>` mechanism.
159
-
160
- ## 9. First-time troubleshooting
161
-
162
- The errors most likely to hit on a fresh install or first port.
163
-
164
- ### "Cannot find module '@sodax/sdk' or its corresponding type declarations"
165
-
166
- - TypeScript `moduleResolution` is `'node'` (legacy). Switch to `'bundler'` or `'node16'`/`'nodenext'`.
167
- - Or: clear `node_modules` and reinstall. `@sodax/sdk` ships dual exports; resolution should be automatic.
168
-
169
- ### "Module '\"@sodax/sdk\"' has no exported member 'SONIC_MAINNET_CHAIN_ID'"
170
-
171
- - v1 constant name. Use `ChainKeys.SONIC_MAINNET`. See [`../migration/breaking-changes/type-system.md`](../migration/breaking-changes/type-system.md) § 1.
172
-
173
- ### "Object literal may only specify known properties, and 'walletProvider' does not exist in type ..."
174
-
175
- - Forgot `raw: false` (or `raw: true`) discriminator on the call. Add it. See [`architecture.md`](architecture.md) § 6.
176
-
177
- ### "Property 'tx' does not exist on type 'SwapResponse'" or similar
178
-
179
- - You're treating the return as the success value directly instead of unpacking `result.value`. v2 returns `Promise<Result<T>>` — branch on `result.ok` first. See [`architecture.md`](architecture.md) § 7.
180
-
181
- ### `sodax.config.findSupportedTokenBySymbol` returns `undefined`
182
-
183
- - `await sodax.config.initialize()` wasn't called. Add it after `new Sodax()`.
184
-
185
- ### "Property 'xChainId' does not exist on type 'XToken'"
186
-
187
- - `XToken.xChainId` was renamed to `XToken.chainKey`. See [`../migration/breaking-changes/type-system.md`](../migration/breaking-changes/type-system.md) § 4.
188
-
189
- ### "Type '{ token, amount, action }' does not satisfy the expected type 'MoneyMarketSupplyParams'"
190
-
191
- - Missing `srcChainKey` and `srcAddress` (required in v2). See [`features/money-market.md`](features/money-market.md).
192
-
193
- ### "Argument of type 'string' is not assignable to parameter of type 'GetAddressType<K>'"
194
-
195
- - For EVM chains, `GetAddressType<K>` is `` `0x${string}` ``. Cast at the boundary: `(await walletProvider.getWalletAddress()) as \`0x${string}\``. See [`recipes/`](recipes/) § "Chain-key narrowing".
196
-
197
- ### `sodax.config.initialize()` hangs / errors
198
-
199
- - The backend API is unreachable. The SDK should fall back to packaged defaults silently — check your network, then check that `SodaxConfig.backendApi.url` is correct (or omit it for the default).
200
-
201
- ### Stellar bridge / swap fails with `'Trustline missing'`
202
-
203
- - Stellar destinations require a trustline for the destination asset before they can receive it. See [`chain-specifics.md`](chain-specifics.md) § "Stellar trustline".
204
-
205
- ---
206
-
207
- ## Cross-references
208
-
209
- - v2 architecture: [`architecture.md`](architecture.md).
210
- - Recipes for common patterns: [`recipes/`](recipes/).
211
- - Per-feature usage: [`features/`](features/).
212
- - Lookup tables (chain keys, error codes, public API): [`reference/`](reference/).
213
- - v1 → v2 porting: [`../migration/README.md`](../migration/README.md).
@@ -1,21 +0,0 @@
1
- # Recipes — `@sodax/sdk` v2
2
-
3
- Copy-pasteable patterns for the most common Core SDK consumer tasks. Each file is self-contained — drop the snippet into your code, swap in your specifics, done.
4
-
5
- | Recipe | When |
6
- |---|---|
7
- | [`initialize-sodax.md`](initialize-sodax.md) | App startup. `new Sodax()` + `await sodax.config.initialize()`, with and without config override. |
8
- | [`result-and-errors.md`](result-and-errors.md) | Branching on `result.ok`, switching on `(error.feature, error.code)`, `isSodaxError` over `instanceof`, sub-Result propagation, logger integration. |
9
- | [`signed-tx-flow.md`](signed-tx-flow.md) | `raw: false` + chain-narrowed `walletProvider`. Returns tx hash (or `TxHashPair` for cross-chain mutations). |
10
- | [`raw-tx-flow.md`](raw-tx-flow.md) | `raw: true`. Builds an unsigned chain-specific payload; you sign elsewhere. |
11
- | [`chain-key-narrowing.md`](chain-key-narrowing.md) | Cast-at-boundary pattern; runtime `chainType` discriminant. |
12
- | [`testing.md`](testing.md) | Mocking the `Sodax` instance, stubbing the relay layer, `Result<T>` assertions. |
13
- | [`gas-estimation.md`](gas-estimation.md) | Pre-flight gas estimation for raw-tx flows. |
14
- | [`backend-server-init.md`](backend-server-init.md) | Node script / bot / partner backend pattern with `declare const` wallet placeholders. |
15
-
16
- ## Cross-references
17
-
18
- - v2 architectural concepts: [`../architecture.md`](../architecture.md).
19
- - Lookup tables (chain keys, error codes, public API): [`../reference/`](../reference/).
20
- - DO / DO NOT / workflow: [`../ai-rules.md`](../ai-rules.md).
21
- - v1 → v2 migration: [`../../migration/recipes.md`](../../migration/recipes.md).
@@ -1,69 +0,0 @@
1
- # Backend-server initialization (private-key)
2
-
3
- Node script / bot / partner backend pattern. The `Sodax` instance holds no wallet itself — your application owns the `I*WalletProvider` object and passes it into each call.
4
-
5
- ```ts
6
- import { Sodax, ChainKeys, type IEvmWalletProvider, type SpokeChainKey } from '@sodax/sdk';
7
-
8
- declare const evmWallet: IEvmWalletProvider;
9
- // ↑ Your application's wallet-provider object. Implement IEvmWalletProvider yourself,
10
- // or install `@sodax/wallet-sdk-core` (separate package) which ships an `EvmWalletProvider`
11
- // class you can construct with `{ privateKey, rpcUrl }`.
12
-
13
- const sodax = new Sodax({
14
- rpcConfig: {
15
- [ChainKeys.ARBITRUM_MAINNET]: process.env.ARBITRUM_RPC_URL!,
16
- [ChainKeys.SONIC_MAINNET]: process.env.SONIC_RPC_URL!,
17
- // …
18
- },
19
- });
20
- await sodax.config.initialize();
21
-
22
- const result = await sodax.swaps.createIntent({
23
- params: {
24
- srcChainKey: ChainKeys.ARBITRUM_MAINNET,
25
- dstChainKey: ChainKeys.STELLAR_MAINNET,
26
- srcAddress: (await evmWallet.getWalletAddress()) as `0x${string}`,
27
- /* … */
28
- },
29
- raw: false,
30
- walletProvider: evmWallet,
31
- });
32
- ```
33
-
34
- ### Multi-chain bots
35
-
36
- If your bot operates on multiple source chains, hold one wallet provider per chain family and pick the right one at call time:
37
-
38
- ```ts
39
- declare const wallets: {
40
- readonly [ChainKeys.ARBITRUM_MAINNET]: IEvmWalletProvider;
41
- readonly [ChainKeys.SONIC_MAINNET]: IEvmWalletProvider;
42
- readonly [ChainKeys.SOLANA_MAINNET]: ISolanaWalletProvider;
43
- };
44
-
45
- function getWallet(chainKey: SpokeChainKey) {
46
- const wp = wallets[chainKey as keyof typeof wallets];
47
- if (!wp) throw new Error(`No wallet configured for ${chainKey}`);
48
- return wp;
49
- }
50
-
51
- await sodax.swaps.createIntent({
52
- params: { srcChainKey: ChainKeys.ARBITRUM_MAINNET, /* … */ },
53
- raw: false,
54
- walletProvider: getWallet(ChainKeys.ARBITRUM_MAINNET),
55
- });
56
- ```
57
-
58
- ### Pitfall
59
-
60
- Hold one wallet-provider instance per chain family for the lifetime of your process; don't recreate them per request. Implementations typically own an RPC client connection that's expensive to set up.
61
-
62
- ---
63
-
64
-
65
- ## Cross-references
66
-
67
- - [`README.md`](README.md) — recipe index.
68
- - [`../architecture.md`](../architecture.md) — concepts behind these patterns.
69
- - [`../reference/`](../reference/) — chain keys, error codes, public API surface.