@sodax/wallet-sdk-react 2.0.0-rc.3 → 2.0.0-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +12 -5
  2. package/dist/{chunk-BKJB527E.mjs → chunk-3QETHO6P.mjs} +1 -3
  3. package/dist/{chunk-PJLEJVAU.mjs → chunk-42LTUHMZ.mjs} +1 -3
  4. package/dist/{chunk-NY7U7OJW.mjs → chunk-7V7O3Q7Y.mjs} +0 -2
  5. package/dist/{chunk-BXJLBR4G.mjs → chunk-C6M34IVL.mjs} +2 -4
  6. package/dist/{chunk-XZ7CHO2S.mjs → chunk-FSOGMSJH.mjs} +2 -4
  7. package/dist/{chunk-X2MHIWXO.mjs → chunk-IFXZQW4C.mjs} +0 -2
  8. package/dist/{chunk-7ULB6DW4.mjs → chunk-JQ4H4GJ5.mjs} +3 -5
  9. package/dist/{chunk-N5A2TMF6.mjs → chunk-LKSSME2J.mjs} +2 -4
  10. package/dist/{chunk-PLCA4ZDJ.mjs → chunk-LUKR7YKV.mjs} +54 -30
  11. package/dist/{chunk-MXZVF5HR.mjs → chunk-NAKCAL2M.mjs} +0 -2
  12. package/dist/chunk-QMXBY3UI.mjs +1 -0
  13. package/dist/{chunk-MAQ47Q52.mjs → chunk-TACW7Z4D.mjs} +0 -2
  14. package/dist/{chunk-2BOUGCJ7.mjs → chunk-WPZOLGVB.mjs} +4 -6
  15. package/dist/{chunk-66BAUK56.mjs → chunk-X7BHR7WS.mjs} +2 -4
  16. package/dist/{chunk-E5IAZ7E6.mjs → chunk-Z5GXDHGL.mjs} +9 -5
  17. package/dist/{config-OlnzyEUE.d.ts → config-GVKK8IfY.d.ts} +6 -1
  18. package/dist/index.d.ts +4 -4
  19. package/dist/index.mjs +20 -31
  20. package/dist/xchains/bitcoin/index.mjs +14 -16
  21. package/dist/xchains/evm/index.d.ts +1 -1
  22. package/dist/xchains/evm/index.mjs +3 -5
  23. package/dist/xchains/icon/index.mjs +5 -7
  24. package/dist/xchains/injective/index.mjs +3 -5
  25. package/dist/xchains/near/index.mjs +4 -6
  26. package/dist/xchains/solana/index.mjs +5 -7
  27. package/dist/xchains/stacks/index.mjs +3 -5
  28. package/dist/xchains/stellar/index.mjs +4 -6
  29. package/dist/xchains/sui/index.mjs +5 -7
  30. package/docs/ADDING_A_NEW_CHAIN.md +1 -1
  31. package/docs/SUB_PATH_EXPORTS.md +14 -42
  32. package/package.json +32 -24
  33. package/ai-exported/AGENTS.md +0 -122
  34. package/ai-exported/integration/README.md +0 -102
  35. package/ai-exported/integration/ai-rules.md +0 -136
  36. package/ai-exported/integration/architecture.md +0 -181
  37. package/ai-exported/integration/examples/01-minimal-evm.tsx +0 -75
  38. package/ai-exported/integration/examples/02-multi-chain-modal.tsx +0 -169
  39. package/ai-exported/integration/examples/03-nextjs-app-router.tsx +0 -99
  40. package/ai-exported/integration/examples/04-walletconnect-setup.tsx +0 -89
  41. package/ai-exported/integration/examples/README.md +0 -29
  42. package/ai-exported/integration/recipes/batch-operations.md +0 -223
  43. package/ai-exported/integration/recipes/bridge-to-sdk.md +0 -164
  44. package/ai-exported/integration/recipes/chain-detection.md +0 -254
  45. package/ai-exported/integration/recipes/connect-button.md +0 -156
  46. package/ai-exported/integration/recipes/multi-chain-modal.md +0 -199
  47. package/ai-exported/integration/recipes/setup.md +0 -160
  48. package/ai-exported/integration/recipes/sign-message.md +0 -137
  49. package/ai-exported/integration/recipes/sub-path-imports.md +0 -95
  50. package/ai-exported/integration/recipes/switch-chain.md +0 -141
  51. package/ai-exported/integration/recipes/walletconnect-setup.md +0 -139
  52. package/ai-exported/integration/reference/api-surface.md +0 -175
  53. package/ai-exported/integration/reference/chain-support.md +0 -78
  54. package/ai-exported/integration/reference/connectors.md +0 -74
  55. package/ai-exported/integration/reference/hooks.md +0 -204
  56. package/ai-exported/integration/reference/wallet-brands.md +0 -106
  57. package/ai-exported/migration/README.md +0 -49
  58. package/ai-exported/migration/ai-rules.md +0 -144
  59. package/ai-exported/migration/breaking-changes.md +0 -305
  60. package/ai-exported/migration/checklist.md +0 -159
  61. package/ai-exported/migration/recipes/connect-button.md +0 -166
  62. package/ai-exported/migration/recipes/multi-chain-modal.md +0 -244
  63. package/ai-exported/migration/recipes/ssr-setup.md +0 -164
  64. package/ai-exported/migration/recipes/walletconnect-migration.md +0 -168
  65. package/ai-exported/migration/reference/components.md +0 -73
  66. package/ai-exported/migration/reference/config.md +0 -325
  67. package/ai-exported/migration/reference/hooks.md +0 -323
  68. package/ai-exported/migration/reference/imports.md +0 -157
  69. package/dist/chunk-2BOUGCJ7.mjs.map +0 -1
  70. package/dist/chunk-66BAUK56.mjs.map +0 -1
  71. package/dist/chunk-7ULB6DW4.mjs.map +0 -1
  72. package/dist/chunk-BKJB527E.mjs.map +0 -1
  73. package/dist/chunk-BXJLBR4G.mjs.map +0 -1
  74. package/dist/chunk-E5IAZ7E6.mjs.map +0 -1
  75. package/dist/chunk-MAQ47Q52.mjs.map +0 -1
  76. package/dist/chunk-MXZVF5HR.mjs.map +0 -1
  77. package/dist/chunk-N5A2TMF6.mjs.map +0 -1
  78. package/dist/chunk-NY7U7OJW.mjs.map +0 -1
  79. package/dist/chunk-PJLEJVAU.mjs.map +0 -1
  80. package/dist/chunk-PLCA4ZDJ.mjs.map +0 -1
  81. package/dist/chunk-TZMKDXFA.mjs +0 -3
  82. package/dist/chunk-TZMKDXFA.mjs.map +0 -1
  83. package/dist/chunk-X2MHIWXO.mjs.map +0 -1
  84. package/dist/chunk-XZ7CHO2S.mjs.map +0 -1
  85. package/dist/index.cjs +0 -3337
  86. package/dist/index.cjs.map +0 -1
  87. package/dist/index.mjs.map +0 -1
  88. package/dist/xchains/bitcoin/index.cjs +0 -1927
  89. package/dist/xchains/bitcoin/index.cjs.map +0 -1
  90. package/dist/xchains/bitcoin/index.mjs.map +0 -1
  91. package/dist/xchains/evm/index.cjs +0 -316
  92. package/dist/xchains/evm/index.cjs.map +0 -1
  93. package/dist/xchains/evm/index.mjs.map +0 -1
  94. package/dist/xchains/icon/index.cjs +0 -311
  95. package/dist/xchains/icon/index.cjs.map +0 -1
  96. package/dist/xchains/icon/index.mjs.map +0 -1
  97. package/dist/xchains/injective/index.cjs +0 -223
  98. package/dist/xchains/injective/index.cjs.map +0 -1
  99. package/dist/xchains/injective/index.mjs.map +0 -1
  100. package/dist/xchains/near/index.cjs +0 -190
  101. package/dist/xchains/near/index.cjs.map +0 -1
  102. package/dist/xchains/near/index.mjs.map +0 -1
  103. package/dist/xchains/solana/index.cjs +0 -186
  104. package/dist/xchains/solana/index.cjs.map +0 -1
  105. package/dist/xchains/solana/index.mjs.map +0 -1
  106. package/dist/xchains/stacks/index.cjs +0 -240
  107. package/dist/xchains/stacks/index.cjs.map +0 -1
  108. package/dist/xchains/stacks/index.mjs.map +0 -1
  109. package/dist/xchains/stellar/index.cjs +0 -322
  110. package/dist/xchains/stellar/index.cjs.map +0 -1
  111. package/dist/xchains/stellar/index.mjs.map +0 -1
  112. package/dist/xchains/sui/index.cjs +0 -248
  113. package/dist/xchains/sui/index.cjs.map +0 -1
  114. package/dist/xchains/sui/index.mjs.map +0 -1
  115. package/skills/SKILLS.md +0 -84
  116. package/skills/bridge-to-sdk.md +0 -148
  117. package/skills/connect-button.md +0 -116
  118. package/skills/evm-only-walletconnect.md +0 -111
  119. package/skills/multi-chain-modal.md +0 -178
  120. package/skills/setup.md +0 -107
