@sodax/dapp-kit 2.0.0-rc.1 → 2.0.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai-exported/AGENTS.md +1 -1
- package/ai-exported/integration/ai-rules.md +1 -0
- package/ai-exported/integration/architecture.md +9 -7
- package/ai-exported/integration/features/README.md +10 -10
- package/ai-exported/integration/features/auxiliary-services.md +3 -3
- package/ai-exported/integration/features/money-market.md +30 -2
- package/ai-exported/integration/recipes/money-market.md +5 -4
- package/ai-exported/integration/recipes/setup.md +24 -0
- package/ai-exported/integration/recipes/wallet-connectivity.md +27 -0
- package/ai-exported/integration/reference/README.md +1 -1
- package/ai-exported/integration/reference/glossary.md +2 -0
- package/ai-exported/integration/reference/hooks-index.md +12 -16
- package/ai-exported/integration/reference/public-api.md +2 -2
- package/ai-exported/migration/breaking-changes/sdk-leakage.md +2 -0
- package/ai-exported/migration/features/auxiliary-services.md +3 -3
- package/ai-exported/migration/features/bridge.md +50 -13
- package/ai-exported/migration/features/money-market.md +45 -3
- package/ai-exported/migration/features/swap.md +17 -2
- package/ai-exported/migration/recipes.md +11 -14
- package/ai-exported/migration/reference/renamed-hooks.md +2 -0
- package/dist/index.cjs +3 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -4
- package/dist/index.d.ts +11 -4
- package/dist/index.mjs +3 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -4
- package/src/providers/SodaxProvider.tsx +15 -11
package/ai-exported/AGENTS.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Project
|
|
6
6
|
|
|
7
|
-
`@sodax/dapp-kit` is a React hooks library that wraps `@sodax/sdk` with React Query. It provides
|
|
7
|
+
`@sodax/dapp-kit` is a React hooks library that wraps `@sodax/sdk` with React Query. It provides hooks across 11 feature domains (swap, money market, staking, bridge, dex, migration, partner, recovery, bitcoin/Radfi, backend queries, shared) for consumer dApps. It is **React-only** — Node.js scripts and backend services use `@sodax/sdk` directly.
|
|
8
8
|
|
|
9
9
|
This package is **v2**. v2 was a deep canonicalization pass over v1's hook shapes — single-object params, mandatory `mutateAsyncSafe`, hook-owned invalidations, throw-on-`Result.!ok` inside `mutationFn`, canonical queryKey/mutationKey conventions. Plus the entire SDK underneath was reshaped (chain-key-driven routing, `Result<T>` everywhere, `WalletProviderSlot<K, Raw>`). Code written against v1 dapp-kit will not compile against v2.
|
|
10
10
|
|
|
@@ -39,6 +39,7 @@ DO / DO NOT / workflow / stop conditions for AI agents writing v2 dapp-kit code.
|
|
|
39
39
|
- **DO NOT** recreate the v1 `invalidateMmQueries(...)` utility or anything similar. Each mutation hook invalidates the relevant keys in its own `onSuccess`. Add cross-feature invalidations via consumer `onSuccess`.
|
|
40
40
|
- **DO NOT** destructure cross-chain mutation results as arrays — `[a, b] = result.value` is wrong. The shape is `TxHashPair = { srcChainTxHash, dstChainTxHash }` (object). This applies to `useBridge`, `useStake`/`useUnstake`/etc., `useDexDeposit`/`useDexWithdraw`, all four MM mutations, and all four migration mutations.
|
|
41
41
|
- **DO NOT** use legacy chain-id constants (`BSC_MAINNET_CHAIN_ID`, etc.). They're gone in v2 — use `ChainKeys.X_MAINNET`.
|
|
42
|
+
- **DO NOT** reach for `as any` / `as IEvmWalletProvider` casts when wiring `useWalletProvider({ xChainId })` into mutation `mutate(vars)`. v2 supports the broad-union case structurally; the cast is not needed. See `recipes/wallet-connectivity.md` § "No type cast is needed".
|
|
42
43
|
|
|
43
44
|
## Stop conditions (defer to user)
|
|
44
45
|
|
|
@@ -33,6 +33,8 @@ Every v2 design concept the hooks rest on, in one TOC-navigable file. Read it on
|
|
|
33
33
|
|
|
34
34
|
`SodaxProvider` does **not** depend on `@sodax/wallet-sdk-react` — wallet state is wired side-by-side. Backend / non-React consumers (Node scripts, bots) bypass dapp-kit entirely and use `@sodax/sdk` directly with their own wallet implementation.
|
|
35
35
|
|
|
36
|
+
**Config reactivity.** `config` is tracked by reference - see [`recipes/setup.md § Config reactivity`](recipes/setup.md#config-reactivity) for the module-const vs `useMemo` patterns.
|
|
37
|
+
|
|
36
38
|
### `createSodaxQueryClient`
|
|
37
39
|
|
|
38
40
|
Returns a `QueryClient` pre-wired with a `MutationCache.onError` hook for global mutation observability. Default behavior: logs every mutation failure to console as `[sodax] Mutation error: <error>`.
|
|
@@ -237,7 +239,7 @@ queryClient.invalidateQueries({ queryKey: ['dex', 'positionInfo', tokenId, poolK
|
|
|
237
239
|
|
|
238
240
|
## Hook organization
|
|
239
241
|
|
|
240
|
-
|
|
242
|
+
Hooks organized by feature domain in `src/hooks/`:
|
|
241
243
|
|
|
242
244
|
```
|
|
243
245
|
hooks/
|
|
@@ -248,13 +250,13 @@ hooks/
|
|
|
248
250
|
├── swap/ # useQuote, useSwap, useStatus, useSwapAllowance, useSwapApprove,
|
|
249
251
|
│ # useCancelSwap, useCreateLimitOrder, useCancelLimitOrder
|
|
250
252
|
├── mm/ # useSupply, useWithdraw, useBorrow, useRepay, useMMAllowance, useMMApprove,
|
|
251
|
-
│ # reserves data hooks
|
|
253
|
+
│ # reserves data hooks
|
|
252
254
|
├── bridge/ # useBridge, useBridgeAllowance, useBridgeApprove, bridgeable amounts/tokens
|
|
253
|
-
├── staking/ # useStake, useUnstake, useInstantUnstake, useClaim, staking info hooks
|
|
254
|
-
├── dex/ # usePools, useDexDeposit, useDexWithdraw, liquidity hooks
|
|
255
|
-
├── bitcoin/ # useRadfiSession, fund/withdraw, UTXO management
|
|
256
|
-
├── backend/ # Intent tracking, swap submission, orderbook, money market position queries
|
|
257
|
-
├── partner/ # Partner fee claim, auto-swap preferences, token approval
|
|
255
|
+
├── staking/ # useStake, useUnstake, useInstantUnstake, useClaim, staking info hooks
|
|
256
|
+
├── dex/ # usePools, useDexDeposit, useDexWithdraw, liquidity hooks
|
|
257
|
+
├── bitcoin/ # useRadfiSession, fund/withdraw, UTXO management
|
|
258
|
+
├── backend/ # Intent tracking, swap submission, orderbook, money market position queries
|
|
259
|
+
├── partner/ # Partner fee claim, auto-swap preferences, token approval
|
|
258
260
|
├── recovery/ # useHubAssetBalances, useWithdrawHubAsset
|
|
259
261
|
└── migrate/ # useMigrateIcxToSoda, useRevertMigrateSodaToIcx, useMigratebnUSD,
|
|
260
262
|
# useMigrateBaln, useMigrationApprove, useMigrationAllowance
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Per-feature reference docs. Each file documents the hooks, params types, return types, and feature-specific gotchas — but doesn't include extended worked examples (those live in [`../recipes/`](../recipes/)).
|
|
4
4
|
|
|
5
|
-
| File |
|
|
6
|
-
|
|
7
|
-
| [`swap.md`](swap.md) |
|
|
8
|
-
| [`money-market.md`](money-market.md) |
|
|
9
|
-
| [`staking.md`](staking.md) |
|
|
10
|
-
| [`bridge.md`](bridge.md) |
|
|
11
|
-
| [`dex.md`](dex.md) |
|
|
12
|
-
| [`migration.md`](migration.md) |
|
|
13
|
-
| [`bitcoin.md`](bitcoin.md) |
|
|
14
|
-
| [`auxiliary-services.md`](auxiliary-services.md) |
|
|
5
|
+
| File | What's covered |
|
|
6
|
+
|---|---|
|
|
7
|
+
| [`swap.md`](swap.md) | Cross-chain swaps via the intent solver: `useQuote`, `useSwap`, allowance/approve, status polling, limit orders. |
|
|
8
|
+
| [`money-market.md`](money-market.md) | Lending/borrowing on the cross-chain MM: `useSupply`, `useBorrow`, `useWithdraw`, `useRepay`, allowance/approve, reserves data hooks. |
|
|
9
|
+
| [`staking.md`](staking.md) | SODA → xSODA staking: `useStake`, `useUnstake`, `useInstantUnstake`, `useClaim`, `useCancelUnstake`, allowance/approve, info/ratio reads. |
|
|
10
|
+
| [`bridge.md`](bridge.md) | Cross-chain token bridging: `useBridge`, allowance/approve, bridgeable amount/tokens. |
|
|
11
|
+
| [`dex.md`](dex.md) | Concentrated liquidity DEX: assets in/out, liquidity supply/decrease, claim rewards, position info, pool reads, param builders. |
|
|
12
|
+
| [`migration.md`](migration.md) | Token migration: `useMigrateIcxToSoda`, `useRevertMigrateSodaToIcx`, `useMigratebnUSD`, `useMigrateBaln`, allowance/approve. |
|
|
13
|
+
| [`bitcoin.md`](bitcoin.md) | Radfi (dapp-kit-unique): session, trading wallet, fund/withdraw, UTXOs. |
|
|
14
|
+
| [`auxiliary-services.md`](auxiliary-services.md) | Partner fee claiming, recovery, backend queries (intent tracking, orderbook, MM data), shared utilities (xBalances, gas, trustlines). |
|
|
15
15
|
|
|
16
16
|
## Reference vs recipes
|
|
17
17
|
|
|
@@ -6,7 +6,7 @@ Pair: [`../../migration/features/auxiliary-services.md`](../../migration/feature
|
|
|
6
6
|
|
|
7
7
|
## Partner
|
|
8
8
|
|
|
9
|
-
Partner fee claiming and auto-swap preferences.
|
|
9
|
+
Partner fee claiming and auto-swap preferences.
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
12
|
// @ai-snippets-skip
|
|
@@ -22,7 +22,7 @@ useFeeClaimSwap({ mutationOptions }); // Claim partner fees via sw
|
|
|
22
22
|
|
|
23
23
|
## Recovery
|
|
24
24
|
|
|
25
|
-
Withdraw stuck hub-wallet assets back to a spoke chain.
|
|
25
|
+
Withdraw stuck hub-wallet assets back to a spoke chain.
|
|
26
26
|
|
|
27
27
|
```ts
|
|
28
28
|
// @ai-snippets-skip
|
|
@@ -32,7 +32,7 @@ useWithdrawHubAsset({ mutationOptions });
|
|
|
32
32
|
|
|
33
33
|
## Backend queries (read-only data)
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
No wallet connection required.
|
|
36
36
|
|
|
37
37
|
### Intent tracking
|
|
38
38
|
|
|
@@ -29,10 +29,38 @@ useUserFormattedSummary({ params, queryOptions }); // Health factor, collate
|
|
|
29
29
|
useUserReservesData({ params, queryOptions }); // Per-reserve user position
|
|
30
30
|
|
|
31
31
|
// aTokens
|
|
32
|
-
useAToken({ params, queryOptions });
|
|
33
|
-
useATokensBalances({ params, queryOptions });
|
|
32
|
+
useAToken({ params: { aToken }, queryOptions }); // aToken metadata (single)
|
|
33
|
+
useATokensBalances({ params: { aTokens, spokeChainKey, userAddress }, queryOptions }); // aToken balances (batched multicall)
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
### Read-hook param shapes
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
// @ai-snippets-skip
|
|
40
|
+
// useUserFormattedSummary / useUserReservesData — user-position queries
|
|
41
|
+
type UseUserFormattedSummaryParams = ReadHookParams<FormatUserSummaryResponse, {
|
|
42
|
+
spokeChainKey: SpokeChainKey | undefined;
|
|
43
|
+
userAddress: string | undefined;
|
|
44
|
+
}>;
|
|
45
|
+
// Same shape on useUserReservesData. The hook derives the hub wallet from (spokeChainKey, userAddress) internally.
|
|
46
|
+
|
|
47
|
+
// useAToken — single aToken metadata; FLAT (no chain/user fields)
|
|
48
|
+
type UseATokenParams = ReadHookParams<ATokenData, {
|
|
49
|
+
aToken: Address | string | undefined;
|
|
50
|
+
}>;
|
|
51
|
+
// ATokenData = Erc20Token & { chainKey: ChainKey }
|
|
52
|
+
|
|
53
|
+
// useATokensBalances — batched aToken balances
|
|
54
|
+
type UseATokensBalancesParams = ReadHookParams<Map<Address, bigint>, {
|
|
55
|
+
aTokens: readonly Address[];
|
|
56
|
+
spokeChainKey: SpokeChainKey | undefined;
|
|
57
|
+
userAddress: string | undefined;
|
|
58
|
+
}>;
|
|
59
|
+
// Returns a Map keyed by aToken address. The hook resolves the hub wallet from (spokeChainKey, userAddress).
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> **Read-side chain key is `spokeChainKey`, not `srcChainKey`.** Mutation hooks (`useSupply`/`useBorrow`/etc.) use `srcChainKey` because the request crosses chains and needs a source. Read hooks describe a user's position on a single spoke chain — the field is `spokeChainKey`. Applies to `useATokensBalances`, `useUserFormattedSummary`, and `useUserReservesData` (`useAToken` is metadata-only and takes neither). Don't grep-replace one for the other.
|
|
63
|
+
|
|
36
64
|
## Mutation params
|
|
37
65
|
|
|
38
66
|
All four user mutations share the same TVars shape (only the `action` literal differs):
|
|
@@ -191,16 +191,17 @@ type MoneyMarketSupplyParams<K extends SpokeChainKey = SpokeChainKey> = {
|
|
|
191
191
|
token: string;
|
|
192
192
|
amount: bigint;
|
|
193
193
|
action: 'supply';
|
|
194
|
-
|
|
195
|
-
|
|
194
|
+
dstChainKey?: SpokeChainKey;
|
|
195
|
+
dstAddress?: string;
|
|
196
196
|
};
|
|
197
197
|
|
|
198
|
-
// Borrow / Withdraw / Repay follow the same shape with their respective `action` literal
|
|
198
|
+
// Borrow / Withdraw / Repay follow the same shape with their respective `action` literal
|
|
199
|
+
// (`'borrow'` / `'withdraw'` / `'repay'`) and the same `src*` / `dst*` field names.
|
|
199
200
|
```
|
|
200
201
|
|
|
201
202
|
## Notes
|
|
202
203
|
|
|
203
204
|
- **Borrow/withdraw skip approval** — `useMMAllowance` returns `true` automatically for these actions.
|
|
204
205
|
- **Health factor < 1.0** means liquidation risk.
|
|
205
|
-
- All operations
|
|
206
|
+
- All four operations (supply / borrow / withdraw / repay) accept optional `dstChainKey` / `dstAddress` for cross-chain delivery — omit both for same-chain. There are no `from*` / `to*` field variants on any action.
|
|
206
207
|
- Mutations throw on SDK failure — use `mutateAsyncSafe` for `Result<T>` ergonomics without `try/catch`.
|
|
@@ -47,6 +47,30 @@ export function Providers({ children }: { children: React.ReactNode }) {
|
|
|
47
47
|
}
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
### Config reactivity
|
|
51
|
+
|
|
52
|
+
`SodaxProvider`'s `config` prop is tracked by **reference**, not by value. The SDK is re-instantiated whenever the prop identity changes - resetting wagmi connection state, in-flight RPC, and any persisted state inside `useSodaxContext` consumers. Choose the pattern that matches your config source:
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
// @ai-snippets-skip — illustrative; uses placeholder values + JSX without surrounding imports
|
|
56
|
+
// ✅ Static config — module constant (preferred when nothing depends on runtime state).
|
|
57
|
+
const sodaxConfig: DeepPartial<SodaxConfig> = {
|
|
58
|
+
chains: { [ChainKeys.SONIC_MAINNET]: { rpcUrl: '...' } },
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// ✅ Runtime-switchable config — useMemo with explicit deps.
|
|
62
|
+
// Re-runs only when listed deps change, so the SDK survives unrelated re-renders.
|
|
63
|
+
const sodaxConfig = useMemo(
|
|
64
|
+
() => ({ solver: solverConfigMap[solverEnv], chains: { ... } }),
|
|
65
|
+
[solverEnv], // SDK re-inits when solverEnv switches.
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
// ❌ Inline — new identity every parent render, SDK churns on every render.
|
|
69
|
+
<SodaxProvider config={{ chains: { ... } }}>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Drive runtime config switches (solver env, feature flags, etc.) through `useMemo` deps - never remount `SodaxProvider` for them.
|
|
73
|
+
|
|
50
74
|
### Optional: Add Wallet Provider
|
|
51
75
|
|
|
52
76
|
If you want to use `@sodax/wallet-sdk-react` for wallet connectivity, wrap `SodaxWalletProvider` inside `QueryClientProvider`:
|
|
@@ -99,3 +99,30 @@ function SwapButton() {
|
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
This pattern is consistent across all features: `useSwap`, `useBridge`, `useSupply`, `useStake`, `useDexDeposit`, etc.
|
|
102
|
+
|
|
103
|
+
## No type cast is needed — broad-union wiring just works
|
|
104
|
+
|
|
105
|
+
A common anti-pattern is reaching for `as any` / `as IEvmWalletProvider` when the runtime-typed `walletProvider` from `useWalletProvider({ xChainId })` is passed into a mutation hook. **That cast is not needed.** v2 accepts the broad-union wallet-provider type as long as the chain key on the payload and the wallet provider both come from the same runtime `xChainId` value.
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
// @ai-snippets-skip — illustrative anti-pattern vs correct
|
|
109
|
+
// ❌ ANTI-PATTERN — unnecessary cast
|
|
110
|
+
const walletProvider = useWalletProvider({ xChainId });
|
|
111
|
+
await swap({ params, walletProvider: walletProvider as any }); // don't
|
|
112
|
+
await swap({ params, walletProvider: walletProvider as IEvmWalletProvider }); // don't
|
|
113
|
+
|
|
114
|
+
// ✅ CORRECT — pass directly, TypeScript infers the relationship
|
|
115
|
+
const walletProvider = useWalletProvider({ xChainId });
|
|
116
|
+
if (!walletProvider) return; // narrow undefined first
|
|
117
|
+
await swap({ params, walletProvider });
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Why this works
|
|
121
|
+
|
|
122
|
+
- `useWalletProvider({ xChainId })` returns `GetWalletProviderType<typeof xChainId> | undefined`. When `xChainId` is a runtime value (e.g. from props/state typed `SpokeChainKey`), the return type is the **broad union** `IWalletProvider | undefined`, not `any`.
|
|
123
|
+
- Mutation hooks like `useSwap<K>()` default `K` to the broad `SpokeChainKey` union. Their `mutate` vars are typed `{ params: SwapParams<SpokeChainKey>, walletProvider: GetWalletProviderType<SpokeChainKey> }` — i.e. `walletProvider` is the same broad union.
|
|
124
|
+
- The two unions are structurally assignable. No cast required.
|
|
125
|
+
|
|
126
|
+
### When the cast is actually needed
|
|
127
|
+
|
|
128
|
+
If you've narrowed `xChainId` to a literal (e.g. via `chainKey === ChainKeys.BSC_MAINNET` checks in a branch) and the mutation hook is also generic-narrowed, you'll get narrower types on both sides. Even there, the cast is usually unnecessary — TypeScript propagates the narrowed `K` through the hook's generic. Reach for a cast only when you can produce a real TS error message proving it's needed.
|
|
@@ -4,7 +4,7 @@ Lookup tables. Read while writing code; not a tutorial.
|
|
|
4
4
|
|
|
5
5
|
| File | What's in it |
|
|
6
6
|
|---|---|
|
|
7
|
-
| [`hooks-index.md`](hooks-index.md) | Comprehensive hook table (
|
|
7
|
+
| [`hooks-index.md`](hooks-index.md) | Comprehensive hook table (organized by feature, with hook type and purpose). |
|
|
8
8
|
| [`querykey-conventions.md`](querykey-conventions.md) | Mandatory queryKey/mutationKey shape rules + per-feature key tables. |
|
|
9
9
|
| [`public-api.md`](public-api.md) | What `@sodax/dapp-kit` exports + import rules. |
|
|
10
10
|
| [`glossary.md`](glossary.md) | Type aliases (`ReadHookParams`, `MutationHookParams`, `SafeUseMutationResult`, `MutationHookOptions`, etc.). |
|
|
@@ -132,6 +132,8 @@ App-level React component. Provides:
|
|
|
132
132
|
|
|
133
133
|
Optional config: `<SodaxProvider config={DeepPartial<SodaxConfig>}>`. Without config, SDK uses packaged defaults.
|
|
134
134
|
|
|
135
|
+
Config is tracked by **reference** - see [`recipes/setup.md § Config reactivity`](../recipes/setup.md#config-reactivity) for module-const vs `useMemo` patterns.
|
|
136
|
+
|
|
135
137
|
### `createSodaxQueryClient`
|
|
136
138
|
|
|
137
139
|
Factory for a `QueryClient` with `MutationCache.onError` pre-wired for global mutation observability. Optional — if you construct your own `QueryClient`, dapp-kit hooks still work; you just don't get the global observability seam.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Hooks index — `@sodax/dapp-kit` v2
|
|
2
2
|
|
|
3
|
-
Comprehensive hook table
|
|
3
|
+
Comprehensive hook table across 11 feature domains. Use this when you know the feature you're building but don't remember the exact hook name.
|
|
4
4
|
|
|
5
5
|
## Provider + context
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ Comprehensive hook table. ~95 hooks across 11 feature domains. Use this when you
|
|
|
11
11
|
| `useSodaxContext` | Utility | Access the `Sodax` SDK instance |
|
|
12
12
|
| `useHubProvider` | Utility | Hub chain (Sonic) provider |
|
|
13
13
|
|
|
14
|
-
## Swap
|
|
14
|
+
## Swap
|
|
15
15
|
|
|
16
16
|
| Hook | Type | Purpose |
|
|
17
17
|
|---|---|---|
|
|
@@ -24,7 +24,7 @@ Comprehensive hook table. ~95 hooks across 11 feature domains. Use this when you
|
|
|
24
24
|
| `useCreateLimitOrder` | Mutation | Create a limit order (no deadline) |
|
|
25
25
|
| `useCancelLimitOrder` | Mutation | Cancel a limit order |
|
|
26
26
|
|
|
27
|
-
## Money market
|
|
27
|
+
## Money market
|
|
28
28
|
|
|
29
29
|
| Hook | Type | Purpose |
|
|
30
30
|
|---|---|---|
|
|
@@ -43,7 +43,7 @@ Comprehensive hook table. ~95 hooks across 11 feature domains. Use this when you
|
|
|
43
43
|
| `useAToken` | Query | aToken metadata |
|
|
44
44
|
| `useATokensBalances` | Query | aToken balances |
|
|
45
45
|
|
|
46
|
-
## Bridge
|
|
46
|
+
## Bridge
|
|
47
47
|
|
|
48
48
|
| Hook | Type | Purpose |
|
|
49
49
|
|---|---|---|
|
|
@@ -53,7 +53,7 @@ Comprehensive hook table. ~95 hooks across 11 feature domains. Use this when you
|
|
|
53
53
|
| `useGetBridgeableAmount` | Query | Max bridgeable amount between two `XToken`s |
|
|
54
54
|
| `useGetBridgeableTokens` | Query | Tokens bridgeable to a destination chain |
|
|
55
55
|
|
|
56
|
-
## Staking
|
|
56
|
+
## Staking
|
|
57
57
|
|
|
58
58
|
| Hook | Type | Purpose |
|
|
59
59
|
|---|---|---|
|
|
@@ -76,7 +76,7 @@ Comprehensive hook table. ~95 hooks across 11 feature domains. Use this when you
|
|
|
76
76
|
| `useInstantUnstakeRatio` | Query | Instant unstake rate |
|
|
77
77
|
| `useConvertedAssets` | Query | xSODA → SODA conversion |
|
|
78
78
|
|
|
79
|
-
## DEX
|
|
79
|
+
## DEX
|
|
80
80
|
|
|
81
81
|
| Hook | Type | Purpose |
|
|
82
82
|
|---|---|---|
|
|
@@ -97,7 +97,7 @@ Comprehensive hook table. ~95 hooks across 11 feature domains. Use this when you
|
|
|
97
97
|
| `useCreateSupplyLiquidityParams` | Param builder | Build tick-range + liquidity params |
|
|
98
98
|
| `useCreateDecreaseLiquidityParams` | Param builder | Build decrease params from position state |
|
|
99
99
|
|
|
100
|
-
## Migration
|
|
100
|
+
## Migration
|
|
101
101
|
|
|
102
102
|
| Hook | Type | Purpose |
|
|
103
103
|
|---|---|---|
|
|
@@ -108,7 +108,7 @@ Comprehensive hook table. ~95 hooks across 11 feature domains. Use this when you
|
|
|
108
108
|
| `useMigrationApprove` | Mutation | Approve before migration (action-discriminated) |
|
|
109
109
|
| `useMigrationAllowance` | Query | Approval check (action-discriminated) |
|
|
110
110
|
|
|
111
|
-
## Bitcoin / Radfi
|
|
111
|
+
## Bitcoin / Radfi
|
|
112
112
|
|
|
113
113
|
| Hook | Type | Purpose |
|
|
114
114
|
|---|---|---|
|
|
@@ -122,7 +122,7 @@ Comprehensive hook table. ~95 hooks across 11 feature domains. Use this when you
|
|
|
122
122
|
| `useExpiredUtxos` | Query | Expired UTXOs (polls 60s) |
|
|
123
123
|
| `useRenewUtxos` | Mutation | Renew expired UTXOs |
|
|
124
124
|
|
|
125
|
-
## Backend queries
|
|
125
|
+
## Backend queries
|
|
126
126
|
|
|
127
127
|
### Intents
|
|
128
128
|
|
|
@@ -151,7 +151,7 @@ Comprehensive hook table. ~95 hooks across 11 feature domains. Use this when you
|
|
|
151
151
|
| `useBackendMoneyMarketAssetBorrowers` | Borrowers for an asset |
|
|
152
152
|
| `useBackendAllMoneyMarketBorrowers` | All borrowers |
|
|
153
153
|
|
|
154
|
-
## Partner
|
|
154
|
+
## Partner
|
|
155
155
|
|
|
156
156
|
| Hook | Type | Purpose |
|
|
157
157
|
|---|---|---|
|
|
@@ -162,14 +162,14 @@ Comprehensive hook table. ~95 hooks across 11 feature domains. Use this when you
|
|
|
162
162
|
| `useSetSwapPreference` | Mutation | Set swap preference |
|
|
163
163
|
| `useFeeClaimSwap` | Mutation | Claim partner fees via swap |
|
|
164
164
|
|
|
165
|
-
## Recovery
|
|
165
|
+
## Recovery
|
|
166
166
|
|
|
167
167
|
| Hook | Type | Purpose |
|
|
168
168
|
|---|---|---|
|
|
169
169
|
| `useHubAssetBalances` | Query | Hub asset balances |
|
|
170
170
|
| `useWithdrawHubAsset` | Mutation | Withdraw hub asset |
|
|
171
171
|
|
|
172
|
-
## Shared
|
|
172
|
+
## Shared
|
|
173
173
|
|
|
174
174
|
| Hook | Type | Purpose |
|
|
175
175
|
|---|---|---|
|
|
@@ -183,10 +183,6 @@ Comprehensive hook table. ~95 hooks across 11 feature domains. Use this when you
|
|
|
183
183
|
| `unwrapResult` | Internal | `Result<T>` → throw / return |
|
|
184
184
|
| `toResult` | Internal | `Promise<T>` → `Result<T>` |
|
|
185
185
|
|
|
186
|
-
## Total
|
|
187
|
-
|
|
188
|
-
41 mutations + ~50 queries + utilities + provider = **~95 hooks**.
|
|
189
|
-
|
|
190
186
|
## Cross-references
|
|
191
187
|
|
|
192
188
|
- [`../features/`](../features/) — per-feature reference docs (params types, return shapes, gotchas).
|
|
@@ -8,14 +8,14 @@ The package's `src/index.ts` re-exports four buckets:
|
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
10
|
// @ai-snippets-skip
|
|
11
|
-
export * from './hooks/index.js'; //
|
|
11
|
+
export * from './hooks/index.js'; // hooks across 11 feature dirs
|
|
12
12
|
export * from './providers/index.js'; // SodaxProvider, createSodaxQueryClient
|
|
13
13
|
export * from './utils/index.js'; // dex-utils param builders
|
|
14
14
|
export * from '@sodax/sdk'; // FULL @sodax/sdk re-export
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Practical implications:
|
|
18
|
-
- All
|
|
18
|
+
- All hooks are importable from the root: `import { useSwap, useSupply, ... } from '@sodax/dapp-kit'`.
|
|
19
19
|
- All `@sodax/sdk` types are importable from `@sodax/dapp-kit` directly: `import { ChainKeys, type SodaxConfig, type CreateIntentParams } from '@sodax/dapp-kit'`.
|
|
20
20
|
- You may also import directly from `@sodax/sdk` — both work, both are stable.
|
|
21
21
|
|
|
@@ -96,6 +96,8 @@ Full SDK-level detail: [`../../../../sdk/ai-exported/migration/breaking-changes/
|
|
|
96
96
|
+ }}>
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
**Config is tracked by reference in v2.** See [`../../integration/recipes/setup.md § Config reactivity`](../../integration/recipes/setup.md#config-reactivity) for the module-const vs `useMemo` patterns. Drive runtime config switches (e.g. solver env) through `useMemo` deps, not by remounting the provider.
|
|
100
|
+
|
|
99
101
|
Other v1 fields renamed or restructured:
|
|
100
102
|
|
|
101
103
|
| v1 | v2 |
|
|
@@ -4,7 +4,7 @@ Pair: [`../../integration/features/auxiliary-services.md`](../../integration/fea
|
|
|
4
4
|
|
|
5
5
|
Smaller surfaces grouped together: partner, recovery, backend queries, shared utilities. Most changes are mechanical — single-object params, mutateAsyncSafe — same as the other features.
|
|
6
6
|
|
|
7
|
-
## Partner
|
|
7
|
+
## Partner
|
|
8
8
|
|
|
9
9
|
```diff
|
|
10
10
|
- const claim = useFeeClaimSwap(spokeProvider);
|
|
@@ -18,7 +18,7 @@ Smaller surfaces grouped together: partner, recovery, backend queries, shared ut
|
|
|
18
18
|
|
|
19
19
|
`useFetchAssetsBalances`, `useGetAutoSwapPreferences`, `useIsTokenApproved` — convert to single-object query shape.
|
|
20
20
|
|
|
21
|
-
## Recovery
|
|
21
|
+
## Recovery
|
|
22
22
|
|
|
23
23
|
```diff
|
|
24
24
|
- const withdraw = useWithdrawHubAsset(spokeProvider);
|
|
@@ -26,7 +26,7 @@ Smaller surfaces grouped together: partner, recovery, backend queries, shared ut
|
|
|
26
26
|
+ await withdraw({ params, walletProvider });
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
## Backend queries
|
|
29
|
+
## Backend queries
|
|
30
30
|
|
|
31
31
|
Read-only. No `walletProvider` involved. Convert to single-object query shape.
|
|
32
32
|
|
|
@@ -9,9 +9,11 @@ Pair: [`../../integration/features/bridge.md`](../../integration/features/bridge
|
|
|
9
9
|
1. **`CreateBridgeIntentParams` field renames** (SDK-leakage):
|
|
10
10
|
- `srcChainId` → `srcChainKey`
|
|
11
11
|
- `dstChainId` → `dstChainKey`
|
|
12
|
-
- `
|
|
13
|
-
-
|
|
14
|
-
|
|
12
|
+
- `srcAsset` → `srcToken`
|
|
13
|
+
- `dstAsset` → `dstToken`
|
|
14
|
+
- `recipient` is **unchanged** (stays `recipient` in v2 — it is NOT renamed to `dstAddress`; the only `dstAddress`-shaped field in v2 lives on money-market params, not bridge)
|
|
15
|
+
- **NEW required**: `srcAddress` (the user's spoke-side sender address, distinct from `recipient` which is the destination)
|
|
16
|
+
2. **`bridge()` return shape changed.** v1 was `Promise<string>` (a single tx hash that threw on error). v2 returns `Promise<Result<TxHashPair, BridgeOrchestrationError>>` where `TxHashPair = { srcChainTxHash: string; dstChainTxHash: string }`. **This is the shape at the direct-SDK boundary** (`sodax.bridge.bridge(...)`); the `useBridge` hook does not adapt the inner object, it only unwraps the `Result` wrapper (so the hook surfaces `TxHashPair` directly via `data` / `mutateAsync` / `mutateAsyncSafe`'s `value`). Don't destructure as a tuple — there was no `[spokeTxHash, hubTxHash]` form in either v1 or v2.
|
|
15
17
|
3. **`useGetBridgeableAmount` reshape.** v1 took `(srcChainId, srcAsset, dstChainId, dstAsset)`. v2 takes `{ from: XToken, to: XToken }` — each `XToken` carries its own `chainKey`.
|
|
16
18
|
4. **`useGetBridgeableAmount` return value is `BridgeLimit`, not bare `bigint`.** Access `.value.amount` and `.value.decimals`.
|
|
17
19
|
5. **`useGetBridgeableTokens` is sync now** in the SDK. The hook still returns `UseQueryResult` but the underlying SDK call doesn't fire RPC — it's config-derived.
|
|
@@ -29,7 +31,8 @@ Pair: [`../../integration/features/bridge.md`](../../integration/features/bridge
|
|
|
29
31
|
|
|
30
32
|
const handleBridge = async () => {
|
|
31
33
|
+ if (!walletProvider) return;
|
|
32
|
-
-
|
|
34
|
+
- // v1: single tx hash, throws on failure
|
|
35
|
+
- const txHash: string = await bridge.mutateAsync({
|
|
33
36
|
- params: {
|
|
34
37
|
- srcChainId: BASE_MAINNET_CHAIN_ID,
|
|
35
38
|
- srcAsset: '0x...',
|
|
@@ -39,28 +42,62 @@ Pair: [`../../integration/features/bridge.md`](../../integration/features/bridge
|
|
|
39
42
|
- recipient: '0x...',
|
|
40
43
|
- },
|
|
41
44
|
- });
|
|
42
|
-
- if (result.ok) {
|
|
43
|
-
- const [spokeTxHash, hubTxHash] = result.value;
|
|
44
|
-
- /* ... */
|
|
45
|
-
- }
|
|
46
45
|
+ const result = await bridge({
|
|
47
46
|
+ params: {
|
|
48
47
|
+ srcChainKey: ChainKeys.BASE_MAINNET,
|
|
49
|
-
+ srcAddress, // NEW: required
|
|
50
|
-
+
|
|
48
|
+
+ srcAddress, // NEW: required (your spoke-side sender)
|
|
49
|
+
+ srcToken: '0x...', // RENAMED from `srcAsset`
|
|
51
50
|
+ amount: 1_000_000n,
|
|
52
51
|
+ dstChainKey: ChainKeys.POLYGON_MAINNET,
|
|
53
|
-
+
|
|
54
|
-
+
|
|
52
|
+
+ dstToken: '0x...', // RENAMED from `dstAsset`
|
|
53
|
+
+ recipient: '0x...', // UNCHANGED — destination receiver
|
|
55
54
|
+ },
|
|
56
55
|
+ walletProvider,
|
|
57
56
|
+ });
|
|
58
57
|
+ if (!result.ok) return;
|
|
59
|
-
+ const { srcChainTxHash, dstChainTxHash } = result.value; //
|
|
58
|
+
+ const { srcChainTxHash, dstChainTxHash } = result.value; // TxHashPair object, not [a, b]
|
|
60
59
|
};
|
|
61
60
|
}
|
|
62
61
|
```
|
|
63
62
|
|
|
63
|
+
### Calling `sodax.bridge.bridge()` directly (no hook)
|
|
64
|
+
|
|
65
|
+
If you call the SDK directly inside a custom `useMutation` (instead of `useBridge`), the return shape is **exactly the same** — the dapp-kit hook only unwraps the `Result` wrapper, it does not reshape `TxHashPair`:
|
|
66
|
+
|
|
67
|
+
```diff
|
|
68
|
+
- // v1 direct-SDK call:
|
|
69
|
+
- const txHash: string = await sodax.bridge.bridge({ params: { /* v1 shape */ }, spokeProvider });
|
|
70
|
+
+ // v2 direct-SDK call:
|
|
71
|
+
+ const result = await sodax.bridge.bridge({
|
|
72
|
+
+ params: {
|
|
73
|
+
+ srcChainKey: ChainKeys.BASE_MAINNET,
|
|
74
|
+
+ srcAddress,
|
|
75
|
+
+ srcToken: '0x...',
|
|
76
|
+
+ amount: 1_000_000n,
|
|
77
|
+
+ dstChainKey: ChainKeys.POLYGON_MAINNET,
|
|
78
|
+
+ dstToken: '0x...',
|
|
79
|
+
+ recipient: '0x...',
|
|
80
|
+
+ },
|
|
81
|
+
+ raw: false,
|
|
82
|
+
+ walletProvider,
|
|
83
|
+
+ });
|
|
84
|
+
+ // Type: Result<TxHashPair, BridgeOrchestrationError>
|
|
85
|
+
+ if (!result.ok) {
|
|
86
|
+
+ // result.error is a SodaxError<C> with feature: 'bridge'
|
|
87
|
+
+ return;
|
|
88
|
+
+ }
|
|
89
|
+
+ const { srcChainTxHash, dstChainTxHash } = result.value; // same shape as the hook
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The hook equivalence in code:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
// @ai-snippets-skip
|
|
96
|
+
// What `useBridge` does internally (sketch):
|
|
97
|
+
// mutationFn: async vars => unwrapResult(await sodax.bridge.bridge({ ...vars, raw: false }))
|
|
98
|
+
// `unwrapResult` throws on `!ok` and returns `value` on `ok` — that's the only adapter.
|
|
99
|
+
```
|
|
100
|
+
|
|
64
101
|
### `useGetBridgeableAmount` — params + return reshape
|
|
65
102
|
|
|
66
103
|
```diff
|
|
@@ -10,7 +10,7 @@ Pair: [`../../integration/features/money-market.md`](../../integration/features/
|
|
|
10
10
|
2. **`MoneyMarketSupplyParams<K>` (and the four similar action-param types) gained required `srcChainKey` + `srcAddress`** — SDK-leakage.
|
|
11
11
|
3. **`useMMAllowance` auto-skips on-chain checks for borrow/withdraw** — v1 may have had this too, but v2 returns `true` synchronously for those actions instead of issuing a no-op RPC.
|
|
12
12
|
4. **`useMMApprove` returns standard `SafeUseMutationResult`** — `isLoading` → `isPending`.
|
|
13
|
-
5. **
|
|
13
|
+
5. **Position / aToken-balance hooks renamed `address` → `userAddress`.** Applies to `useUserFormattedSummary`, `useUserReservesData`, **and `useATokensBalances`** (which also drops `spokeProvider` and adds a required `spokeChainKey` alongside `aTokens` + `userAddress`). `useAToken` is unaffected — it takes only `{ aToken }`.
|
|
14
14
|
|
|
15
15
|
## Per-method delta
|
|
16
16
|
|
|
@@ -45,7 +45,25 @@ Pair: [`../../integration/features/money-market.md`](../../integration/features/
|
|
|
45
45
|
}
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
`useBorrow`, `useWithdraw`, `useRepay` follow the same pattern with their respective `action` literals (`'borrow'` / `'withdraw'` / `'repay'`).
|
|
48
|
+
`useBorrow`, `useWithdraw`, `useRepay` follow the same pattern with their respective `action` literals (`'borrow'` / `'withdraw'` / `'repay'`). **All four MM action params share an identical field shape** — only the `action` literal differs:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
// @ai-snippets-skip
|
|
52
|
+
// MoneyMarketSupplyParams<K> | MoneyMarketBorrowParams<K> | MoneyMarketWithdrawParams<K> | MoneyMarketRepayParams<K>
|
|
53
|
+
{
|
|
54
|
+
srcChainKey: K; // required — where the user signs / funds come from
|
|
55
|
+
srcAddress: string; // required — user's spoke-side address on srcChainKey
|
|
56
|
+
token: string; // token on srcChainKey (supply/repay) or on dstChainKey (borrow/withdraw)
|
|
57
|
+
amount: bigint;
|
|
58
|
+
action: 'supply' | 'borrow' | 'withdraw' | 'repay';
|
|
59
|
+
dstChainKey?: SpokeChainKey; // optional — defaults to srcChainKey (same-chain)
|
|
60
|
+
dstAddress?: string; // optional — defaults to srcAddress (same-chain)
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Cross-chain delivery via `dstChainKey` / `dstAddress` is supported on **all four** actions, not just borrow/repay. Omit both for same-chain operations.
|
|
65
|
+
|
|
66
|
+
> **Porting note** — v2 does NOT use `fromChainKey` / `fromAddress` / `toChainKey` / `toAddress` (or `fromChainId` / `toChainId`) on any MM action. Borrow and repay use the **same** `src*` / `dst*` field names as supply and withdraw — the v2 type system unified the cross-chain shape across all four actions. If your v1 call sites or app types carry `from*` / `to*` naming for the spend-chain vs. debt-chain, rename to `src*` / `dst*` (e.g. `fromChainKey → srcChainKey`, `toChainKey → dstChainKey`). See the SDK migration doc cross-link below for explicit borrow/repay diff examples.
|
|
49
67
|
|
|
50
68
|
### `useMMAllowance` — auto-skip
|
|
51
69
|
|
|
@@ -82,11 +100,35 @@ User-position hooks renamed param fields:
|
|
|
82
100
|
+ const { data } = useUserFormattedSummary({ params: { spokeChainKey, userAddress } });
|
|
83
101
|
```
|
|
84
102
|
|
|
103
|
+
Same shape on `useUserReservesData`.
|
|
104
|
+
|
|
105
|
+
### `useATokensBalances`
|
|
106
|
+
|
|
107
|
+
```diff
|
|
108
|
+
- const { data: balances } = useATokensBalances({ aTokens, spokeProvider, userAddress });
|
|
109
|
+
+ const { data: balances } = useATokensBalances({
|
|
110
|
+
+ params: {
|
|
111
|
+
+ aTokens, // readonly Address[]
|
|
112
|
+
+ spokeChainKey, // SpokeChainKey — NOT `srcChainKey`
|
|
113
|
+
+ userAddress, // string — spoke-side user address (renamed from `address` if you're porting from any earlier shape)
|
|
114
|
+
+ },
|
|
115
|
+
+ });
|
|
116
|
+
+ // data: Map<Address, bigint> | undefined (already unwrapped — hook throws on SDK !ok)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Three things to verify when porting:
|
|
120
|
+
|
|
121
|
+
- `spokeProvider` is gone — the hook derives the hub wallet internally from `(spokeChainKey, userAddress)` via `EvmHubProvider.getUserHubWalletAddress`.
|
|
122
|
+
- The chain-key field is **`spokeChainKey`**, not `srcChainKey`. `src*` names belong to mutation params (`useSupply`/`useBorrow`/etc.) — read hooks for a single-chain position use `spokeChainKey`.
|
|
123
|
+
- The user-address field is **`userAddress`**, not `address` — same rename as `useUserFormattedSummary` and `useUserReservesData`.
|
|
124
|
+
|
|
125
|
+
`useAToken` (metadata-only) is unaffected by the user/chain renames — it takes only `{ aToken }`.
|
|
126
|
+
|
|
85
127
|
## Pitfalls
|
|
86
128
|
|
|
87
129
|
1. **`srcAddress` is the user's spoke-side address**, not the hub address. Hub wallet is derived internally.
|
|
88
130
|
2. **`useMMAllowance` returns `true` instantly for borrow/withdraw** — don't wait on the query state. Branch on `isApproved` directly.
|
|
89
|
-
3. **Cross-chain
|
|
131
|
+
3. **Cross-chain delivery (all four actions)**: omit `dstChainKey` / `dstAddress` for same-chain. Don't pass `dstChainKey === srcChainKey` (let the default kick in). The field names are `src*` / `dst*` on **every** MM action — there is no `from*` / `to*` variant.
|
|
90
132
|
4. **`MoneyMarketSupplyParams<K>` is now generic.** Use `as const` on `srcChainKey` for narrowing: `srcChainKey: ChainKeys.BASE_MAINNET as const`.
|
|
91
133
|
|
|
92
134
|
## Cross-references
|