@sodax/dapp-kit 2.0.0-rc.3 → 2.0.0-rc.5
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/README.md +9 -63
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +0 -2
- package/package.json +31 -20
- package/ai-exported/AGENTS.md +0 -134
- package/ai-exported/integration/README.md +0 -49
- package/ai-exported/integration/ai-rules.md +0 -80
- package/ai-exported/integration/architecture.md +0 -276
- package/ai-exported/integration/features/README.md +0 -29
- package/ai-exported/integration/features/auxiliary-services.md +0 -169
- package/ai-exported/integration/features/bitcoin.md +0 -87
- package/ai-exported/integration/features/bridge.md +0 -91
- package/ai-exported/integration/features/dex.md +0 -152
- package/ai-exported/integration/features/migration.md +0 -118
- package/ai-exported/integration/features/money-market.md +0 -144
- package/ai-exported/integration/features/staking.md +0 -123
- package/ai-exported/integration/features/swap.md +0 -101
- package/ai-exported/integration/quickstart.md +0 -187
- package/ai-exported/integration/recipes/README.md +0 -136
- package/ai-exported/integration/recipes/backend-queries.md +0 -157
- package/ai-exported/integration/recipes/bitcoin.md +0 -193
- package/ai-exported/integration/recipes/bridge.md +0 -174
- package/ai-exported/integration/recipes/dex.md +0 -204
- package/ai-exported/integration/recipes/invalidations.md +0 -115
- package/ai-exported/integration/recipes/migration.md +0 -212
- package/ai-exported/integration/recipes/money-market.md +0 -207
- package/ai-exported/integration/recipes/mutation-error-handling.md +0 -118
- package/ai-exported/integration/recipes/observability.md +0 -93
- package/ai-exported/integration/recipes/setup.md +0 -168
- package/ai-exported/integration/recipes/staking.md +0 -202
- package/ai-exported/integration/recipes/swap.md +0 -272
- package/ai-exported/integration/recipes/wallet-connectivity.md +0 -128
- package/ai-exported/integration/reference/README.md +0 -12
- package/ai-exported/integration/reference/glossary.md +0 -190
- package/ai-exported/integration/reference/hooks-index.md +0 -190
- package/ai-exported/integration/reference/public-api.md +0 -110
- package/ai-exported/integration/reference/querykey-conventions.md +0 -179
- package/ai-exported/migration/README.md +0 -60
- package/ai-exported/migration/ai-rules.md +0 -81
- package/ai-exported/migration/breaking-changes/hook-signatures.md +0 -233
- package/ai-exported/migration/breaking-changes/querykey-conventions.md +0 -108
- package/ai-exported/migration/breaking-changes/result-handling.md +0 -211
- package/ai-exported/migration/breaking-changes/sdk-leakage.md +0 -167
- package/ai-exported/migration/checklist.md +0 -89
- package/ai-exported/migration/features/README.md +0 -34
- package/ai-exported/migration/features/auxiliary-services.md +0 -114
- package/ai-exported/migration/features/bitcoin.md +0 -88
- package/ai-exported/migration/features/bridge.md +0 -160
- package/ai-exported/migration/features/dex.md +0 -101
- package/ai-exported/migration/features/migration.md +0 -120
- package/ai-exported/migration/features/money-market.md +0 -139
- package/ai-exported/migration/features/staking.md +0 -109
- package/ai-exported/migration/features/swap.md +0 -133
- package/ai-exported/migration/recipes.md +0 -185
- package/ai-exported/migration/reference/README.md +0 -15
- package/ai-exported/migration/reference/deleted-hooks.md +0 -110
- package/ai-exported/migration/reference/error-shape-crosswalk.md +0 -144
- package/ai-exported/migration/reference/renamed-hooks.md +0 -68
- package/dist/index.cjs +0 -2641
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -1557
- package/dist/index.mjs.map +0 -1
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
# Money Market migration — v1 → v2 (dapp-kit)
|
|
2
|
-
|
|
3
|
-
Pair: [`../../integration/features/money-market.md`](../../integration/features/money-market.md).
|
|
4
|
-
|
|
5
|
-
## TL;DR
|
|
6
|
-
|
|
7
|
-
> Cross-cutting conventions (drop `spokeProvider`, single-object hook init, `mutate(vars)` for domain inputs, `mutateAsyncSafe` ergonomics) — see [`../breaking-changes/hook-signatures.md`](../breaking-changes/hook-signatures.md) and [`../breaking-changes/result-handling.md`](../breaking-changes/result-handling.md). Feature-specific deltas below:
|
|
8
|
-
|
|
9
|
-
1. **`useSupply` / `useBorrow` / `useWithdraw` / `useRepay`** all switch to single-object `{ mutationOptions }` hook init + `mutate({ params, walletProvider })`.
|
|
10
|
-
2. **`MoneyMarketSupplyParams<K>` (and the four similar action-param types) gained required `srcChainKey` + `srcAddress`** — SDK-leakage.
|
|
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
|
-
4. **`useMMApprove` returns standard `SafeUseMutationResult`** — `isLoading` → `isPending`.
|
|
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
|
-
|
|
15
|
-
## Per-method delta
|
|
16
|
-
|
|
17
|
-
### `useSupply` (and `useBorrow` / `useWithdraw` / `useRepay`)
|
|
18
|
-
|
|
19
|
-
```diff
|
|
20
|
-
function SupplyButton({ token, amount, srcAddress }) {
|
|
21
|
-
- const supply = useSupply(spokeProvider);
|
|
22
|
-
+ const walletProvider = useWalletProvider({ xChainId: ChainKeys.BASE_MAINNET });
|
|
23
|
-
+ const { mutateAsyncSafe: supply, isPending } = useSupply();
|
|
24
|
-
|
|
25
|
-
const handleSupply = async () => {
|
|
26
|
-
+ if (!walletProvider) return;
|
|
27
|
-
- const result = await supply.mutateAsync({ params: { token, amount, action: 'supply' } });
|
|
28
|
-
- if (result.ok) {
|
|
29
|
-
- const txHashPair = result.value;
|
|
30
|
-
- /* ... */
|
|
31
|
-
- }
|
|
32
|
-
+ const result = await supply({
|
|
33
|
-
+ params: {
|
|
34
|
-
+ srcChainKey: ChainKeys.BASE_MAINNET, // NEW: required
|
|
35
|
-
+ srcAddress, // NEW: required
|
|
36
|
-
+ token,
|
|
37
|
-
+ amount,
|
|
38
|
-
+ action: 'supply',
|
|
39
|
-
+ },
|
|
40
|
-
+ walletProvider,
|
|
41
|
-
+ });
|
|
42
|
-
+ if (!result.ok) return;
|
|
43
|
-
+ const { srcChainTxHash, dstChainTxHash } = result.value; // TxHashPair
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
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.
|
|
67
|
-
|
|
68
|
-
### `useMMAllowance` — auto-skip
|
|
69
|
-
|
|
70
|
-
```diff
|
|
71
|
-
- const { data: isApproved } = useMMAllowance({ params, spokeProvider });
|
|
72
|
-
+ const { data: isApproved } = useMMAllowance({ params: { payload: params } });
|
|
73
|
-
+ // No walletProvider — read-only (SDK call uses `raw: true` internally).
|
|
74
|
-
+ // For borrow/withdraw actions, returns `true` synchronously (no RPC call).
|
|
75
|
-
+ // For supply/repay, reads on-chain allowance.
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### `useMMApprove`
|
|
79
|
-
|
|
80
|
-
```diff
|
|
81
|
-
- const { approve, isLoading } = useMMApprove(spokeProvider);
|
|
82
|
-
- await approve(params);
|
|
83
|
-
+ const { mutateAsync: approve, isPending } = useMMApprove();
|
|
84
|
-
+ await approve({ params, walletProvider });
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Reserve data hooks
|
|
88
|
-
|
|
89
|
-
Most got the single-object shape:
|
|
90
|
-
|
|
91
|
-
```diff
|
|
92
|
-
- const { data } = useReservesData({ ...refetchOptions });
|
|
93
|
-
+ const { data } = useReservesData({ queryOptions: { ...refetchOptions } });
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
User-position hooks renamed param fields:
|
|
97
|
-
|
|
98
|
-
```diff
|
|
99
|
-
- const { data } = useUserFormattedSummary({ spokeChainKey, address: userAddress });
|
|
100
|
-
+ const { data } = useUserFormattedSummary({ params: { spokeChainKey, userAddress } });
|
|
101
|
-
```
|
|
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
|
-
|
|
127
|
-
## Pitfalls
|
|
128
|
-
|
|
129
|
-
1. **`srcAddress` is the user's spoke-side address**, not the hub address. Hub wallet is derived internally.
|
|
130
|
-
2. **`useMMAllowance` returns `true` instantly for borrow/withdraw** — don't wait on the query state. Branch on `isApproved` directly.
|
|
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.
|
|
132
|
-
4. **`MoneyMarketSupplyParams<K>` is now generic.** Use `as const` on `srcChainKey` for narrowing: `srcChainKey: ChainKeys.BASE_MAINNET as const`.
|
|
133
|
-
|
|
134
|
-
## Cross-references
|
|
135
|
-
|
|
136
|
-
- [`../../integration/features/money-market.md`](../../integration/features/money-market.md) — v2 reference.
|
|
137
|
-
- [`../../integration/recipes/money-market.md`](../../integration/recipes/money-market.md) — full v2 worked example.
|
|
138
|
-
- [`../breaking-changes/sdk-leakage.md`](../breaking-changes/sdk-leakage.md) — `srcChainKey`/`srcAddress` required.
|
|
139
|
-
- [`../../../../sdk/ai-exported/migration/features/money-market.md`](../../../../sdk/ai-exported/migration/features/money-market.md) — underlying SDK MM migration.
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
# Staking migration — v1 → v2 (dapp-kit)
|
|
2
|
-
|
|
3
|
-
Pair: [`../../integration/features/staking.md`](../../integration/features/staking.md).
|
|
4
|
-
|
|
5
|
-
## TL;DR
|
|
6
|
-
|
|
7
|
-
> Cross-cutting conventions (drop `spokeProvider`, single-object hook init, `mutate(vars)` for domain inputs, `mutateAsyncSafe` ergonomics) — see [`../breaking-changes/hook-signatures.md`](../breaking-changes/hook-signatures.md) and [`../breaking-changes/result-handling.md`](../breaking-changes/result-handling.md). Feature-specific deltas below:
|
|
8
|
-
|
|
9
|
-
1. **All five mutations** (`useStake`, `useUnstake`, `useInstantUnstake`, `useClaim`, `useCancelUnstake`) drop `spokeProvider` from hook init; `walletProvider` flows through `mutate(vars)`.
|
|
10
|
-
2. **Three approve hooks** (`useStakeApprove`, `useUnstakeApprove`, `useInstantUnstakeApprove`) — same shape change. Each approves a different token (SODA for stake; xSODA for unstake/instant).
|
|
11
|
-
3. **`useStakeRatio` return changed.** v2: `Result<[xSodaAmount, previewDepositAmount]>` — a 2-tuple. v1 returned a single bigint.
|
|
12
|
-
4. **`useUnstakingInfo` return shape changed.** v2: `Result<UnstakingInfo>` where `UnstakingInfo = { userUnstakeSodaRequests: UserUnstakeInfo[], totalUnstaking: bigint }`. v1 may have returned just the array — v2 wraps it in an object.
|
|
13
|
-
5. **Action params gained `srcChainKey` + `srcAddress`.** Same SDK-leakage as MM.
|
|
14
|
-
|
|
15
|
-
## Per-method delta
|
|
16
|
-
|
|
17
|
-
### `useStake` (template for all five)
|
|
18
|
-
|
|
19
|
-
```diff
|
|
20
|
-
function StakeButton({ amount, srcAddress }) {
|
|
21
|
-
- const stake = useStake(spokeProvider);
|
|
22
|
-
+ const walletProvider = useWalletProvider({ xChainId: ChainKeys.BASE_MAINNET });
|
|
23
|
-
+ const { mutateAsyncSafe: stake } = useStake();
|
|
24
|
-
|
|
25
|
-
const handleStake = async () => {
|
|
26
|
-
+ if (!walletProvider) return;
|
|
27
|
-
- await stake.mutateAsync({ params: { amount, minReceive, action: 'stake' } });
|
|
28
|
-
+ const result = await stake({
|
|
29
|
-
+ params: {
|
|
30
|
-
+ srcChainKey: ChainKeys.BASE_MAINNET,
|
|
31
|
-
+ srcAddress,
|
|
32
|
-
+ amount,
|
|
33
|
-
+ minReceive,
|
|
34
|
-
+ action: 'stake',
|
|
35
|
-
+ },
|
|
36
|
-
+ walletProvider,
|
|
37
|
-
+ });
|
|
38
|
-
+ if (!result.ok) return;
|
|
39
|
-
+ const { srcChainTxHash, dstChainTxHash } = result.value;
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
`useUnstake` / `useInstantUnstake` / `useClaim` / `useCancelUnstake` follow the same pattern with their respective params types.
|
|
45
|
-
|
|
46
|
-
### Approve hooks
|
|
47
|
-
|
|
48
|
-
Each of stake / unstake / instantUnstake has its OWN approve hook (different tokens):
|
|
49
|
-
|
|
50
|
-
```diff
|
|
51
|
-
- const { approve, isLoading } = useStakeApprove(spokeProvider);
|
|
52
|
-
- await approve({ amount, action: 'stake' });
|
|
53
|
-
+ const { mutateAsync: approve, isPending } = useStakeApprove();
|
|
54
|
-
+ await approve({ params: { srcChainKey, srcAddress, amount, action: 'stake' }, walletProvider });
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
`useUnstakeApprove`, `useInstantUnstakeApprove` — same pattern.
|
|
58
|
-
|
|
59
|
-
### `useStakeRatio` — return type change
|
|
60
|
-
|
|
61
|
-
```diff
|
|
62
|
-
- const { data: ratio } = useStakeRatio(amount);
|
|
63
|
-
- if (ratio) {
|
|
64
|
-
- const xSodaAmount = ratio; // v1 returned single bigint
|
|
65
|
-
- /* ... */
|
|
66
|
-
- }
|
|
67
|
-
+ const { data: ratio } = useStakeRatio({ params: { amount } });
|
|
68
|
-
+ if (ratio?.ok) {
|
|
69
|
-
+ const [xSodaAmount, previewDepositAmount] = ratio.value; // v2 returns tuple
|
|
70
|
-
+ }
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### `useUnstakingInfo` — return shape change
|
|
74
|
-
|
|
75
|
-
```diff
|
|
76
|
-
- const { data: requests } = useUnstakingInfo(spokeProvider);
|
|
77
|
-
- requests?.map((r) => /* ... */); // v1 was an array
|
|
78
|
-
+ const { data: result } = useUnstakingInfo({ params: { srcAddress, srcChainKey } });
|
|
79
|
-
+ if (result?.ok) {
|
|
80
|
-
+ const { userUnstakeSodaRequests, totalUnstaking } = result.value; // v2 is object
|
|
81
|
-
+ userUnstakeSodaRequests.map((r) => /* ... */);
|
|
82
|
-
+ }
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### `useUnstakingInfoWithPenalty`
|
|
86
|
-
|
|
87
|
-
New in v2 — wraps `useUnstakingInfo`'s base shape with a per-request penalty annotation. Skip this section if your v1 codebase didn't compute penalty client-side.
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
// @ai-snippets-skip
|
|
91
|
-
const { data: result } = useUnstakingInfoWithPenalty({ params: { srcAddress, srcChainKey } });
|
|
92
|
-
if (result?.ok) {
|
|
93
|
-
const { requestsWithPenalty } = result.value; // each adds penalty, penaltyPercentage, claimableAmount
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Pitfalls
|
|
98
|
-
|
|
99
|
-
1. **`useStakeRatio` returns a tuple, not a single bigint.** v1 was simpler; v2 returns `[xSodaAmount, previewDepositAmount]`. Adjust render code.
|
|
100
|
-
2. **`useStakingInfo` is unwrapped (not Result), but `useUnstakingInfo` IS Result-wrapped.** Asymmetric — check the integration docs per hook.
|
|
101
|
-
3. **`useUnstakingInfoWithPenalty` returns an object with `requestsWithPenalty` array embedded** — don't `.value.map(...)`, use `.value.requestsWithPenalty.map(...)`.
|
|
102
|
-
4. **Unstake has a waiting period.** Display via `useStakingConfig().unstakingPeriod`. Shows up in v1 too, but the read shape may have changed.
|
|
103
|
-
5. **Instant unstake bypasses the waiting period but pays slippage.** Use `useInstantUnstakeRatio` to preview; set `minAmount` in params for slippage protection.
|
|
104
|
-
|
|
105
|
-
## Cross-references
|
|
106
|
-
|
|
107
|
-
- [`../../integration/features/staking.md`](../../integration/features/staking.md) — v2 reference.
|
|
108
|
-
- [`../../integration/recipes/staking.md`](../../integration/recipes/staking.md) — full v2 worked example.
|
|
109
|
-
- [`../../../../sdk/ai-exported/migration/features/staking.md`](../../../../sdk/ai-exported/migration/features/staking.md) — underlying SDK staking migration.
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
# Swap migration — v1 → v2 (dapp-kit)
|
|
2
|
-
|
|
3
|
-
Pair: [`../../integration/features/swap.md`](../../integration/features/swap.md).
|
|
4
|
-
|
|
5
|
-
## TL;DR
|
|
6
|
-
|
|
7
|
-
> Cross-cutting conventions (drop `spokeProvider`, single-object hook init, `mutate(vars)` for domain inputs, `mutateAsyncSafe` ergonomics) — see [`../breaking-changes/hook-signatures.md`](../breaking-changes/hook-signatures.md) and [`../breaking-changes/result-handling.md`](../breaking-changes/result-handling.md). Feature-specific deltas below:
|
|
8
|
-
|
|
9
|
-
1. **Drop `spokeProvider` from `useSwap` and `useSwapApprove` hook init.** Pass `walletProvider` (from `useWalletProvider({ xChainId: chainKey })`) into `mutate(vars)`.
|
|
10
|
-
2. **`useSwapAllowance({ params: { payload, srcChainKey, walletProvider } })`** — query inputs all nest under `params` (no top-level `spokeProvider` or `walletProvider`); the SDK request goes under `params.payload`.
|
|
11
|
-
3. **Approve hook return shape changed.** `{ approve, isLoading } = useSwapApprove(...)` → `{ mutateAsync: approve, isPending } = useSwapApprove()`.
|
|
12
|
-
4. **`mutationFn` throws on SDK `!ok`.** Either wrap `mutateAsync` in `try/catch` or use `mutateAsyncSafe` for `Result<T>` branching.
|
|
13
|
-
5. **Field on `Intent` read shape kept its name.** `Intent.srcChain` / `Intent.dstChain` are still `IntentRelayChainId` (bigint) — distinct from request-side `srcChainKey` / `dstChainKey` on action params.
|
|
14
|
-
6. **`useStatus({ params: { intentTxHash } })` — single-object query shape.** v1's positional version is gone. Key was renamed `intentHash → intentTxHash`. Return is `Result<SolverIntentStatusResponse, SolverErrorResponse> | undefined` — branch on `data?.ok` before reading status fields.
|
|
15
|
-
|
|
16
|
-
## Per-method delta
|
|
17
|
-
|
|
18
|
-
### `useSwap` — execute swap
|
|
19
|
-
|
|
20
|
-
```diff
|
|
21
|
-
function SwapButton({ intentParams }: { intentParams: CreateIntentParams }) {
|
|
22
|
-
- const swap = useSwap(spokeProvider);
|
|
23
|
-
+ const walletProvider = useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET });
|
|
24
|
-
+ const { mutateAsyncSafe: swap, isPending } = useSwap();
|
|
25
|
-
|
|
26
|
-
const handleSwap = async () => {
|
|
27
|
-
+ if (!walletProvider) return;
|
|
28
|
-
- const result = await swap.mutateAsync({ params: intentParams });
|
|
29
|
-
- if (result.ok) {
|
|
30
|
-
- // v1: result.value was a TUPLE — destructure positionally
|
|
31
|
-
- const [executionResponse] = result.value;
|
|
32
|
-
- const txHash = executionResponse.intent_hash;
|
|
33
|
-
- /* ... */
|
|
34
|
-
- } else {
|
|
35
|
-
- toast.error(result.error.message);
|
|
36
|
-
- }
|
|
37
|
-
+ const result = await swap({ params: intentParams, walletProvider });
|
|
38
|
-
+ if (!result.ok) {
|
|
39
|
-
+ toast.error(result.error instanceof Error ? result.error.message : 'Swap failed');
|
|
40
|
-
+ return;
|
|
41
|
-
+ }
|
|
42
|
-
+ // v2: result.value is a NAMED OBJECT (SwapResponse) — destructure by name
|
|
43
|
-
+ const { solverExecutionResponse, intent, intentDeliveryInfo } = result.value;
|
|
44
|
-
+ const intentHash = solverExecutionResponse.intent_hash; // protocol-level intent id (v1 ≈ executionResponse.intent_hash)
|
|
45
|
-
+ const spokeTxHash = intentDeliveryInfo.srcTxHash; // on-chain tx hash on srcChainKey — use for tx-history display
|
|
46
|
-
+ /* ... */
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
#### `SwapResponse` field map (`result.value`)
|
|
52
|
-
|
|
53
|
-
| Field | Type | Use it for |
|
|
54
|
-
|---|---|---|
|
|
55
|
-
| `solverExecutionResponse` | `{ answer: 'OK'; intent_hash: Hex }` | Protocol-level intent identifier. **`solverExecutionResponse.intent_hash` is the v2 equivalent of v1's `executionResponse.intent_hash`.** Pass it to `useStatus({ params: { intentTxHash } })` to poll execution status. |
|
|
56
|
-
| `intent` | `Intent` | Intent metadata (`intentId: bigint`, `creator`, tokens, amounts, `srcChain`/`dstChain` as `IntentRelayChainId` bigints). **No transaction hashes on this object** — don't read `intent.intent_hash` (does not exist) or `intent.tx_hash`. |
|
|
57
|
-
| `intentDeliveryInfo` | `{ srcChainKey, srcTxHash, srcAddress, dstChainKey, dstTxHash, dstAddress }` | **On-chain transaction hashes.** `srcTxHash` is the spoke-chain tx on `srcChainKey` (the one that typically feeds a user-facing transaction history); `dstTxHash` is the delivery tx on `dstChainKey`. |
|
|
58
|
-
|
|
59
|
-
**Porting `[executionResponse] = result.value` (v1 tuple) → v2:** rename to `{ solverExecutionResponse } = result.value`. Any `executionResponse.intent_hash` read becomes `solverExecutionResponse.intent_hash`. If the value was being used as the **transaction hash** in a transaction-history row (not as the intent identifier), switch to `intentDeliveryInfo.srcTxHash` instead — `intent_hash` and `srcTxHash` are not interchangeable.
|
|
60
|
-
|
|
61
|
-
### `useSwapApprove` — return shape
|
|
62
|
-
|
|
63
|
-
```diff
|
|
64
|
-
- const { approve, isLoading, error } = useSwapApprove(spokeProvider);
|
|
65
|
-
- await approve(intentParams);
|
|
66
|
-
+ const { mutateAsync: approve, isPending, error } = useSwapApprove();
|
|
67
|
-
+ await approve({ params: intentParams, walletProvider });
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
`isLoading` → `isPending` (React Query 5 convention).
|
|
71
|
-
|
|
72
|
-
### `useSwapAllowance` — payload + srcChainKey + walletProvider all under `params`
|
|
73
|
-
|
|
74
|
-
```diff
|
|
75
|
-
- const { data: allowanceResult } = useSwapAllowance({ params: intentParams, spokeProvider });
|
|
76
|
-
+ const { data: isApproved } = useSwapAllowance({
|
|
77
|
-
+ params: { payload: intentParams, srcChainKey: ChainKeys.BSC_MAINNET, walletProvider },
|
|
78
|
-
+ });
|
|
79
|
-
+ // `data` is `boolean | undefined` (already unwrapped); no `.ok` branch needed.
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### `useStatus` — single-object shape + param renamed `intentHash → intentTxHash`
|
|
83
|
-
|
|
84
|
-
```diff
|
|
85
|
-
- const { data: status } = useStatus(intentHash);
|
|
86
|
-
+ const { data: status } = useStatus({ params: { intentTxHash } });
|
|
87
|
-
+ // `data` is `Result<SolverIntentStatusResponse, SolverErrorResponse> | undefined` —
|
|
88
|
-
+ // branch on `data?.ok` before reading `data.value.<fields>`.
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### `useQuote` — single-object shape + SDK request nested under `params.payload`
|
|
92
|
-
|
|
93
|
-
```diff
|
|
94
|
-
- const { data: quote } = useQuote({
|
|
95
|
-
- token_src: SRC_TOKEN,
|
|
96
|
-
- token_dst: DST_TOKEN,
|
|
97
|
-
- token_src_blockchain_id: BSC_MAINNET_CHAIN_ID,
|
|
98
|
-
- token_dst_blockchain_id: ARBITRUM_MAINNET_CHAIN_ID,
|
|
99
|
-
- amount,
|
|
100
|
-
- quote_type: 'exact_input',
|
|
101
|
-
- });
|
|
102
|
-
+ const { data: quote } = useQuote({
|
|
103
|
-
+ params: {
|
|
104
|
-
+ payload: {
|
|
105
|
-
+ token_src: SRC_TOKEN,
|
|
106
|
-
+ token_dst: DST_TOKEN,
|
|
107
|
-
+ token_src_blockchain_id: ChainKeys.BSC_MAINNET,
|
|
108
|
-
+ token_dst_blockchain_id: ChainKeys.ARBITRUM_MAINNET,
|
|
109
|
-
+ amount,
|
|
110
|
-
+ quote_type: 'exact_input',
|
|
111
|
-
+ },
|
|
112
|
-
+ },
|
|
113
|
-
+ });
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
`SolverIntentQuoteRequest` shape unchanged. Two v2 changes: SDK request is nested under `params.payload` (not directly under `params`); constants renamed (`*_MAINNET_CHAIN_ID` → `ChainKeys.X_MAINNET`).
|
|
117
|
-
|
|
118
|
-
### `useCreateLimitOrder` / `useCancelLimitOrder` / `useCancelSwap`
|
|
119
|
-
|
|
120
|
-
Same shape changes as `useSwap` — drop `spokeProvider`, move domain inputs to `mutate(vars)`.
|
|
121
|
-
|
|
122
|
-
## Pitfalls
|
|
123
|
-
|
|
124
|
-
1. **`Intent.srcChain` / `Intent.dstChain` look like they should rename.** They didn't. Those are read-shape `IntentRelayChainId` (bigint), distinct from request-side `srcChainKey` / `dstChainKey`. Don't grep-replace.
|
|
125
|
-
2. **`useStatus` polling default.** v2 polls every 3 s unconditionally once `intentTxHash` is supplied (it does not auto-stop on terminal states — your UI should disable rendering when no longer needed, or override `queryOptions.refetchInterval: false`). Port any v1 custom polling to `queryOptions.refetchInterval`.
|
|
126
|
-
3. **`useQuote` data is `Result<T>`** — branch on `data?.ok` before reading `data.value.quoted_amount`.
|
|
127
|
-
|
|
128
|
-
## Cross-references
|
|
129
|
-
|
|
130
|
-
- [`../../integration/features/swap.md`](../../integration/features/swap.md) — v2 reference.
|
|
131
|
-
- [`../../integration/recipes/swap.md`](../../integration/recipes/swap.md) — full v2 worked example.
|
|
132
|
-
- [`../breaking-changes/hook-signatures.md`](../breaking-changes/hook-signatures.md), [`../breaking-changes/result-handling.md`](../breaking-changes/result-handling.md) — cross-cutting deltas.
|
|
133
|
-
- [`../../../../sdk/ai-exported/migration/features/swap.md`](../../../../sdk/ai-exported/migration/features/swap.md) — underlying SDK swap migration.
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
# Migration recipes — `@sodax/dapp-kit` v1 → v2
|
|
2
|
-
|
|
3
|
-
Codemods, adapters, and incremental migration patterns. Use these when full conversion in one pass isn't realistic or when you want to mechanize the boring parts.
|
|
4
|
-
|
|
5
|
-
## Codemod 1: chain-id constants → ChainKeys
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
# From your consumer's repo root:
|
|
9
|
-
find src -type f \( -name '*.ts' -o -name '*.tsx' \) | xargs sed -i '' -E 's/\b([A-Z_]+)_MAINNET_CHAIN_ID\b/ChainKeys.\1_MAINNET/g'
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
Then add `import { ChainKeys } from '@sodax/sdk'` (or `'@sodax/dapp-kit'` — both work) where needed. tsc will flag missing imports.
|
|
13
|
-
|
|
14
|
-
For more sophisticated automation across many files, use ts-morph:
|
|
15
|
-
|
|
16
|
-
```ts
|
|
17
|
-
// @ai-snippets-skip
|
|
18
|
-
// codemod-chain-ids.ts — run with `tsx codemod-chain-ids.ts`
|
|
19
|
-
import { Project, SyntaxKind } from 'ts-morph';
|
|
20
|
-
|
|
21
|
-
const project = new Project({ tsConfigFilePath: './tsconfig.json' });
|
|
22
|
-
|
|
23
|
-
for (const file of project.getSourceFiles('src/**/*.{ts,tsx}')) {
|
|
24
|
-
let needsImport = false;
|
|
25
|
-
|
|
26
|
-
file.forEachDescendant((node) => {
|
|
27
|
-
if (node.getKind() === SyntaxKind.Identifier) {
|
|
28
|
-
const text = node.getText();
|
|
29
|
-
const m = text.match(/^([A-Z_]+)_MAINNET_CHAIN_ID$/);
|
|
30
|
-
if (m) {
|
|
31
|
-
node.replaceWithText(`ChainKeys.${m[1]}_MAINNET`);
|
|
32
|
-
needsImport = true;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
if (needsImport && !file.getImportDeclaration('@sodax/sdk')?.getNamedImports().some(n => n.getName() === 'ChainKeys')) {
|
|
38
|
-
file.addImportDeclaration({ moduleSpecifier: '@sodax/sdk', namedImports: ['ChainKeys'] });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
await project.save();
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Codemod 2: useSpokeProvider deletion (2-arg → 1-arg)
|
|
46
|
-
|
|
47
|
-
`useSpokeProvider` is gone in v2. Replace with `useWalletProvider` from `@sodax/wallet-sdk-react`.
|
|
48
|
-
|
|
49
|
-
v1 had **two positional args**: `useSpokeProvider(spokeChainId, walletProvider)`. v2 collapses to a single options object: `useWalletProvider({ xChainId })`. The second v1 argument is **dropped entirely** — v2 resolves the wallet provider from the wallet-sdk-react store internally based on `xChainId`. If your v1 code constructed a wallet provider separately to pass in, delete that construction code too.
|
|
50
|
-
|
|
51
|
-
```diff
|
|
52
|
-
- // v1 — 2 positional args (chainKey + walletProvider)
|
|
53
|
-
- import { useSpokeProvider } from '@sodax/dapp-kit';
|
|
54
|
-
- const spokeProvider = useSpokeProvider(srcChainId, walletProvider);
|
|
55
|
-
|
|
56
|
-
+ // v2 — 1 options arg, no external walletProvider
|
|
57
|
-
+ import { useWalletProvider } from '@sodax/wallet-sdk-react';
|
|
58
|
-
+ const walletProvider = useWalletProvider({ xChainId: srcChainId });
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
A naive single-pass regex over `useSpokeProvider\(([^)]+)\)` eats both args and produces invalid `useWalletProvider({ xChainId: chainKey, walletProvider })`. Do the rewrite in two passes: first the call shape (drop the second positional arg), then the import (from `@sodax/dapp-kit` → `@sodax/wallet-sdk-react`). A small number of v1 callers used the single-arg form `useSpokeProvider(chainId)` — handle those separately since they don't have a second arg to drop.
|
|
62
|
-
|
|
63
|
-
Update downstream consumers of `spokeProvider` to use `walletProvider` instead — usually inside `mutate(vars)` payloads or query hook params. The field name on payloads also renamed `spokeProvider:` → `walletProvider:` (see `@sodax/sdk/ai-exported/migration/checklist.md` step 7b).
|
|
64
|
-
|
|
65
|
-
## Codemod 3: invalidate*Queries utilities deletion
|
|
66
|
-
|
|
67
|
-
Most v1 consumers had `lib/invalidate*Queries.ts` files. Hook-owned invalidations make these obsolete:
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
# Find them.
|
|
71
|
-
grep -rE '(invalidateMmQueries|invalidateSwapQueries|invalidateBridgeQueries|invalidate\w+Queries)' src/
|
|
72
|
-
|
|
73
|
-
# For each call site, delete the call. The mutation hook handles invalidation.
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
If you have a custom invalidation that dapp-kit's hooks don't know about (e.g. your own analytics view), move it into `mutationOptions.onSuccess`:
|
|
77
|
-
|
|
78
|
-
```diff
|
|
79
|
-
const { mutateAsync: supply } = useSupply({
|
|
80
|
-
+ mutationOptions: {
|
|
81
|
-
+ onSuccess: async (data, vars) => {
|
|
82
|
-
+ await queryClient.invalidateQueries({ queryKey: ['my-app', 'analytics'] });
|
|
83
|
-
+ },
|
|
84
|
-
+ },
|
|
85
|
-
});
|
|
86
|
-
- await supply({ params, spokeProvider });
|
|
87
|
-
- invalidateMmQueries(queryClient, ...); // delete
|
|
88
|
-
- await queryClient.invalidateQueries({ queryKey: ['my-app', 'analytics'] }); // delete
|
|
89
|
-
+ await supply({ params, walletProvider });
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Adapter: Result<T>-shape adapter for legacy error consumers
|
|
93
|
-
|
|
94
|
-
If your consumer code has a helper that branches on a v1 error shape (e.g. `error.code` from old per-feature classes), the minimal change is to map v2 onto v1 at the boundary:
|
|
95
|
-
|
|
96
|
-
```ts
|
|
97
|
-
// adapters/v1ErrorShape.ts
|
|
98
|
-
import { isSodaxError } from '@sodax/dapp-kit';
|
|
99
|
-
|
|
100
|
-
// V1 shape: { code, message, data?: { error } }
|
|
101
|
-
export function adaptToV1ErrorShape(error: unknown): { code?: string; message?: string; data?: { error?: unknown } } | null {
|
|
102
|
-
if (!error) return null;
|
|
103
|
-
if (isSodaxError(error)) {
|
|
104
|
-
return {
|
|
105
|
-
code: error.code,
|
|
106
|
-
message: error.message,
|
|
107
|
-
data: { error: error.cause },
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
if (error instanceof Error) return { code: 'UNKNOWN', message: error.message };
|
|
111
|
-
if (typeof error === 'object') return error as { code?: string; message?: string };
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
Then your existing v1-shape error handlers keep working:
|
|
117
|
-
|
|
118
|
-
```ts
|
|
119
|
-
// @ai-snippets-skip
|
|
120
|
-
const { mutateAsync: swap } = useSwap();
|
|
121
|
-
try {
|
|
122
|
-
await swap({ params, walletProvider });
|
|
123
|
-
} catch (e) {
|
|
124
|
-
const adapted = adaptToV1ErrorShape(e);
|
|
125
|
-
if (adapted?.code === 'INTENT_CREATION_FAILED' /* etc. */) { /* ... */ }
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
Plan to delete the adapter once you've converted error-handling code site-by-site.
|
|
130
|
-
|
|
131
|
-
## Incremental migration: feature-by-feature
|
|
132
|
-
|
|
133
|
-
If the codebase is too large for a single-pass migration, you can convert one feature at a time. The pattern:
|
|
134
|
-
|
|
135
|
-
1. **Pick a low-traffic feature first** (e.g. recovery, partner). It limits blast radius if something breaks.
|
|
136
|
-
2. **Convert that feature's call sites and approve hooks**.
|
|
137
|
-
3. **Run the app, smoke-test the feature**.
|
|
138
|
-
4. **Move on to the next feature**.
|
|
139
|
-
|
|
140
|
-
The catch: SDK-level changes are global (e.g. chain-key terminology). You can't do `xChainId` on `XToken` for swap and `chainKey` for staking — both run on the same SDK. Plan to do all SDK-level migrations in one pass first (Phase 1 + 2 of [`checklist.md`](checklist.md)), then per-feature hook-call-site work in any order (Phase 3+).
|
|
141
|
-
|
|
142
|
-
## Incremental migration: keeping v1 wrappers temporarily
|
|
143
|
-
|
|
144
|
-
If you have many call sites that share a custom wrapper hook (e.g. one your codebase named `useLegacySwap` calling v1 dapp-kit underneath), you can rewrite the wrapper's body to call v2 internally while keeping the wrapper's name and surface intact. Call sites stay unchanged.
|
|
145
|
-
|
|
146
|
-
```tsx
|
|
147
|
-
// Custom wrapper that your codebase already has (with a project-specific name).
|
|
148
|
-
// Rewrite its body to call v2 dapp-kit internally; preserve the surface so
|
|
149
|
-
// existing call sites don't change yet.
|
|
150
|
-
|
|
151
|
-
import { useSwap } from '@sodax/dapp-kit';
|
|
152
|
-
import { useWalletProvider } from '@sodax/wallet-sdk-react';
|
|
153
|
-
import type { CreateIntentParams } from '@sodax/sdk';
|
|
154
|
-
|
|
155
|
-
// Function name starts with `use` because it calls React hooks (`useWalletProvider`,
|
|
156
|
-
// `useSwap`). Inside a component, call it like any other hook.
|
|
157
|
-
export function useLegacySwapAdapter(spokeProvider: unknown, params: CreateIntentParams) {
|
|
158
|
-
const walletProvider = useWalletProvider(/* derive chainKey from spokeProvider */);
|
|
159
|
-
const m = useSwap();
|
|
160
|
-
return {
|
|
161
|
-
swap: async () => {
|
|
162
|
-
if (!walletProvider) throw new Error('wallet not connected');
|
|
163
|
-
// Adapt v2 throw-on-fail back to v1 success-with-Result shape:
|
|
164
|
-
try {
|
|
165
|
-
const value = await m.mutateAsync({ params, walletProvider });
|
|
166
|
-
return { ok: true, value };
|
|
167
|
-
} catch (e) {
|
|
168
|
-
return { ok: false, error: e };
|
|
169
|
-
}
|
|
170
|
-
},
|
|
171
|
-
isLoading: m.isPending,
|
|
172
|
-
error: m.error,
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Then convert call sites at your own pace. Delete the wrapper once you're done.
|
|
178
|
-
|
|
179
|
-
## Cross-references
|
|
180
|
-
|
|
181
|
-
- [`README.md`](README.md) — overview + glossary.
|
|
182
|
-
- [`checklist.md`](checklist.md) — top-down migration checklist.
|
|
183
|
-
- [`ai-rules.md`](ai-rules.md) — DO / DO NOT for the agent doing the migration.
|
|
184
|
-
- [`breaking-changes/`](breaking-changes/) — cross-cutting deltas in detail.
|
|
185
|
-
- [`features/`](features/) — per-feature porting playbooks.
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# Migration reference — `@sodax/dapp-kit` v1 → v2
|
|
2
|
-
|
|
3
|
-
Lookup tables for the v1 → v2 delta. Skim during migration to confirm specific renames or removals.
|
|
4
|
-
|
|
5
|
-
| File | What's in it |
|
|
6
|
-
|---|---|
|
|
7
|
-
| [`deleted-hooks.md`](deleted-hooks.md) | v1 hooks that no longer exist in v2 (`useSpokeProvider`, `invalidateMmQueries`, legacy `useMigrate`-style API). |
|
|
8
|
-
| [`renamed-hooks.md`](renamed-hooks.md) | Hooks whose name or signature changed (rare — most renames are field-level). |
|
|
9
|
-
| [`error-shape-crosswalk.md`](error-shape-crosswalk.md) | v1 error class names → v2 `SodaxError<C>` mapping; how thrown errors look at the consumer level. |
|
|
10
|
-
|
|
11
|
-
For SDK-level reference (deleted exports, renames, error code crosswalk), see [`../../../../sdk/ai-exported/migration/reference/`](../../../../sdk/ai-exported/migration/reference/) — the underlying SDK has its own reference tree.
|
|
12
|
-
|
|
13
|
-
## Pair
|
|
14
|
-
|
|
15
|
-
This `migration/reference/` tree mirrors [`../../integration/reference/`](../../integration/reference/) (which documents v2 directly). When you need both "what does v2 do" and "what changed from v1" — open both.
|