@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.
Files changed (62) hide show
  1. package/README.md +9 -63
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.mjs +0 -2
  4. package/package.json +31 -20
  5. package/ai-exported/AGENTS.md +0 -134
  6. package/ai-exported/integration/README.md +0 -49
  7. package/ai-exported/integration/ai-rules.md +0 -80
  8. package/ai-exported/integration/architecture.md +0 -276
  9. package/ai-exported/integration/features/README.md +0 -29
  10. package/ai-exported/integration/features/auxiliary-services.md +0 -169
  11. package/ai-exported/integration/features/bitcoin.md +0 -87
  12. package/ai-exported/integration/features/bridge.md +0 -91
  13. package/ai-exported/integration/features/dex.md +0 -152
  14. package/ai-exported/integration/features/migration.md +0 -118
  15. package/ai-exported/integration/features/money-market.md +0 -144
  16. package/ai-exported/integration/features/staking.md +0 -123
  17. package/ai-exported/integration/features/swap.md +0 -101
  18. package/ai-exported/integration/quickstart.md +0 -187
  19. package/ai-exported/integration/recipes/README.md +0 -136
  20. package/ai-exported/integration/recipes/backend-queries.md +0 -157
  21. package/ai-exported/integration/recipes/bitcoin.md +0 -193
  22. package/ai-exported/integration/recipes/bridge.md +0 -174
  23. package/ai-exported/integration/recipes/dex.md +0 -204
  24. package/ai-exported/integration/recipes/invalidations.md +0 -115
  25. package/ai-exported/integration/recipes/migration.md +0 -212
  26. package/ai-exported/integration/recipes/money-market.md +0 -207
  27. package/ai-exported/integration/recipes/mutation-error-handling.md +0 -118
  28. package/ai-exported/integration/recipes/observability.md +0 -93
  29. package/ai-exported/integration/recipes/setup.md +0 -168
  30. package/ai-exported/integration/recipes/staking.md +0 -202
  31. package/ai-exported/integration/recipes/swap.md +0 -272
  32. package/ai-exported/integration/recipes/wallet-connectivity.md +0 -128
  33. package/ai-exported/integration/reference/README.md +0 -12
  34. package/ai-exported/integration/reference/glossary.md +0 -190
  35. package/ai-exported/integration/reference/hooks-index.md +0 -190
  36. package/ai-exported/integration/reference/public-api.md +0 -110
  37. package/ai-exported/integration/reference/querykey-conventions.md +0 -179
  38. package/ai-exported/migration/README.md +0 -60
  39. package/ai-exported/migration/ai-rules.md +0 -81
  40. package/ai-exported/migration/breaking-changes/hook-signatures.md +0 -233
  41. package/ai-exported/migration/breaking-changes/querykey-conventions.md +0 -108
  42. package/ai-exported/migration/breaking-changes/result-handling.md +0 -211
  43. package/ai-exported/migration/breaking-changes/sdk-leakage.md +0 -167
  44. package/ai-exported/migration/checklist.md +0 -89
  45. package/ai-exported/migration/features/README.md +0 -34
  46. package/ai-exported/migration/features/auxiliary-services.md +0 -114
  47. package/ai-exported/migration/features/bitcoin.md +0 -88
  48. package/ai-exported/migration/features/bridge.md +0 -160
  49. package/ai-exported/migration/features/dex.md +0 -101
  50. package/ai-exported/migration/features/migration.md +0 -120
  51. package/ai-exported/migration/features/money-market.md +0 -139
  52. package/ai-exported/migration/features/staking.md +0 -109
  53. package/ai-exported/migration/features/swap.md +0 -133
  54. package/ai-exported/migration/recipes.md +0 -185
  55. package/ai-exported/migration/reference/README.md +0 -15
  56. package/ai-exported/migration/reference/deleted-hooks.md +0 -110
  57. package/ai-exported/migration/reference/error-shape-crosswalk.md +0 -144
  58. package/ai-exported/migration/reference/renamed-hooks.md +0 -68
  59. package/dist/index.cjs +0 -2641
  60. package/dist/index.cjs.map +0 -1
  61. package/dist/index.d.cts +0 -1557
  62. package/dist/index.mjs.map +0 -1