@@ -1,305 +0,0 @@
1
- # Breaking Changes: v1 → v2
2
-
3
- This is the **single source of truth** for behavior and API changes between v1 and v2 of `@sodax/wallet-sdk-react`. The reference files (`imports.md`, `hooks.md`, `config.md`, `components.md`) are **lookup tables** derived from the changes here — they do not duplicate the prose.
4
-
5
- ## Table of contents
6
-
7
- 1. [`SodaxWalletProvider` props (largest change)](#1-sodaxwalletprovider-props-largest-change)
8
- 2. [`QueryClientProvider` is no longer mounted internally](#2-queryclientprovider-is-no-longer-mounted-internally)
9
- 3. [Hooks now take an options object, not positional args](#3-hooks-now-take-an-options-object-not-positional-args)
10
- 4. [Store hook removed from the public API](#4-store-hook-removed-from-the-public-api)
11
- 5. [Concrete chain classes moved behind sub-path imports](#5-concrete-chain-classes-moved-behind-sub-path-imports)
12
- 6. [Chain-type opt-in (mounting behavior)](#6-chain-type-opt-in-mounting-behavior)
13
- 7. [EVM = single connection across every configured EVM network](#7-evm--single-connection-across-every-configured-evm-network)
14
- 8. [New: WalletConnect support for EVM](#8-new-walletconnect-support-for-evm)
15
- 9. [New: headless wallet modal primitives](#9-new-headless-wallet-modal-primitives)
16
- 10. [Removed: `useXBalances`](#10-removed-usexbalances)
17
- 11. [`useEvmSwitchChain` reshaped](#11-useevmswitchchain-reshaped)
18
- 12. [`SodaxWalletProvider` freezes config on first render](#12-sodaxwalletprovider-freezes-config-on-first-render)
19
-
20
- What did NOT change → [bottom of file](#what-did-not-change).
21
-
22
- ---
23
-
24
- ## 1. `SodaxWalletProvider` props (largest change)
25
-
26
- ### What changed
27
-
28
- v1 spread chain configuration across **three separate props**: `rpcConfig` (per-chain RPC URLs), `options` (per-adapter options like `wagmi.ssr`, `solana.autoConnect`, `sui.autoConnect`), and `initialState` (wagmi state for SSR hydration).
29
-
30
- v2 collapses all three into a **single `config` prop** of type `SodaxWalletConfig`. The new shape uses **chain-type slots** (`EVM`, `SOLANA`, `SUI`, `BITCOIN`, `STELLAR`, `ICON`, `INJECTIVE`, `NEAR`, `STACKS`) at the top level. Each slot is `ChainTypeConfig<T>` — adapter options merged with `{ chains?, connectors? }` where `chains` is keyed by `ChainKey` and holds per-chain `{ rpcUrl?, defaults? }`.
31
-
32
- ### Why
33
-
34
- - **Configurable chain opt-in.** v1 always mounted every chain adapter regardless of need. v2 mounts only the slots you include — omit a slot to skip it entirely. Pass `{}` to mount with SDK defaults.
35
- - **Single source of truth.** v1 spread chain knowledge across three independent props that had to stay in sync; the new `config` shape derives `enabledChains`, `chains`, and per-chain defaults from one tree.
36
- - **Per-chain `defaults`.** v2 lets each chain entry hold call-level defaults (e.g. EVM `waitForTransactionReceipt.confirmations`) that flow to the bridged `IXxxWalletProvider`.
37
-
38
- ### How to migrate
39
-
40
- See [`reference/config.md`](./reference/config.md) for the mechanical mapping. See [`recipes/`](./recipes/) for paired before/after code in common patterns.
41
-
42
- ---
43
-
44
- ## 2. `QueryClientProvider` is no longer mounted internally
45
-
46
- ### What changed
47
-
48
- v1 created its own `QueryClient` inside `SodaxWalletProvider` and wrapped children with `<QueryClientProvider>` automatically. v2 expects the consumer to provide one, externally.
49
-
50
- ### Why
51
-
52
- - **One QueryClient per app, not per package.** v1's behavior caused subtle bugs when an app already had its own `QueryClient` for app-level queries — there were two clients, two caches, and React Query devtools showed only one.
53
- - **Predictable provider order.** Consumers can now mount `QueryClientProvider` at the position that fits their app — between auth providers and `SodaxWalletProvider`, around route boundaries, etc.
54
-
55
- ### How to migrate
56
-
57
- Wrap `<SodaxWalletProvider>` with `<QueryClientProvider>` at the call site:
58
-
59
- ```tsx
60
- // v2 ✅
61
- <QueryClientProvider client={queryClient}>
62
- <SodaxWalletProvider config={walletConfig}>{children}</SodaxWalletProvider>
63
- </QueryClientProvider>
64
- ```
65
-
66
- Add `@tanstack/react-query` as a direct dependency if not already present:
67
-
68
- ```bash
69
- pnpm add @tanstack/react-query
70
- ```
71
-
72
- ---
73
-
74
- ## 3. Hooks now take an options object, not positional args
75
-
76
- ### What changed
77
-
78
- Every public hook that took a `xChainType` or `chainIdentifier` positional argument now takes an options object with named fields. The same applies to the **callback returned by `useXDisconnect`** — `await disconnect('EVM')` is now `await disconnect({ xChainType: 'EVM' })`.
79
-
80
- ### Why
81
-
82
- - **Forward compatibility.** Adding new fields (e.g. `xChainId` alongside `xChainType`) without breaking call sites.
83
- - **Disambiguation.** v1 `useXAccount(chainIdentifier)` accepted both `ChainType` (`'EVM'`) and `ChainId` (`'0x1.eth'`) and detected at runtime. v2 splits them — `xChainType: ChainType` vs `xChainId: SpokeChainKey` — and the type system enforces "exactly one".
84
-
85
- ### How to migrate
86
-
87
- See [`reference/hooks.md`](./reference/hooks.md) for the per-hook signature map. The `useXDisconnect` returned-callback case typically surfaces as `TS2345: Argument of type 'string' is not assignable to parameter of type 'UseXDisconnectArgs'`.
88
-
89
- ---
90
-
91
- ## 4. Store hook removed from the public API
92
-
93
- ### What changed
94
-
95
- v1 exported the Zustand store hook as `useXWagmiStore` from the package barrel. v2 **does not export the store hook at all** — direct store access is no longer part of the public API. The localStorage **persistence key is unchanged** (`xwagmi-store`) so existing user connections survive the upgrade.
96
-
97
- ### Why
98
-
99
- - **Public surface should be the hook layer.** Reading store state directly couples consumers to internal field shapes that change between minor versions. v2 provides one public hook per consumer concern (`useXService`, `useXConnection`, `useXConnectors`, …) so internal store renames don't break consumers.
100
- - **localStorage compatibility.** Renaming the persistence key would log every user out on upgrade. The internal store rename (which v2 also did) keeps the localStorage key intact.
101
-
102
- ### How to migrate
103
-
104
- For each `useXWagmiStore(state => state.X)` selector, replace with the equivalent public hook. There is no `useXWalletStore` import to rename to. See [`reference/imports.md`](./reference/imports.md) § "Store hook removed" for the field-to-hook map.
105
-
106
- ---
107
-
108
- ## 5. Concrete chain classes moved behind sub-path imports
109
-
110
- ### What changed
111
-
112
- v1 re-exported every concrete `XService` and `XConnector` class from the package barrel:
113
-
114
- ```diff
115
- - // v1 — barrel exports concrete classes
116
- - import { EvmXService, XverseXConnector, IconHanaXConnector } from '@sodax/wallet-sdk-react';
117
- ```
118
-
119
- v2's barrel exports only **types, hooks, abstractions, and `SodaxWalletProvider`**. Concrete chain classes live behind sub-paths:
120
-
121
- ```ts
122
- // v2 — concrete classes via sub-path
123
- import { XverseXConnector } from '@sodax/wallet-sdk-react/xchains/bitcoin';
124
- ```
125
-
126
- ### Why
127
-
128
- - **API surface hygiene.** Consumers who only use hooks shouldn't pull concrete chain classes into their bundle just because they were re-exported. v2's barrel is shaped around the consumer-facing API; advanced use (e.g. `instanceof`) opts in via deep imports.
129
- - **Adding chains is non-breaking.** v1 required updating `index.ts` whenever a new chain landed. v2 auto-discovers per-chain entries via tsup glob — adding a chain doesn't touch the barrel.
130
-
131
- ### How to migrate
132
-
133
- See [`reference/imports.md`](./reference/imports.md) for the sub-path map per chain.
134
-
135
- ---
136
-
137
- ## 6. Chain-type opt-in (mounting behavior)
138
-
139
- ### What changed
140
-
141
- v1 mounted **every** chain adapter (wagmi, `@solana/wallet-adapter`, `@mysten/dapp-kit`) and registered services for every chain regardless of whether the consumer used them.
142
-
143
- v2 mounts only the slots present in `walletConfig`. An app that only needs EVM + Sui passes `{ EVM: {...}, SUI: {...} }` and ships **none** of the Solana / Bitcoin / NEAR adapter code in the React tree.
144
-
145
- ### Why
146
-
147
- - **Bundle size.** v1 forced every consumer to ship every adapter. v2 lets you opt in.
148
- - **Provider context isolation.** Apps that don't need Solana don't get the `WalletProvider` from `@solana/wallet-adapter` in their context — fewer renders, fewer dev-tool nodes.
149
-
150
- ### How to migrate
151
-
152
- Add only the chain-type slots your app actually uses to `walletConfig`. See [`reference/config.md`](./reference/config.md). New behavior: `useXConnectors({ xChainType: 'X' })` returns `[]` for chains not in `enabledChains` and logs a one-time warning.
153
-
154
- ---
155
-
156
- ## 7. EVM = single connection across every configured EVM network
157
-
158
- ### What changed
159
-
160
- v1 had one connector per chain in some flows (legacy from earlier wagmi versions). v2 treats EVM as **one logical connection** that spans every configured EVM chain — there is no per-network connect/disconnect, and `useChainGroups` collapses EVM into a single row.
161
-
162
- ### Why
163
-
164
- - **Match wagmi's actual semantics.** wagmi has always modeled EVM connection as one connector per session that hops between configured chains via `wagmi.switchChain`. v1's per-chain UI was a workaround.
165
- - **Multi-chain dApps.** Users connect once and operate across every EVM network the app supports — no re-authorization on each chain switch.
166
-
167
- ### How to migrate
168
-
169
- Audit any UI that exposed per-EVM-chain connect/disconnect. Replace with a single "EVM" entry. Use `useEvmSwitchChain` for switching. See [`recipes/connect-button.md`](./recipes/connect-button.md) and [`recipes/multi-chain-modal.md`](./recipes/multi-chain-modal.md).
170
-
171
- ---
172
-
173
- ## 8. New: WalletConnect support for EVM
174
-
175
- ### What changed
176
-
177
- v2 adds `EVM.walletConnect.projectId` to `walletConfig` to enable the WalletConnect connector. v1 did not support WalletConnect — only EIP-6963 injected wallets.
178
-
179
- ### Why
180
-
181
- - **Enterprise custody.** Partners using Fireblocks / Ledger Live / mobile-only wallets cannot install browser extensions. WalletConnect is the only viable protocol.
182
- - **Backwards compatible default.** Omitting `walletConnect` from the config preserves v1 behavior (EIP-6963 only).
183
-
184
- ### How to migrate
185
-
186
- Not breaking — additive. See [`recipes/walletconnect-migration.md`](./recipes/walletconnect-migration.md) for opt-in.
187
-
188
- ---
189
-
190
- ## 9. New: headless wallet modal primitives
191
-
192
- ### What changed
193
-
194
- v2 ships `useWalletModal`, `useChainGroups`, `useConnectedChains`, `useBatchConnect`, `useBatchDisconnect`, `useIsWalletInstalled`, `useConnectionFlow`. None of these existed in v1.
195
-
196
- ### Why
197
-
198
- - **Bring-your-own UI.** v1 left the modal UX to the consumer. v2 ships state-machine primitives — render-agnostic — so apps can build modal UX without rebuilding the chain registry / connector dispatch logic from scratch.
199
-
200
- ### How to migrate
201
-
202
- Not breaking — additive. See [`recipes/multi-chain-modal.md`](./recipes/multi-chain-modal.md) for the modern pattern.
203
-
204
- ---
205
-
206
- ## 10. Removed: `useXBalances`
207
-
208
- ### What changed
209
-
210
- v1 exported `useXBalances({ xChainId, xTokens, address })` from `@sodax/wallet-sdk-react`. v2 removes it. A hook with the same name lives in `@sodax/dapp-kit`, but the **signature has changed**:
211
-
212
- ```diff
213
- - // v1 ❌ — from wallet-sdk-react
214
- - import { useXBalances } from '@sodax/wallet-sdk-react';
215
- - const { data } = useXBalances({ xChainId, xTokens, address });
216
- + // v2 ✅ — from dapp-kit, params are now wrapped
217
- + import { useXBalances } from '@sodax/dapp-kit';
218
- + import { useXService } from '@sodax/wallet-sdk-react';
219
- + const xService = useXService({ xChainType: 'EVM' });
220
- + const { data } = useXBalances({ params: { xService, xChainId, xTokens, address } });
221
- ```
222
-
223
- ### Why
224
-
225
- - **Wrong package.** Token-balance queries are a dApp-feature concern, not a wallet-sdk concern. The hook required token metadata, RPC routing, and refetch policies — none of which belong in a wallet SDK.
226
- - **`xService` is now an explicit input.** v2 surfaces the chain service to the call site so query keys are stable across config changes and the hook is testable in isolation.
227
-
228
- ### How to migrate
229
-
230
- 1. `pnpm add @sodax/dapp-kit` if not already installed.
231
- 2. Switch the import path: `'@sodax/wallet-sdk-react'` → `'@sodax/dapp-kit'`.
232
- 3. Wrap the existing arg as `{ params: { xService, xChainId, xTokens, address } }` and pass `xService` from `useXService({ xChainType })`.
233
-
234
- If you cannot add dapp-kit, port the call to direct `viem` / `@solana/web3.js` reads with your own `useQuery`.
235
-
236
- ---
237
-
238
- ## 11. `useEvmSwitchChain` reshaped
239
-
240
- ### What changed
241
-
242
- v1 forwarded wagmi's `switchChain` mutation directly:
243
-
244
- ```ts
245
- // v1 ❌
246
- const { switchChain } = useEvmSwitchChain();
247
- await switchChain({ chainId: 1 });
248
- ```
249
-
250
- v2 takes a target `xChainId` and exposes wrong-network state:
251
-
252
- ```ts
253
- // v2 ✅
254
- import { ChainKeys } from '@sodax/types';
255
-
256
- const { isWrongChain, handleSwitchChain } = useEvmSwitchChain({
257
- xChainId: ChainKeys.ETHEREUM_MAINNET,
258
- });
259
- ```
260
-
261
- ### Why
262
-
263
- - **Single source of truth for "expected chain".** UI code repeatedly recomputed `connectedChainId !== expectedChainId`. The hook owns that comparison once.
264
- - **Injective + MetaMask.** v2 transparently handles the Injective-via-MetaMask case (auto-switches to Ethereum mainnet). v1 callers had to bolt this on.
265
- - **Safe when EVM is disabled.** If the consumer's `walletConfig` omits the `EVM` slot, v2 returns no-op values instead of throwing.
266
-
267
- ### How to migrate
268
-
269
- Replace the destructured `switchChain` with `handleSwitchChain` and feed the target chain via `xChainId`. Render the network-mismatch CTA from `isWrongChain`. See [`reference/hooks.md`](./reference/hooks.md) for examples.
270
-
271
- ---
272
-
273
- ## 12. `SodaxWalletProvider` freezes config on first render
274
-
275
- ### What changed
276
-
277
- v1 re-derived chain config on every render whose `rpcConfig` / `options` reference changed. v2 **captures `config` once on mount** and ignores subsequent prop changes. To swap config at runtime, remount with a new `key`.
278
-
279
- ### Why
280
-
281
- - **Stable wagmi config object.** wagmi's `WagmiProvider` is sensitive to config-object identity changes — re-creating the config triggers re-connection and breaks in-flight transactions.
282
- - **Predictable identity.** Apps should compose chain config once at startup, not derive it dynamically. Hot config swaps were rare in v1 but caused hard-to-debug reconnect storms.
283
-
284
- ### How to migrate
285
-
286
- If you previously updated `rpcConfig` reactively, route the change through a remount:
287
-
288
- ```tsx
289
- <SodaxWalletProvider key={configVersion} config={walletConfig}>
290
- {children}
291
- </SodaxWalletProvider>
292
- ```
293
-
294
- Bumping `configVersion` (e.g. when the user picks a new RPC endpoint) forces a clean re-init of all chain services.
295
-
296
- ---
297
-
298
- ## What did NOT change
299
-
300
- - Chain support: still 9 chain types (EVM, BITCOIN, INJECTIVE, STELLAR, SUI, SOLANA, ICON, NEAR, STACKS).
301
- - Persisted localStorage key: still `xwagmi-store`.
302
- - Devtools store name: still `xwagmi-store`.
303
- - Peer dependencies: `react >= 19`, `@tanstack/react-query 5.x`.
304
- - `XService` / `XConnector` abstract base contract (still has `connect()` / `disconnect()` / `getXConnectors()`).
305
- - Public `XAccount`, `XConnection`, `WalletId` types in `@sodax/types`.
@@ -1,159 +0,0 @@
1
- # Migration Checklist (Machine-Checkable)
2
-
3
- Run these checks after every code change and at the end of the migration. Each item has a concrete `grep` / typecheck command. Loop through until all are checked.
4
-
5
- ---
6
-
7
- ## Provider migration
8
-
9
- - [ ] `SodaxWalletProvider` is mounted exactly once in app source.
10
- ```bash
11
- grep -rn "SodaxWalletProvider" <user-src> --include="*.tsx" --include="*.ts" | grep -v "import" | wc -l
12
- # expect 1 (the JSX usage)
13
- ```
14
-
15
- - [ ] `SodaxWalletProvider` uses the v2 `config` prop (no `rpcConfig` / `options` / `initialState`).
16
- ```bash
17
- grep -rnE "SodaxWalletProvider[^/>]*\b(rpcConfig|initialState|options)\s*=" <user-src>
18
- # expect empty
19
- ```
20
-
21
- - [ ] `QueryClientProvider` wraps `SodaxWalletProvider`.
22
- ```bash
23
- # Manual — open the provider file and confirm:
24
- # <QueryClientProvider client={queryClient}>
25
- # <SodaxWalletProvider config={walletConfig}>
26
- ```
27
-
28
- - [ ] If app is Next.js, `EVM.ssr: true` is set in `walletConfig`.
29
- ```bash
30
- grep -rnE "EVM:\s*\{[^}]*\bssr:\s*true" <user-src>
31
- # expect at least one match if Next.js
32
- ```
33
-
34
- ---
35
-
36
- ## Store migration
37
-
38
- - [ ] No `useXWagmiStore` imports remain (the v2 barrel removed the store hook entirely — every call site must be replaced with a public hook).
39
- ```bash
40
- grep -rn "useXWagmiStore" <user-src>
41
- # expect empty
42
- ```
43
-
44
- - [ ] No `useXWalletStore` imports were introduced (v2 does not export the store hook under either name).
45
- ```bash
46
- grep -rn "useXWalletStore" <user-src>
47
- # expect empty
48
- ```
49
-
50
- - [ ] Every former store read uses a public hook (`useXService` / `useXServices` / `useXConnection` / `useXConnections` / `useEnabledChains` / `useWalletProvider`). See [`reference/imports.md`](./reference/imports.md) § "Store hook removed" for the field-to-hook map.
51
-
52
- ---
53
-
54
- ## Hook signature migration
55
-
56
- - [ ] No positional hook calls remain.
57
- ```bash
58
- # All of these must be empty:
59
- grep -rnE "useXAccount\(['\"]" <user-src>
60
- grep -rnE "useXConnectors\(['\"]" <user-src>
61
- grep -rnE "useXConnection\(['\"]" <user-src>
62
- grep -rnE "useXService\(['\"]" <user-src>
63
- grep -rnE "useWalletProvider\(['\"]" <user-src>
64
- ```
65
-
66
- - [ ] All call sites pass `{ xChainType }` or `{ xChainId }`, never both.
67
- ```bash
68
- grep -rnE "useXAccount\(\{[^}]*xChainType[^}]*xChainId" <user-src>
69
- grep -rnE "useXAccount\(\{[^}]*xChainId[^}]*xChainType" <user-src>
70
- # expect empty
71
- ```
72
-
73
- - [ ] No `useXDisconnect` callback called with positional ChainType (v2 takes `{ xChainType }` object).
74
- ```bash
75
- # The hook itself is identical in v1/v2; the BREAKING change is on the returned callback.
76
- # Look for callbacks invoked with a bare string instead of an options object.
77
- grep -rnE "disconnect\((['\"](EVM|SOLANA|SUI|BITCOIN|STELLAR|ICON|INJECTIVE|NEAR|STACKS)['\"])\)" <user-src>
78
- # expect empty — replace with `disconnect({ xChainType: 'EVM' })`
79
- ```
80
-
81
- - [ ] No `useEvmSwitchChain` destructuring of `switchChain` (v2 returns `{ isWrongChain, handleSwitchChain }`).
82
- ```bash
83
- grep -rnE "useEvmSwitchChain\(\)" <user-src>
84
- # expect empty — v2 requires `{ xChainId }`
85
- grep -rnE "const \{[^}]*\bswitchChain\b[^}]*\} = useEvmSwitchChain" <user-src>
86
- # expect empty — switchChain is no longer destructurable from this hook
87
- ```
88
-
89
- ---
90
-
91
- ## Sub-path imports
92
-
93
- - [ ] No concrete chain classes are imported from the package barrel.
94
- ```bash
95
- grep -rnE "from '@sodax/wallet-sdk-react'" <user-src> | grep -E "EvmXService|SolanaXService|SuiXService|BitcoinXService|StellarXService|InjectiveXService|IconXService|NearXService|StacksXService|EvmXConnector|SolanaXConnector|SuiXConnector|UnisatXConnector|XverseXConnector|OKXXConnector|StellarWalletsKitXConnector|InjectiveXConnector|IconHanaXConnector|NearXConnector|StacksXConnector"
96
- # expect empty (or only `import type` lines, which are still allowed for some types)
97
- ```
98
-
99
- - [ ] Concrete classes use sub-path imports (`@sodax/wallet-sdk-react/xchains/<chain>`).
100
- ```bash
101
- grep -rnE "from '@sodax/wallet-sdk-react/xchains/" <user-src>
102
- # if user code needs concrete classes, expect matches here
103
- ```
104
-
105
- ---
106
-
107
- ## Removed APIs
108
-
109
- - [ ] No `useXBalances` calls remain that import from `@sodax/wallet-sdk-react` (moved to `@sodax/dapp-kit` with a new signature).
110
- ```bash
111
- grep -rn "from '@sodax/wallet-sdk-react'" <user-src> | grep useXBalances
112
- # expect empty — v2 imports from '@sodax/dapp-kit', wraps args as `{ params: { xService, xChainId, xTokens, address } }`
113
- ```
114
-
115
- - [ ] No `useEthereumChainId` imports remain (internal in v2).
116
- ```bash
117
- grep -rn "useEthereumChainId" <user-src>
118
- # expect empty — replace with wagmi's `useAccount().chainId` or `useEvmSwitchChain({ xChainId })`
119
- ```
120
-
121
- ---
122
-
123
- ## Behavior verification
124
-
125
- - [ ] `pnpm checkTs` exits clean (in the user's app root).
126
- ```bash
127
- pnpm checkTs
128
- # expect exit code 0
129
- ```
130
-
131
- - [ ] Connect/disconnect flow works in dev environment (manual).
132
- ```
133
- # Manual:
134
- # 1. pnpm dev
135
- # 2. Click connect on each enabled chain
136
- # 3. Confirm address renders, localStorage has `xwagmi-store` key with the new connection
137
- # 4. Reload — confirm connection survives
138
- # 5. Click disconnect — confirm `xwagmi-store` clears that chain
139
- ```
140
-
141
- - [ ] EVM treated as single connection (manual; only if app had per-EVM-chain UI in v1).
142
- ```
143
- # Manual:
144
- # 1. Connect to EVM with any wallet
145
- # 2. Confirm useChainGroups returns one EVM row, not per-network rows
146
- # 3. Confirm useEvmSwitchChain switches the active network without re-connecting
147
- ```
148
-
149
- ---
150
-
151
- ## Done criteria
152
-
153
- The migration is complete when:
154
-
155
- - [ ] All sections above are checked.
156
- - [ ] User has confirmed the app's connect / disconnect / sign flows work end-to-end.
157
- - [ ] Tests are updated (if any test mocks `XService` / `useXWagmiStore`) — flagged in stop conditions; defer to user.
158
-
159
- If any item fails or is ambiguous, **stop and ask the user**. Do not declare complete until every box is ticked.
@@ -1,166 +0,0 @@
1
- # Recipe: Migrate a Single-Chain Connect Button
2
-
3
- Migrates the most common pattern: one button per chain that lists connectors, lets the user pick one, and shows the connected address. Self-contained — apply this recipe without reading other files.
4
-
5
- ---
6
-
7
- ## When to use this recipe
8
-
9
- Apply when the user's v1 code uses any of:
10
-
11
- - `useXConnectors('<chain>')` (positional)
12
- - `useXAccount('<chain>')` (positional)
13
- - `useXConnect()` + `useXDisconnect()` for a per-chain button
14
-
15
- If the user has a multi-chain modal (chain picker → connector picker), use [`multi-chain-modal.md`](./multi-chain-modal.md) instead.
16
-
17
- ---
18
-
19
- ## Before (v1)
20
-
21
- ```tsx
22
- 'use client';
23
-
24
- import {
25
- useXConnectors,
26
- useXConnect,
27
- useXAccount,
28
- useXDisconnect,
29
- } from '@sodax/wallet-sdk-react';
30
-
31
- export function EvmConnectButton() {
32
- const connectors = useXConnectors('EVM');
33
- const { mutateAsync: connect, isPending } = useXConnect();
34
- const { address } = useXAccount('EVM');
35
- const disconnect = useXDisconnect();
36
-
37
- if (address) {
38
- return (
39
- <div>
40
- Connected: {address}
41
- <button onClick={() => disconnect('EVM')}>Disconnect</button>
42
- </div>
43
- );
44
- }
45
-
46
- return (
47
- <div>
48
- {connectors.map((connector) => (
49
- <button
50
- key={connector.id}
51
- disabled={isPending}
52
- onClick={() => connect(connector)}
53
- >
54
- Connect with {connector.name}
55
- </button>
56
- ))}
57
- </div>
58
- );
59
- }
60
- ```
61
-
62
- ---
63
-
64
- ## After (v2)
65
-
66
- ```tsx
67
- 'use client';
68
-
69
- import {
70
- useXConnectors,
71
- useXConnect,
72
- useXAccount,
73
- useXDisconnect,
74
- } from '@sodax/wallet-sdk-react';
75
-
76
- export function EvmConnectButton() {
77
- const connectors = useXConnectors({ xChainType: 'EVM' });
78
- const { mutateAsync: connect, isPending } = useXConnect();
79
- const { address } = useXAccount({ xChainType: 'EVM' });
80
- const disconnect = useXDisconnect();
81
-
82
- if (address) {
83
- return (
84
- <div>
85
- Connected: {address}
86
- <button onClick={() => disconnect({ xChainType: 'EVM' })}>Disconnect</button>
87
- </div>
88
- );
89
- }
90
-
91
- return (
92
- <div>
93
- {connectors.map((connector) => (
94
- <button
95
- key={connector.id}
96
- disabled={isPending}
97
- onClick={() => connect(connector)}
98
- >
99
- Connect with {connector.name}
100
- </button>
101
- ))}
102
- </div>
103
- );
104
- }
105
- ```
106
-
107
- ---
108
-
109
- ## What changed
110
-
111
- | Line | v1 | v2 |
112
- |---|---|---|
113
- | `useXConnectors` | `useXConnectors('EVM')` | `useXConnectors({ xChainType: 'EVM' })` |
114
- | `useXAccount` | `useXAccount('EVM')` | `useXAccount({ xChainType: 'EVM' })` |
115
- | `useXConnect` mutation arg | pass `connector` to `mutateAsync` | unchanged |
116
- | `useXDisconnect` returned callback | `disconnect('EVM')` | `disconnect({ xChainType: 'EVM' })` |
117
-
118
- The mechanical changes are the **three hook usages** above. The `useXDisconnect` callback shape changed in v2 — see [`../reference/hooks.md`](../reference/hooks.md) § `useXDisconnect`.
119
-
120
- ---
121
-
122
- ## Variations
123
-
124
- ### Per-chain-id (e.g. one connect button per EVM network)
125
-
126
- If v1 used `useXAccount('0x1.eth')`:
127
-
128
- ```tsx
129
- // v1 ❌
130
- const { address } = useXAccount('0x1.eth');
131
- ```
132
-
133
- Use the typed chain key in v2:
134
-
135
- ```tsx
136
- // v2 ✅
137
- import { ChainKeys } from '@sodax/types';
138
- const { address } = useXAccount({ xChainId: ChainKeys.ETHEREUM_MAINNET });
139
- ```
140
-
141
- > ⚠️ If the v1 button is "connect to Ethereum", remember v2 treats EVM as a **single connection across every configured EVM network**. A per-Ethereum button is rarely what users want — consider replacing with a single "EVM" button + `useEvmSwitchChain` for network switching. See [`../breaking-changes.md`](../breaking-changes.md) §7.
142
-
143
- ### Sui / Solana / etc.
144
-
145
- Replace `'EVM'` with the chain type the button targets — the migration is mechanical:
146
-
147
- ```tsx
148
- const connectors = useXConnectors({ xChainType: 'SUI' });
149
- const { address } = useXAccount({ xChainType: 'SUI' });
150
- ```
151
-
152
- ---
153
-
154
- ## Verification
155
-
156
- ```bash
157
- # 1. Type check
158
- pnpm checkTs
159
-
160
- # 2. Confirm no positional hook args remain in this file
161
- grep -nE "useXAccount\(['\"]" <file>
162
- grep -nE "useXConnectors\(['\"]" <file>
163
- # expect empty
164
-
165
- # 3. Manual — load page, click connect, confirm address renders
166
- ```