@sodax/dapp-kit 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.
- package/README.md +9 -63
- package/dist/index.d.ts +11 -4
- package/dist/index.mjs +3 -6
- package/package.json +31 -19
- package/src/providers/SodaxProvider.tsx +15 -11
- package/ai-exported/AGENTS.md +0 -134
- package/ai-exported/integration/README.md +0 -49
- package/ai-exported/integration/ai-rules.md +0 -79
- package/ai-exported/integration/architecture.md +0 -274
- 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 -116
- 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 -206
- 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 -144
- 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 -101
- package/ai-exported/integration/reference/README.md +0 -12
- package/ai-exported/integration/reference/glossary.md +0 -188
- 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 -165
- 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 -123
- 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 -97
- package/ai-exported/migration/features/staking.md +0 -109
- package/ai-exported/migration/features/swap.md +0 -118
- package/ai-exported/migration/recipes.md +0 -188
- 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 -66
- package/dist/index.cjs +0 -2642
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -1550
- package/dist/index.mjs.map +0 -1
|
@@ -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,118 +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
|
-
- const { intent, intentDeliveryInfo } = result.value;
|
|
31
|
-
- /* ... */
|
|
32
|
-
- } else {
|
|
33
|
-
- toast.error(result.error.message);
|
|
34
|
-
- }
|
|
35
|
-
+ const result = await swap({ params: intentParams, walletProvider });
|
|
36
|
-
+ if (!result.ok) {
|
|
37
|
-
+ toast.error(result.error instanceof Error ? result.error.message : 'Swap failed');
|
|
38
|
-
+ return;
|
|
39
|
-
+ }
|
|
40
|
-
+ const { intent, intentDeliveryInfo } = result.value;
|
|
41
|
-
+ /* ... */
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### `useSwapApprove` — return shape
|
|
47
|
-
|
|
48
|
-
```diff
|
|
49
|
-
- const { approve, isLoading, error } = useSwapApprove(spokeProvider);
|
|
50
|
-
- await approve(intentParams);
|
|
51
|
-
+ const { mutateAsync: approve, isPending, error } = useSwapApprove();
|
|
52
|
-
+ await approve({ params: intentParams, walletProvider });
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
`isLoading` → `isPending` (React Query 5 convention).
|
|
56
|
-
|
|
57
|
-
### `useSwapAllowance` — payload + srcChainKey + walletProvider all under `params`
|
|
58
|
-
|
|
59
|
-
```diff
|
|
60
|
-
- const { data: allowanceResult } = useSwapAllowance({ params: intentParams, spokeProvider });
|
|
61
|
-
+ const { data: isApproved } = useSwapAllowance({
|
|
62
|
-
+ params: { payload: intentParams, srcChainKey: ChainKeys.BSC_MAINNET, walletProvider },
|
|
63
|
-
+ });
|
|
64
|
-
+ // `data` is `boolean | undefined` (already unwrapped); no `.ok` branch needed.
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### `useStatus` — single-object shape + param renamed `intentHash → intentTxHash`
|
|
68
|
-
|
|
69
|
-
```diff
|
|
70
|
-
- const { data: status } = useStatus(intentHash);
|
|
71
|
-
+ const { data: status } = useStatus({ params: { intentTxHash } });
|
|
72
|
-
+ // `data` is `Result<SolverIntentStatusResponse, SolverErrorResponse> | undefined` —
|
|
73
|
-
+ // branch on `data?.ok` before reading `data.value.<fields>`.
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### `useQuote` — single-object shape + SDK request nested under `params.payload`
|
|
77
|
-
|
|
78
|
-
```diff
|
|
79
|
-
- const { data: quote } = useQuote({
|
|
80
|
-
- token_src: SRC_TOKEN,
|
|
81
|
-
- token_dst: DST_TOKEN,
|
|
82
|
-
- token_src_blockchain_id: BSC_MAINNET_CHAIN_ID,
|
|
83
|
-
- token_dst_blockchain_id: ARBITRUM_MAINNET_CHAIN_ID,
|
|
84
|
-
- amount,
|
|
85
|
-
- quote_type: 'exact_input',
|
|
86
|
-
- });
|
|
87
|
-
+ const { data: quote } = useQuote({
|
|
88
|
-
+ params: {
|
|
89
|
-
+ payload: {
|
|
90
|
-
+ token_src: SRC_TOKEN,
|
|
91
|
-
+ token_dst: DST_TOKEN,
|
|
92
|
-
+ token_src_blockchain_id: ChainKeys.BSC_MAINNET,
|
|
93
|
-
+ token_dst_blockchain_id: ChainKeys.ARBITRUM_MAINNET,
|
|
94
|
-
+ amount,
|
|
95
|
-
+ quote_type: 'exact_input',
|
|
96
|
-
+ },
|
|
97
|
-
+ },
|
|
98
|
-
+ });
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
`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`).
|
|
102
|
-
|
|
103
|
-
### `useCreateLimitOrder` / `useCancelLimitOrder` / `useCancelSwap`
|
|
104
|
-
|
|
105
|
-
Same shape changes as `useSwap` — drop `spokeProvider`, move domain inputs to `mutate(vars)`.
|
|
106
|
-
|
|
107
|
-
## Pitfalls
|
|
108
|
-
|
|
109
|
-
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.
|
|
110
|
-
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`.
|
|
111
|
-
3. **`useQuote` data is `Result<T>`** — branch on `data?.ok` before reading `data.value.quoted_amount`.
|
|
112
|
-
|
|
113
|
-
## Cross-references
|
|
114
|
-
|
|
115
|
-
- [`../../integration/features/swap.md`](../../integration/features/swap.md) — v2 reference.
|
|
116
|
-
- [`../../integration/recipes/swap.md`](../../integration/recipes/swap.md) — full v2 worked example.
|
|
117
|
-
- [`../breaking-changes/hook-signatures.md`](../breaking-changes/hook-signatures.md), [`../breaking-changes/result-handling.md`](../breaking-changes/result-handling.md) — cross-cutting deltas.
|
|
118
|
-
- [`../../../../sdk/ai-exported/migration/features/swap.md`](../../../../sdk/ai-exported/migration/features/swap.md) — underlying SDK swap migration.
|
|
@@ -1,188 +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
|
|
46
|
-
|
|
47
|
-
`useSpokeProvider` is gone in v2. Delete the import + usage; replace with `useWalletProvider` from `@sodax/wallet-sdk-react`.
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
# 1. Find all usages first.
|
|
51
|
-
grep -rE '\buseSpokeProvider\b' src/
|
|
52
|
-
|
|
53
|
-
# 2. Manual delete + rewrite each (no safe sed for this — context varies).
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Per call site, the rewrite:
|
|
57
|
-
|
|
58
|
-
```diff
|
|
59
|
-
- import { useSpokeProvider } from '@sodax/dapp-kit';
|
|
60
|
-
- const spokeProvider = useSpokeProvider({ chainId: BSC_MAINNET_CHAIN_ID });
|
|
61
|
-
+ import { useWalletProvider } from '@sodax/wallet-sdk-react';
|
|
62
|
-
+ import { ChainKeys } from '@sodax/sdk';
|
|
63
|
-
+ const walletProvider = useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET });
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
Then update consumers of `spokeProvider` to use `walletProvider` instead — usually inside `mutate(vars)` payloads, sometimes inside query hook params.
|
|
67
|
-
|
|
68
|
-
## Codemod 3: invalidate*Queries utilities deletion
|
|
69
|
-
|
|
70
|
-
Most v1 consumers had `lib/invalidate*Queries.ts` files. Hook-owned invalidations make these obsolete:
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
# Find them.
|
|
74
|
-
grep -rE '(invalidateMmQueries|invalidateSwapQueries|invalidateBridgeQueries|invalidate\w+Queries)' src/
|
|
75
|
-
|
|
76
|
-
# For each call site, delete the call. The mutation hook handles invalidation.
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
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`:
|
|
80
|
-
|
|
81
|
-
```diff
|
|
82
|
-
const { mutateAsync: supply } = useSupply({
|
|
83
|
-
+ mutationOptions: {
|
|
84
|
-
+ onSuccess: async (data, vars) => {
|
|
85
|
-
+ await queryClient.invalidateQueries({ queryKey: ['my-app', 'analytics'] });
|
|
86
|
-
+ },
|
|
87
|
-
+ },
|
|
88
|
-
});
|
|
89
|
-
- await supply({ params, spokeProvider });
|
|
90
|
-
- invalidateMmQueries(queryClient, ...); // delete
|
|
91
|
-
- await queryClient.invalidateQueries({ queryKey: ['my-app', 'analytics'] }); // delete
|
|
92
|
-
+ await supply({ params, walletProvider });
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Adapter: Result<T>-shape adapter for legacy error consumers
|
|
96
|
-
|
|
97
|
-
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:
|
|
98
|
-
|
|
99
|
-
```ts
|
|
100
|
-
// adapters/v1ErrorShape.ts
|
|
101
|
-
import { isSodaxError } from '@sodax/dapp-kit';
|
|
102
|
-
|
|
103
|
-
// V1 shape: { code, message, data?: { error } }
|
|
104
|
-
export function adaptToV1ErrorShape(error: unknown): { code?: string; message?: string; data?: { error?: unknown } } | null {
|
|
105
|
-
if (!error) return null;
|
|
106
|
-
if (isSodaxError(error)) {
|
|
107
|
-
return {
|
|
108
|
-
code: error.code,
|
|
109
|
-
message: error.message,
|
|
110
|
-
data: { error: error.cause },
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
if (error instanceof Error) return { code: 'UNKNOWN', message: error.message };
|
|
114
|
-
if (typeof error === 'object') return error as { code?: string; message?: string };
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Then your existing v1-shape error handlers keep working:
|
|
120
|
-
|
|
121
|
-
```ts
|
|
122
|
-
// @ai-snippets-skip
|
|
123
|
-
const { mutateAsync: swap } = useSwap();
|
|
124
|
-
try {
|
|
125
|
-
await swap({ params, walletProvider });
|
|
126
|
-
} catch (e) {
|
|
127
|
-
const adapted = adaptToV1ErrorShape(e);
|
|
128
|
-
if (adapted?.code === 'INTENT_CREATION_FAILED' /* etc. */) { /* ... */ }
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
Plan to delete the adapter once you've converted error-handling code site-by-site.
|
|
133
|
-
|
|
134
|
-
## Incremental migration: feature-by-feature
|
|
135
|
-
|
|
136
|
-
If the codebase is too large for a single-pass migration, you can convert one feature at a time. The pattern:
|
|
137
|
-
|
|
138
|
-
1. **Pick a low-traffic feature first** (e.g. recovery, partner). It limits blast radius if something breaks.
|
|
139
|
-
2. **Convert that feature's call sites and approve hooks**.
|
|
140
|
-
3. **Run the app, smoke-test the feature**.
|
|
141
|
-
4. **Move on to the next feature**.
|
|
142
|
-
|
|
143
|
-
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+).
|
|
144
|
-
|
|
145
|
-
## Incremental migration: keeping v1 wrappers temporarily
|
|
146
|
-
|
|
147
|
-
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.
|
|
148
|
-
|
|
149
|
-
```tsx
|
|
150
|
-
// Custom wrapper that your codebase already has (with a project-specific name).
|
|
151
|
-
// Rewrite its body to call v2 dapp-kit internally; preserve the surface so
|
|
152
|
-
// existing call sites don't change yet.
|
|
153
|
-
|
|
154
|
-
import { useSwap } from '@sodax/dapp-kit';
|
|
155
|
-
import { useWalletProvider } from '@sodax/wallet-sdk-react';
|
|
156
|
-
import type { CreateIntentParams } from '@sodax/sdk';
|
|
157
|
-
|
|
158
|
-
// Function name starts with `use` because it calls React hooks (`useWalletProvider`,
|
|
159
|
-
// `useSwap`). Inside a component, call it like any other hook.
|
|
160
|
-
export function useLegacySwapAdapter(spokeProvider: unknown, params: CreateIntentParams) {
|
|
161
|
-
const walletProvider = useWalletProvider(/* derive chainKey from spokeProvider */);
|
|
162
|
-
const m = useSwap();
|
|
163
|
-
return {
|
|
164
|
-
swap: async () => {
|
|
165
|
-
if (!walletProvider) throw new Error('wallet not connected');
|
|
166
|
-
// Adapt v2 throw-on-fail back to v1 success-with-Result shape:
|
|
167
|
-
try {
|
|
168
|
-
const value = await m.mutateAsync({ params, walletProvider });
|
|
169
|
-
return { ok: true, value };
|
|
170
|
-
} catch (e) {
|
|
171
|
-
return { ok: false, error: e };
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
isLoading: m.isPending,
|
|
175
|
-
error: m.error,
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
Then convert call sites at your own pace. Delete the wrapper once you're done.
|
|
181
|
-
|
|
182
|
-
## Cross-references
|
|
183
|
-
|
|
184
|
-
- [`README.md`](README.md) — overview + glossary.
|
|
185
|
-
- [`checklist.md`](checklist.md) — top-down migration checklist.
|
|
186
|
-
- [`ai-rules.md`](ai-rules.md) — DO / DO NOT for the agent doing the migration.
|
|
187
|
-
- [`breaking-changes/`](breaking-changes/) — cross-cutting deltas in detail.
|
|
188
|
-
- [`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.
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# Deleted hooks — v1 → v2
|
|
2
|
-
|
|
3
|
-
Hooks that existed in v1 dapp-kit (or v1-style consumer-side utilities) and have no v2 equivalent.
|
|
4
|
-
|
|
5
|
-
## `useSpokeProvider`
|
|
6
|
-
|
|
7
|
-
| | |
|
|
8
|
-
|---|---|
|
|
9
|
-
| v1 path | `import { useSpokeProvider } from '@sodax/dapp-kit'` |
|
|
10
|
-
| v2 status | **DELETED** |
|
|
11
|
-
| v2 alternative | Use `useWalletProvider({ xChainId: chainKey })` from `@sodax/wallet-sdk-react`, then pass `walletProvider` directly into `mutate(vars)` for mutations or as a query-hook param. |
|
|
12
|
-
|
|
13
|
-
```diff
|
|
14
|
-
- import { useSpokeProvider } from '@sodax/dapp-kit';
|
|
15
|
-
- const spokeProvider = useSpokeProvider({ chainId: BSC_MAINNET_CHAIN_ID });
|
|
16
|
-
+ import { useWalletProvider } from '@sodax/wallet-sdk-react';
|
|
17
|
-
+ import { ChainKeys } from '@sodax/sdk';
|
|
18
|
-
+ const walletProvider = useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET });
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
The chain key on the action params is what routes to the right per-chain spoke service inside the SDK; there's no "spoke provider" object for consumers to construct or hold.
|
|
22
|
-
|
|
23
|
-
## `useMigrate(spokeProvider)` (and any v1 single-migration-hook variant)
|
|
24
|
-
|
|
25
|
-
| | |
|
|
26
|
-
|---|---|
|
|
27
|
-
| v1 path | A single `useMigrate(spokeProvider)` hook (often commented out by the time consumers tried to use it) |
|
|
28
|
-
| v2 status | **DELETED** |
|
|
29
|
-
| v2 alternative | Six per-action hooks: `useMigrateIcxToSoda`, `useRevertMigrateSodaToIcx`, `useMigratebnUSD`, `useMigrateBaln`, `useMigrationApprove`, `useMigrationAllowance`. |
|
|
30
|
-
|
|
31
|
-
See [`../features/migration.md`](../features/migration.md) for the full split.
|
|
32
|
-
|
|
33
|
-
## Consumer-side `invalidate*Queries` utilities
|
|
34
|
-
|
|
35
|
-
| | |
|
|
36
|
-
|---|---|
|
|
37
|
-
| v1 path | Often a `lib/invalidateMmQueries.ts` (or similar per-feature) file in the consumer codebase |
|
|
38
|
-
| v2 status | **No longer needed — DELETE** |
|
|
39
|
-
| v2 alternative | Hook-owned invalidations. Each mutation hook invalidates the relevant query keys in its own `onSuccess`. |
|
|
40
|
-
|
|
41
|
-
```diff
|
|
42
|
-
- // lib/invalidateMmQueries.ts — DELETE this file
|
|
43
|
-
- export function invalidateMmQueries(qc, srcChainKey, userAddress, token) {
|
|
44
|
-
- qc.invalidateQueries({ queryKey: ['mm', 'userReservesData', srcChainKey, userAddress] });
|
|
45
|
-
- qc.invalidateQueries({ queryKey: ['shared', 'xBalances', srcChainKey] });
|
|
46
|
-
- /* ... */
|
|
47
|
-
- }
|
|
48
|
-
|
|
49
|
-
- // call site — DROP the manual invalidation
|
|
50
|
-
- await supply({ params, spokeProvider });
|
|
51
|
-
- invalidateMmQueries(queryClient, srcChainKey, userAddress, token);
|
|
52
|
-
+ // v2 — supply hook invalidates xBalances + userReservesData itself
|
|
53
|
-
+ await supply({ params, walletProvider });
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
For cross-feature invalidations the hook can't know about (e.g. your custom analytics view), use `mutationOptions.onSuccess`:
|
|
57
|
-
|
|
58
|
-
```ts
|
|
59
|
-
// @ai-snippets-skip
|
|
60
|
-
const { mutateAsync: supply } = useSupply({
|
|
61
|
-
mutationOptions: {
|
|
62
|
-
onSuccess: async (data, vars) => {
|
|
63
|
-
await queryClient.invalidateQueries({ queryKey: ['my-app', 'analytics'] });
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## Approve hook return shape (`{ approve, isLoading, error }`)
|
|
70
|
-
|
|
71
|
-
| | |
|
|
72
|
-
|---|---|
|
|
73
|
-
| v1 shape | Per-feature: `useFooApprove(spokeProvider) → { approve, isLoading, error }` |
|
|
74
|
-
| v2 status | **DELETED** (return shape, not the hooks themselves) |
|
|
75
|
-
| v2 alternative | Standard `SafeUseMutationResult` — `mutateAsync` / `mutateAsyncSafe`, `isPending`, `error`. |
|
|
76
|
-
|
|
77
|
-
```diff
|
|
78
|
-
- const { approve, isLoading } = useSwapApprove(spokeProvider);
|
|
79
|
-
- await approve(params);
|
|
80
|
-
+ const { mutateAsync: approve, isPending } = useSwapApprove();
|
|
81
|
-
+ await approve({ params, walletProvider });
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
`isLoading` → `isPending` (React Query 5 convention).
|
|
85
|
-
|
|
86
|
-
## v1 individual chain-id constants (SDK-leakage)
|
|
87
|
-
|
|
88
|
-
Not strictly hooks, but they used to be importable from `@sodax/sdk` (or `@sodax/dapp-kit` re-export):
|
|
89
|
-
|
|
90
|
-
| Constant | v1 value | v2 alternative |
|
|
91
|
-
|---|---|---|
|
|
92
|
-
| `BSC_MAINNET_CHAIN_ID` | `'0x38.bsc'` | `ChainKeys.BSC_MAINNET` |
|
|
93
|
-
| `ARBITRUM_MAINNET_CHAIN_ID` | `'0xa4b1.arbitrum'` | `ChainKeys.ARBITRUM_MAINNET` |
|
|
94
|
-
| `BASE_MAINNET_CHAIN_ID` | `'0x2105.base'` | `ChainKeys.BASE_MAINNET` |
|
|
95
|
-
| `POLYGON_MAINNET_CHAIN_ID` | `'0x89.polygon'` | `ChainKeys.POLYGON_MAINNET` |
|
|
96
|
-
| `ETHEREUM_MAINNET_CHAIN_ID` | `'0x1.ethereum'` | `ChainKeys.ETHEREUM_MAINNET` |
|
|
97
|
-
| ... 11 more | ... | All under `ChainKeys.*` namespace |
|
|
98
|
-
|
|
99
|
-
Codemod with sed:
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
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'
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Cross-references
|
|
106
|
-
|
|
107
|
-
- [`renamed-hooks.md`](renamed-hooks.md) — hooks whose name/signature changed (different from deletions).
|
|
108
|
-
- [`error-shape-crosswalk.md`](error-shape-crosswalk.md) — error class consolidation.
|
|
109
|
-
- [`../breaking-changes/hook-signatures.md`](../breaking-changes/hook-signatures.md) — broader hook-shape changes.
|
|
110
|
-
- [`../breaking-changes/sdk-leakage.md`](../breaking-changes/sdk-leakage.md) — SDK-level migrations leaking through.
|