@@ -1,174 +0,0 @@
1
- # Recipe: Bridge
2
-
3
- Cross-chain token transfers via the hub-and-spoke vault architecture.
4
-
5
- **Depends on:** [setup.md](setup.md), [wallet-connectivity.md](wallet-connectivity.md)
6
-
7
- ## Hooks
8
-
9
- | Hook | Type | Purpose |
10
- |------|------|---------|
11
- | `useBridge` | Mutation | Execute a cross-chain bridge transfer |
12
- | `useBridgeAllowance` | Query | Check if token approval is needed |
13
- | `useBridgeApprove` | Mutation | Approve tokens for bridge |
14
- | `useGetBridgeableAmount` | Query | Available bridgeable amount between two tokens |
15
- | `useGetBridgeableTokens` | Query | Tokens bridgeable to a destination chain |
16
-
17
- ## Check Bridgeable Tokens
18
-
19
- ```tsx
20
- import { useGetBridgeableTokens } from '@sodax/dapp-kit';
21
- import { ChainKeys } from '@sodax/sdk';
22
-
23
- function BridgeableTokensList() {
24
- // `data` is `XToken[] | undefined` — the hook throws on SDK `!ok` so we get the unwrapped value.
25
- const { data: tokens } = useGetBridgeableTokens({
26
- params: { from: ChainKeys.BASE_MAINNET, to: ChainKeys.POLYGON_MAINNET, token: '0x0000000000000000000000000000000000000000' },
27
- });
28
-
29
- if (tokens) {
30
- return <ul>{tokens.map((t) => <li key={t.address}>{t.symbol}</li>)}</ul>;
31
- }
32
- return null;
33
- }
34
- ```
35
-
36
- ## Check Allowance + Approve
37
-
38
- ```tsx
39
- import { useBridgeAllowance, useBridgeApprove } from '@sodax/dapp-kit';
40
- import { useWalletProvider } from '@sodax/wallet-sdk-react';
41
- import { ChainKeys } from '@sodax/sdk';
42
- import type { CreateBridgeIntentParams } from '@sodax/sdk';
43
-
44
- function BridgeApproval({ params }: { params: CreateBridgeIntentParams }) {
45
- const walletProvider = useWalletProvider({ xChainId: ChainKeys.BASE_MAINNET });
46
- // useBridgeAllowance wraps payload + walletProvider under params (not at top level).
47
- const { data: isApproved } = useBridgeAllowance({
48
- params: { payload: params, walletProvider },
49
- });
50
- const { mutateAsync: approve, isPending } = useBridgeApprove();
51
-
52
- if (isApproved) return null;
53
- return (
54
- <button onClick={() => walletProvider && approve({ params, walletProvider })} disabled={isPending}>
55
- {isPending ? 'Approving...' : 'Approve for Bridge'}
56
- </button>
57
- );
58
- }
59
- ```
60
-
61
- ## Execute Bridge
62
-
63
- ```tsx
64
- import { useBridge } from '@sodax/dapp-kit';
65
- import { useWalletProvider } from '@sodax/wallet-sdk-react';
66
- import { ChainKeys } from '@sodax/sdk';
67
-
68
- function BridgeButton({ srcAddress }: { srcAddress: `0x${string}` }) {
69
- const walletProvider = useWalletProvider({ xChainId: ChainKeys.BASE_MAINNET });
70
- const { mutateAsync: bridge, isPending } = useBridge();
71
-
72
- const handleBridge = async () => {
73
- if (!walletProvider) return;
74
- try {
75
- const { srcChainTxHash, dstChainTxHash } = await bridge({
76
- params: {
77
- srcChainKey: ChainKeys.BASE_MAINNET,
78
- srcAddress,
79
- srcToken: '0x0000000000000000000000000000000000000000',
80
- amount: 1000000000000000000n,
81
- dstChainKey: ChainKeys.POLYGON_MAINNET,
82
- dstToken: '0x0000000000000000000000000000000000000000',
83
- recipient: '0x0000000000000000000000000000000000000000',
84
- },
85
- walletProvider,
86
- });
87
- console.log('Bridge successful:', { srcChainTxHash, dstChainTxHash });
88
- } catch (e) {
89
- console.error(e);
90
- }
91
- };
92
-
93
- return (
94
- <button onClick={handleBridge} disabled={isPending}>
95
- {isPending ? 'Bridging...' : 'Bridge'}
96
- </button>
97
- );
98
- }
99
- ```
100
-
101
- ## Full Example
102
-
103
- ```tsx
104
- import { useState } from 'react';
105
- import { useBridge, useBridgeAllowance, useBridgeApprove, useGetBridgeableAmount } from '@sodax/dapp-kit';
106
- import { useWalletProvider } from '@sodax/wallet-sdk-react';
107
- import { ChainKeys, type XToken } from '@sodax/sdk';
108
- import type { CreateBridgeIntentParams } from '@sodax/sdk';
109
- import { parseUnits, formatUnits } from 'viem';
110
-
111
- export function BridgePage({ srcXToken, dstXToken, srcAddress }: { srcXToken: XToken; dstXToken: XToken; srcAddress: `0x${string}` }) {
112
- const [amount, setAmount] = useState('');
113
- const walletProvider = useWalletProvider({ xChainId: ChainKeys.BASE_MAINNET });
114
- const parsedAmount = amount ? parseUnits(amount, 6) : 0n;
115
-
116
- const bridgeParams: CreateBridgeIntentParams<typeof ChainKeys.BASE_MAINNET> | undefined = parsedAmount > 0n
117
- ? {
118
- srcChainKey: ChainKeys.BASE_MAINNET,
119
- srcAddress,
120
- srcToken: srcXToken.address,
121
- amount: parsedAmount,
122
- dstChainKey: ChainKeys.POLYGON_MAINNET,
123
- dstToken: dstXToken.address,
124
- recipient: '0x0000000000000000000000000000000000000000',
125
- }
126
- : undefined;
127
-
128
- // useGetBridgeableAmount in v2 takes a pair of XToken objects (each carries chainKey).
129
- // `data` is `BridgeLimit | undefined` (already unwrapped; hook throws on SDK !ok).
130
- const { data: bridgeableAmount } = useGetBridgeableAmount({
131
- params: { from: srcXToken, to: dstXToken },
132
- });
133
- const { data: isApproved } = useBridgeAllowance({
134
- params: bridgeParams ? { payload: bridgeParams, walletProvider } : undefined,
135
- });
136
- const { mutateAsyncSafe: approve, isPending: isApproving } = useBridgeApprove();
137
- const { mutateAsyncSafe: bridge, isPending: isBridging } = useBridge();
138
-
139
- const handleBridge = async () => {
140
- if (!bridgeParams || !walletProvider) return;
141
- if (!isApproved) {
142
- const r = await approve({ params: bridgeParams, walletProvider });
143
- if (!r.ok) { alert(r.error instanceof Error ? r.error.message : 'Approve failed'); return; }
144
- }
145
- const r = await bridge({ params: bridgeParams, walletProvider });
146
- if (r.ok) alert(`Bridge complete! src=${r.value.srcChainTxHash}`);
147
- else alert(r.error instanceof Error ? r.error.message : 'Bridge failed');
148
- };
149
-
150
- return (
151
- <div>
152
- <input placeholder="Amount" value={amount} onChange={(e) => setAmount(e.target.value)} />
153
- {bridgeableAmount && <p>Max: {formatUnits(bridgeableAmount.amount, bridgeableAmount.decimals)}</p>}
154
- <button onClick={handleBridge} disabled={isBridging || isApproving || !bridgeParams || !walletProvider}>
155
- {isApproving ? 'Approving...' : isBridging ? 'Bridging...' : 'Bridge'}
156
- </button>
157
- </div>
158
- );
159
- }
160
- ```
161
-
162
- ## Types
163
-
164
- ```typescript
165
- type CreateBridgeIntentParams<K extends SpokeChainKey = SpokeChainKey> = {
166
- srcChainKey: K;
167
- srcAddress: string;
168
- srcToken: string;
169
- amount: bigint;
170
- dstChainKey: SpokeChainKey;
171
- dstToken: string;
172
- recipient: string; // non-encoded recipient address on the destination chain
173
- };
174
- ```
@@ -1,204 +0,0 @@
1
- # Recipe: DEX
2
-
3
- Concentrated liquidity positions and asset management.
4
-
5
- **Depends on:** [setup.md](setup.md), [wallet-connectivity.md](wallet-connectivity.md)
6
-
7
- ## Hooks
8
-
9
- ### Assets
10
-
11
- | Hook | Type | Purpose |
12
- |------|------|---------|
13
- | `useDexDeposit` | Mutation | Deposit assets into pool tokens |
14
- | `useDexWithdraw` | Mutation | Withdraw assets from pool tokens |
15
- | `useDexAllowance` | Query | Check approval for deposit |
16
- | `useDexApprove` | Mutation | Approve tokens |
17
- | `usePoolBalances` | Query | User's pool token balances |
18
-
19
- ### Liquidity
20
-
21
- | Hook | Type | Purpose |
22
- |------|------|---------|
23
- | `useSupplyLiquidity` | Mutation | Supply liquidity to a position |
24
- | `useDecreaseLiquidity` | Mutation | Remove liquidity |
25
- | `useClaimRewards` | Mutation | Claim trading fees |
26
- | `usePools` | Query | List available pools |
27
- | `usePoolData` | Query | Pool details (price, tick, liquidity) |
28
- | `usePositionInfo` | Query | Position details |
29
- | `useLiquidityAmounts` | Query | Token amounts for a tick range |
30
-
31
- ### Param Builders
32
-
33
- | Hook | Purpose |
34
- |------|---------|
35
- | `useCreateDepositParams` | Build deposit params with ERC-4626 conversion |
36
- | `useCreateWithdrawParams` | Build withdraw params |
37
- | `useCreateSupplyLiquidityParams` | Build tick range + liquidity params |
38
- | `useCreateDecreaseLiquidityParams` | Build decrease params from position state |
39
-
40
- ## List Pools
41
-
42
- ```tsx
43
- import { usePools } from '@sodax/dapp-kit';
44
-
45
- function PoolsList() {
46
- // `usePools` returns `PoolKey[]` — pool keys carry `currency0`, `currency1`, `fee`,
47
- // `hooks`, `poolManager`, and `parameters`. Resolve token symbols via your own
48
- // token-list lookup (e.g. config-derived).
49
- const { data: pools } = usePools({});
50
- return (
51
- <div>
52
- {pools?.map((pool, i) => (
53
- <div key={`${pool.currency0}-${pool.currency1}-${pool.fee}-${i}`}>
54
- <h3>{pool.currency0} / {pool.currency1}</h3>
55
- <p>Fee: {pool.fee / 10000}%</p>
56
- </div>
57
- ))}
58
- </div>
59
- );
60
- }
61
- ```
62
-
63
- ## Deposit Assets
64
-
65
- ```tsx
66
- import { useDexDeposit, useDexAllowance, useDexApprove } from '@sodax/dapp-kit';
67
- import { useWalletProvider } from '@sodax/wallet-sdk-react';
68
- import { ChainKeys, type CreateAssetDepositParams } from '@sodax/sdk';
69
-
70
- function DepositToPool({ srcAddress }: { srcAddress: `0x${string}` }) {
71
- const walletProvider = useWalletProvider({ xChainId: ChainKeys.BASE_MAINNET });
72
- const depositParams: CreateAssetDepositParams<typeof ChainKeys.BASE_MAINNET> = {
73
- srcChainKey: ChainKeys.BASE_MAINNET,
74
- srcAddress,
75
- asset: '0x0000000000000000000000000000000000000000',
76
- amount: 1_000_000_000_000_000_000n,
77
- poolToken: '0x0000000000000000000000000000000000000000',
78
- };
79
-
80
- // useDexAllowance wraps CreateAssetDepositParams under params.payload. Read-only;
81
- // no walletProvider needed (the SDK call uses `raw: true`).
82
- const { data: isApproved } = useDexAllowance({
83
- params: { payload: depositParams },
84
- });
85
- const { mutateAsync: approve, isPending: isApproving } = useDexApprove();
86
- const { mutateAsync: deposit, isPending: isDepositing } = useDexDeposit();
87
-
88
- const handleDeposit = async () => {
89
- if (!walletProvider) return;
90
- try {
91
- if (!isApproved) await approve({ params: depositParams, walletProvider });
92
- const txHashPair = await deposit({ params: depositParams, walletProvider });
93
- console.log('Deposited:', txHashPair);
94
- } catch (e) {
95
- console.error(e);
96
- }
97
- };
98
-
99
- return (
100
- <button onClick={handleDeposit} disabled={isDepositing || isApproving || !walletProvider}>
101
- {isApproving ? 'Approving...' : isDepositing ? 'Depositing...' : 'Deposit'}
102
- </button>
103
- );
104
- }
105
- ```
106
-
107
- ## Supply Liquidity
108
-
109
- ```tsx
110
- // @ai-snippets-skip — illustrative flow only; `useCreateSupplyLiquidityParams` takes
111
- // a flat shape `{ poolData, poolKey, minPrice, maxPrice, liquidityToken0Amount,
112
- // liquidityToken1Amount, slippageTolerance }` and the consumer must add
113
- // `srcChainKey` + `srcAddress` at the mutation call site. Real consumers should
114
- // reference `useCreateSupplyLiquidityParams` source for the full param set.
115
- import { useSupplyLiquidity, useCreateSupplyLiquidityParams } from '@sodax/dapp-kit';
116
- import { useWalletProvider } from '@sodax/wallet-sdk-react';
117
- import { ChainKeys } from '@sodax/sdk';
118
-
119
- function SupplyLiquidity() {
120
- const walletProvider = useWalletProvider({ xChainId: ChainKeys.BASE_MAINNET });
121
- const supplyParams = useCreateSupplyLiquidityParams({
122
- params: {
123
- poolKey: { /* ... */ },
124
- tickLower: -60000n,
125
- tickUpper: 60000n,
126
- amount0: 1_000_000_000_000_000_000n,
127
- amount1: 1_000_000_000_000_000_000n,
128
- },
129
- });
130
- const { mutateAsync: supplyLiquidity, isPending } = useSupplyLiquidity();
131
-
132
- return (
133
- <button
134
- disabled={isPending || !supplyParams || !walletProvider}
135
- onClick={async () => {
136
- if (!supplyParams || !walletProvider) return;
137
- try {
138
- const txHashPair = await supplyLiquidity({ params: supplyParams, walletProvider });
139
- console.log('Supplied:', txHashPair);
140
- } catch (e) {
141
- console.error(e);
142
- }
143
- }}
144
- >
145
- {isPending ? 'Supplying...' : 'Supply Liquidity'}
146
- </button>
147
- );
148
- }
149
- ```
150
-
151
- ## Position + Claim Rewards
152
-
153
- ```tsx
154
- // @ai-snippets-skip — illustrative flow only. Real call-shape notes:
155
- // - `usePositionInfo` params.tokenId is `string | null`, not bigint
156
- // - `usePositionInfo` data is `{ positionInfo: ClPositionInfo, isValid: boolean }` —
157
- // access `position.positionInfo.liquidity` etc.
158
- // - `useClaimRewards` params shape: `{ srcChainKey, srcAddress, poolKey, tokenId,
159
- // tickLower, tickUpper }` — far richer than shown.
160
- // See `features/dex.md` for the canonical param types.
161
- import { usePositionInfo, useClaimRewards } from '@sodax/dapp-kit';
162
- import { useWalletProvider } from '@sodax/wallet-sdk-react';
163
- import { ChainKeys } from '@sodax/sdk';
164
- import type { PoolKey } from '@sodax/sdk';
165
-
166
- function Position({ positionId, poolKey }: { positionId: bigint; poolKey: PoolKey }) {
167
- const walletProvider = useWalletProvider({ xChainId: ChainKeys.BASE_MAINNET });
168
- const { data: position } = usePositionInfo({ params: { tokenId: positionId, poolKey } });
169
- const { mutateAsync: claimRewards, isPending } = useClaimRewards();
170
-
171
- if (!position) return null;
172
- return (
173
- <div>
174
- <p>Liquidity: {position.liquidity.toString()}</p>
175
- <p>Range: [{position.tickLower}, {position.tickUpper}]</p>
176
- <button
177
- onClick={() => walletProvider && claimRewards({ params: { srcChainKey: ChainKeys.BASE_MAINNET, positionId }, walletProvider })}
178
- disabled={isPending || !walletProvider}
179
- >
180
- Claim Fees
181
- </button>
182
- </div>
183
- );
184
- }
185
- ```
186
-
187
- ## Remove Liquidity
188
-
189
- ```tsx
190
- // @ai-snippets-skip
191
- const walletProvider = useWalletProvider({ xChainId: ChainKeys.BASE_MAINNET });
192
- const { mutateAsync: decreaseLiquidity } = useDecreaseLiquidity();
193
-
194
- await decreaseLiquidity({
195
- params: { srcChainKey: ChainKeys.BASE_MAINNET, positionId, liquidity: 500_000n, amount0Min: 0n, amount1Min: 0n },
196
- walletProvider,
197
- });
198
- ```
199
-
200
- ## Notes
201
-
202
- - **Two-step flow**: deposit assets (spoke → hub pool tokens) then supply liquidity (pool tokens → position).
203
- - **Ticks**: logarithmic price units (like Uniswap V3). Wider range = more trades, less capital efficiency.
204
- - **ERC-4626**: pool tokens are vault shares. Use `useCreateDepositParams` to handle the conversion.
@@ -1,115 +0,0 @@
1
- # Recipe: Invalidations — hook-owned, composable
2
-
3
- Every dapp-kit mutation hook owns its own query invalidations. After a successful mutation, the hook's `onSuccess` fires invalidation calls against the relevant query keys; **then** your consumer-provided `onSuccess` runs.
4
-
5
- ## Default — invalidations just work
6
-
7
- ```tsx
8
- import { useSwap } from '@sodax/dapp-kit';
9
- import type { CreateIntentParams, IEvmWalletProvider } from '@sodax/sdk';
10
-
11
- function SwapButton({ params, walletProvider }: { params: CreateIntentParams; walletProvider: IEvmWalletProvider }) {
12
- const { mutateAsync: swap } = useSwap();
13
-
14
- const handleClick = async () => {
15
- // After this resolves successfully, dapp-kit invalidates `xBalances`
16
- // for the source and destination chains automatically.
17
- await swap({ params, walletProvider });
18
- };
19
-
20
- return <button onClick={handleClick}>Swap</button>;
21
- }
22
- ```
23
-
24
- You don't need to call `queryClient.invalidateQueries` yourself. Each mutation hook knows what queries it can invalidate (e.g. `useSwap` invalidates `xBalances` for `srcChainKey` and `dstChainKey` from the variables).
25
-
26
- ## Composing your own `onSuccess`
27
-
28
- Pass `mutationOptions.onSuccess` to run logic AFTER dapp-kit's invalidations:
29
-
30
- ```tsx
31
- import { useSwap } from '@sodax/dapp-kit';
32
-
33
- const { mutateAsync: swap } = useSwap({
34
- mutationOptions: {
35
- onSuccess: (data, vars) => {
36
- // Runs AFTER dapp-kit's xBalances invalidations.
37
- // `data` is the unwrapped success value (SwapResponse).
38
- trackSwap(data);
39
- console.log('swap_complete', { from: vars.params.srcChainKey });
40
- },
41
- },
42
- });
43
- console.log(swap);
44
- ```
45
-
46
- The order is fixed:
47
-
48
- 1. `mutationFn` resolves successfully (SDK returned `{ ok: true }`).
49
- 2. dapp-kit's hook-internal `onSuccess` runs the invalidations.
50
- 3. Your `mutationOptions.onSuccess` runs.
51
- 4. Per-call `mutate(vars, { onSuccess })` runs (if provided).
52
-
53
- Failed mutations never trigger any of steps 2–4 — invalidations are correctness logic, not "always run."
54
-
55
- ## What gets invalidated, by feature
56
-
57
- Each feature mutation hook invalidates the related read keys. Common patterns:
58
-
59
- | Mutation | Invalidates |
60
- |---|---|
61
- | `useSwap` | `['shared', 'xBalances', srcChainKey]`, `['shared', 'xBalances', dstChainKey]` |
62
- | `useBridge` | Same as `useSwap` (xBalances on both chains). |
63
- | `useSupply`, `useWithdraw`, `useBorrow`, `useRepay` | `['mm', 'userReservesData']`, `['shared', 'xBalances', srcChainKey]`, plus reserves data on the affected token. |
64
- | `useStake`, `useUnstake`, `useClaim`, `useCancelUnstake`, `useInstantUnstake` | `['staking', 'info']`, `['staking', 'unstakingInfo']`, `['shared', 'xBalances', srcChainKey]`. |
65
- | `useDexDeposit`, `useDexWithdraw` | `['dex', 'poolBalances']`, `['shared', 'xBalances', srcChainKey]`. |
66
- | `useSupplyLiquidity`, `useDecreaseLiquidity`, `useClaimRewards` | `['dex', 'positionInfo', tokenId]`, `['dex', 'poolBalances']`. |
67
- | `useMigrateIcxToSoda`, etc. | `['shared', 'xBalances']` for source + destination chains. |
68
- | Approve hooks (`useSwapApprove`, etc.) | The corresponding allowance read (`['swap', 'allowance']`, etc.). |
69
-
70
- The exact keys are derived from `vars` at success time — so a successful supply on Base only invalidates Base-side reserves, not Arbitrum's.
71
-
72
- ## Adding cross-feature invalidations
73
-
74
- If you operate across multiple features (e.g. you have a custom hook that does `swap → migrate`), invalidate the cross-feature keys yourself in the consumer `onSuccess`:
75
-
76
- ```tsx
77
- import { useQueryClient } from '@tanstack/react-query';
78
- import { useSwap } from '@sodax/dapp-kit';
79
-
80
- const qc = useQueryClient();
81
- const { mutateAsync: swap } = useSwap({
82
- mutationOptions: {
83
- onSuccess: async (data, vars) => {
84
- // dapp-kit invalidates xBalances. We additionally want to refresh a
85
- // custom analytics view that tracks completed swap volume.
86
- await qc.invalidateQueries({ queryKey: ['my-app', 'swap-volume'] });
87
- },
88
- },
89
- });
90
- ```
91
-
92
- ## Per-call invalidation
93
-
94
- For one-off invalidations (only on this specific click), pass `onSuccess` to `mutate`:
95
-
96
- ```tsx
97
- // @ai-snippets-skip
98
- await swap.mutateAsync(
99
- { params, walletProvider },
100
- { onSuccess: () => navigate(`/swap/${data.intent.intentHash}`) }
101
- );
102
- ```
103
-
104
- The order is unchanged: hook invalidations → consumer `onSuccess` → per-call `onSuccess`.
105
-
106
- ## v1 → v2
107
-
108
- In v1 dapp-kit, consumers managed invalidations themselves — most apps had a `lib/invalidate*Queries.ts` utility that fired `queryClient.invalidateQueries(...)` after each mutation. Those utilities are no longer needed in v2; delete them.
109
-
110
- If you're migrating v1 code, see [`../../migration/breaking-changes/hook-signatures.md`](../../migration/breaking-changes/hook-signatures.md) for the full delta.
111
-
112
- ## Cross-references
113
-
114
- - [`mutation-error-handling.md`](mutation-error-handling.md) — picking call shapes.
115
- - [`../architecture.md`](../architecture.md) — `_mutationContract.test.ts` enforces the canonical `onSuccess` composition pattern.