@sodax/wallet-sdk-react 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.
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 -23
  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 -158
  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 -162
  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 -307
  67. package/ai-exported/migration/reference/hooks.md +0 -278
  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,307 +0,0 @@
1
- # Reference: `SodaxWalletProvider` Config Map
2
-
3
- The biggest single change in v2. v1 spread chain configuration across three props (`rpcConfig`, `options`, `initialState`); v2 collapses them into one `config` prop. See [`../breaking-changes.md`](../breaking-changes.md) §1 for the WHY.
4
-
5
- ---
6
-
7
- ## Top-level shape
8
-
9
- ```tsx
10
- // v1 ❌
11
- <SodaxWalletProvider
12
- rpcConfig={rpcConfig}
13
- options={{ wagmi, solana, sui }}
14
- initialState={wagmiState}
15
- >
16
- {children}
17
- </SodaxWalletProvider>
18
-
19
- // v2 ✅
20
- <SodaxWalletProvider config={walletConfig}>{children}</SodaxWalletProvider>
21
- ```
22
-
23
- The v2 `config` is `SodaxWalletConfig`. Top-level keys are **chain-type slots** (`EVM`, `SOLANA`, `SUI`, `BITCOIN`, `STELLAR`, `ICON`, `INJECTIVE`, `NEAR`, `STACKS`). **Omit a slot to skip mounting that adapter**; pass `{}` to mount with SDK defaults.
24
-
25
- ---
26
-
27
- ## v1 `rpcConfig` → v2 per-chain `rpcUrl`
28
-
29
- v1 took a flat dictionary keyed by some chain string:
30
-
31
- ```ts
32
- // v1 ❌
33
- const rpcConfig: RpcConfig = {
34
- 'sonic': 'https://rpc.soniclabs.com',
35
- '0x1.eth': 'https://ethereum-rpc.publicnode.com',
36
- 'solana': 'https://api.mainnet-beta.solana.com',
37
- // ...
38
- };
39
- ```
40
-
41
- v2 nests RPC URLs under `<ChainTypeSlot>.chains[ChainKey].rpcUrl`:
42
-
43
- ```ts
44
- // v2 ✅
45
- import { ChainKeys } from '@sodax/types';
46
- import type { SodaxWalletConfig } from '@sodax/wallet-sdk-react';
47
-
48
- const walletConfig: SodaxWalletConfig = {
49
- EVM: {
50
- chains: {
51
- [ChainKeys.SONIC_MAINNET]: { rpcUrl: 'https://rpc.soniclabs.com' },
52
- [ChainKeys.ETHEREUM_MAINNET]: { rpcUrl: 'https://ethereum-rpc.publicnode.com' },
53
- },
54
- },
55
- SOLANA: {
56
- chains: {
57
- [ChainKeys.SOLANA_MAINNET]: { rpcUrl: 'https://api.mainnet-beta.solana.com' },
58
- },
59
- },
60
- };
61
- ```
62
-
63
- **Per-chain entry shape varies** by chain type:
64
-
65
- | Slot | Per-chain entry |
66
- |---|---|
67
- | `EVM`, `SOLANA`, `SUI`, `ICON`, `NEAR` | `{ rpcUrl?, defaults? }` |
68
- | `BITCOIN`, `STELLAR`, `INJECTIVE` | extends their `*RpcConfig` type with `{ defaults? }` |
69
- | `STACKS` | preset name (string) **or** `StacksNetworkLike & { defaults? }` |
70
-
71
- The single source of truth for the per-chain shape is `ChainMeta` in `src/types/config.ts` — `SodaxWalletConfig`, `ChainEntry<K>`, `WalletDefaultsByKey<K>` derive from it.
72
-
73
- ---
74
-
75
- ## v1 `options.wagmi` → v2 `EVM.*`
76
-
77
- ```ts
78
- // v1 ❌
79
- options: {
80
- wagmi: {
81
- reconnectOnMount: false,
82
- ssr: true,
83
- },
84
- }
85
- ```
86
-
87
- ```ts
88
- // v2 ✅
89
- EVM: {
90
- ssr: true,
91
- reconnectOnMount: true,
92
- chains: { ... },
93
- }
94
- ```
95
-
96
- | v1 | v2 | Notes |
97
- |---|---|---|
98
- | `options.wagmi.ssr` | `EVM.ssr` | Defaults: v1 `true`, v2 not set (caller decides). For Next.js, set `true`. |
99
- | `options.wagmi.reconnectOnMount` | `EVM.reconnectOnMount` | Still supported, default `false`. Moved into the `EVM` slot. See [`migration/recipes/ssr-setup.md`](../recipes/ssr-setup.md) for the SSR-aware flow. |
100
-
101
- ---
102
-
103
- ## v1 `options.solana` → v2 `SOLANA.*`
104
-
105
- ```ts
106
- // v1 ❌
107
- options: {
108
- solana: { autoConnect: true },
109
- }
110
- ```
111
-
112
- ```ts
113
- // v2 ✅
114
- SOLANA: {
115
- autoConnect: true,
116
- chains: {
117
- [ChainKeys.SOLANA_MAINNET]: { rpcUrl: '...' },
118
- },
119
- }
120
- ```
121
-
122
- | v1 | v2 |
123
- |---|---|
124
- | `options.solana.autoConnect` | `SOLANA.autoConnect` |
125
-
126
- ---
127
-
128
- ## v1 `options.sui` → v2 `SUI.*`
129
-
130
- ```ts
131
- // v1 ❌
132
- options: {
133
- sui: { autoConnect: true },
134
- }
135
- ```
136
-
137
- ```ts
138
- // v2 ✅
139
- SUI: {
140
- autoConnect: true,
141
- network: 'mainnet',
142
- }
143
- ```
144
-
145
- `SUI` slot fields (per `SuiAdapterFields` in `src/types/config.ts`):
146
-
147
- | Field | Type | Default |
148
- |---|---|---|
149
- | `autoConnect` | `boolean?` | `true` |
150
- | `network` | `'mainnet' \| 'testnet' \| 'devnet'?` | `'mainnet'` |
151
-
152
- | v1 | v2 |
153
- |---|---|
154
- | `options.sui.autoConnect` | `SUI.autoConnect` |
155
-
156
- ---
157
-
158
- ## v1 `initialState` → v2 `EVM.initialState`
159
-
160
- v1 accepted a top-level `initialState` prop (`WagmiState`) for SSR hydration. v2 still accepts the same value — it just lives **inside the `EVM` slot** of the `config` prop.
161
-
162
- ```ts
163
- // v1 ❌
164
- <SodaxWalletProvider rpcConfig={...} options={...} initialState={wagmiState}>
165
-
166
- // v2 ✅
167
- <SodaxWalletProvider config={{
168
- EVM: {
169
- ssr: true,
170
- initialState: wagmiState,
171
- chains: {...},
172
- },
173
- /* ... */
174
- }}>
175
- ```
176
-
177
- If you previously derived `initialState` via `cookieToInitialState(...)` in a server component, keep that logic — just pass the result into `EVM.initialState` instead of the top-level prop. See [`../recipes/ssr-setup.md`](../recipes/ssr-setup.md) for a full Next.js example.
178
-
179
- ---
180
-
181
- ## New in v2: per-chain `defaults`
182
-
183
- Each chain entry can hold call-level defaults that flow to the bridged `IXxxWalletProvider`:
184
-
185
- ```ts
186
- // v2 ✅
187
- EVM: {
188
- chains: {
189
- [ChainKeys.ARBITRUM_MAINNET]: {
190
- rpcUrl: 'https://arb1.arbitrum.io/rpc',
191
- defaults: {
192
- waitForTransactionReceipt: { confirmations: 1 },
193
- },
194
- },
195
- },
196
- }
197
- ```
198
-
199
- The `defaults` shape is per-chain — the type system narrows what's valid per chain key. Inspect `WalletDefaultsByKey<K>` in `src/types/config.ts`.
200
-
201
- ---
202
-
203
- ## New in v2: `EVM.walletConnect`
204
-
205
- WalletConnect support for EVM — extends wagmi's `WalletConnectParameters`:
206
-
207
- ```ts
208
- // v2 ✅
209
- EVM: {
210
- walletConnect: {
211
- projectId: 'wc-cloud-project-id', // required from cloud.walletconnect.com
212
- // qrModalOptions, isNewChainsStale, etc. — full WalletConnectParameters
213
- },
214
- }
215
- ```
216
-
217
- When `walletConnect` is present, a WalletConnect connector is added to the wagmi config; `useXConnectors({ xChainType: 'EVM' })` will surface it. Omitting the field preserves v1 behavior (EIP-6963 only).
218
-
219
- See [`../recipes/walletconnect-migration.md`](../recipes/walletconnect-migration.md).
220
-
221
- ---
222
-
223
- ## New in v2: `<chainSlot>.connectors?` override
224
-
225
- Each chain slot accepts an optional `connectors` field to override the default connector list. Most consumers don't need this — defaults work for all common wallet vendors.
226
-
227
- ---
228
-
229
- ## Frozen on first render
230
-
231
- `SodaxWalletProvider` captures `config` once on mount and ignores prop-reference changes. To swap config at runtime, remount with a new `key`:
232
-
233
- ```tsx
234
- // v2 ✅
235
- <SodaxWalletProvider key={configVersion} config={walletConfig}>
236
- {children}
237
- </SodaxWalletProvider>
238
- ```
239
-
240
- Bumping `configVersion` (e.g. when the user picks a new RPC endpoint) forces a clean re-init. See [`../breaking-changes.md`](../breaking-changes.md) §12.
241
-
242
- ---
243
-
244
- ## Provider-stack order changed
245
-
246
- v1 created `QueryClient` internally; v2 expects the consumer to provide one:
247
-
248
- ```tsx
249
- // v1 ❌ — QueryClientProvider was internal
250
- <SodaxWalletProvider rpcConfig={...} options={...}>{children}</SodaxWalletProvider>
251
-
252
- // v2 ✅ — caller wraps with QueryClientProvider
253
- <QueryClientProvider client={queryClient}>
254
- <SodaxWalletProvider config={walletConfig}>{children}</SodaxWalletProvider>
255
- </QueryClientProvider>
256
- ```
257
-
258
- Add `@tanstack/react-query 5.x` as a direct dependency if your app didn't already have it. See [`../breaking-changes.md`](../breaking-changes.md) §2.
259
-
260
- ---
261
-
262
- ## Minimal valid v2 config — every shape, side by side
263
-
264
- ```ts
265
- // v2 ✅
266
- import { ChainKeys } from '@sodax/types';
267
- import type { SodaxWalletConfig } from '@sodax/wallet-sdk-react';
268
-
269
- const walletConfig: SodaxWalletConfig = {
270
- // EVM — needs chains
271
- EVM: {
272
- ssr: true,
273
- chains: {
274
- [ChainKeys.SONIC_MAINNET]: { rpcUrl: 'https://rpc.soniclabs.com' },
275
- },
276
- // optional:
277
- // walletConnect: { projectId: '...' },
278
- },
279
-
280
- // SOLANA — chain entry + autoConnect
281
- SOLANA: {
282
- autoConnect: false,
283
- chains: {
284
- [ChainKeys.SOLANA_MAINNET]: { rpcUrl: 'https://api.mainnet-beta.solana.com' },
285
- },
286
- },
287
-
288
- // SUI — network preset
289
- SUI: { network: 'mainnet' },
290
-
291
- // ICON — chain entry
292
- ICON: {
293
- chains: {
294
- [ChainKeys.ICON_MAINNET]: { rpcUrl: 'https://ctz.solidwallet.io/api/v3' },
295
- },
296
- },
297
-
298
- // BITCOIN, STELLAR, INJECTIVE, NEAR, STACKS — pass {} to mount with SDK defaults
299
- BITCOIN: {},
300
- STELLAR: {},
301
- INJECTIVE: {},
302
- NEAR: {},
303
- STACKS: {},
304
- };
305
- ```
306
-
307
- Omit any slot to skip that chain entirely.
@@ -1,278 +0,0 @@
1
- # Reference: Hook Signature Map
2
-
3
- Per-hook signature changes for v1 → v2. See [`../breaking-changes.md`](../breaking-changes.md) §3 for the WHY.
4
-
5
- ---
6
-
7
- ## Quick rule
8
-
9
- | Pattern | v1 (positional) | v2 (options object) |
10
- |---|---|---|
11
- | Pass chain family | `useX('EVM')` | `useX({ xChainType: 'EVM' })` |
12
- | Pass chain id | `useX('0x1.eth')` | `useX({ xChainId: ChainKeys.ETHEREUM_MAINNET })` |
13
- | Cannot pass both | (runtime detected) | TypeScript-enforced (`xChainType: never` on the chain-id branch and vice versa) |
14
-
15
- `xChainId` in v2 is typed as `SpokeChainKey` (the enum from `@sodax/types`), not the raw string id. The narrower type lets v2 hooks return chain-typed providers (e.g. `IEvmWalletProvider | undefined`) instead of the v1 union.
16
-
17
- ---
18
-
19
- ## `useXAccount`
20
-
21
- ```ts
22
- // v1 ❌
23
- const { address } = useXAccount('EVM');
24
- const { address } = useXAccount('0x1.eth');
25
-
26
- // v2 ✅
27
- import { ChainKeys } from '@sodax/types';
28
-
29
- const { address } = useXAccount({ xChainType: 'EVM' });
30
- const { address } = useXAccount({ xChainId: ChainKeys.ETHEREUM_MAINNET });
31
- ```
32
-
33
- **Decision rule (positional value → field name):** v1 accepted both `ChainType` and `ChainId` and detected at runtime. In v2 you must choose the right field:
34
-
35
- - v1 value is a family literal (`'EVM'`, `'SOLANA'`, …) → v2 `xChainType`.
36
- - v1 value is a chain-key string (`'0x1.eth'`, `XToken.xChainId`, …) → v2 `xChainId` typed as `SpokeChainKey`.
37
- - v1 value comes from `getXChainType(...)` (returns `ChainType | undefined`) → v2 `xChainType`, but **guard against `undefined`** — see below.
38
-
39
- **v2 asserts at runtime that exactly one of `xChainId` / `xChainType` is present.** Both undefined throws `'[useXAccount] pass xChainId or xChainType'`; both present throws `'[useXAccount] pass either xChainId or xChainType, not both'`. v1 was permissive (called with `undefined`, it returned an empty account). v2 is strict.
40
-
41
- **Common nullable patterns and their fixes:**
42
-
43
- ```ts
44
- // ❌ v1 idiom — returns empty account when nothing selected, runs every render
45
- const { address } = useXAccount(selectedChainId ?? undefined);
46
-
47
- // ✅ v2 fix 1 — index a snapshot from useXAccounts (no per-key hook call)
48
- const xAccounts = useXAccounts();
49
- const chainType = selectedChainId ? getXChainType(selectedChainId) : undefined;
50
- const address = chainType ? xAccounts[chainType]?.address : undefined;
51
-
52
- // ✅ v2 fix 2 — supply a sensible default chain key so the hook always has input
53
- const { address } = useXAccount({
54
- xChainId: selectedChainId ?? ChainKeys.SONIC_MAINNET,
55
- });
56
-
57
- // ✅ v2 fix 3 — split into a child component that only mounts when input is known
58
- {selectedChainId ? <Account xChainId={selectedChainId} /> : null}
59
- function Account({ xChainId }: { xChainId: SpokeChainKey }) {
60
- const { address } = useXAccount({ xChainId });
61
- // ...
62
- }
63
- ```
64
-
65
- The other "options-object" hooks (`useXConnection`, `useXConnectors`, `useXService`, `useWalletProvider`) are **lenient** — passing no field returns the empty/undefined value silently. `useXAccount` is the only one that asserts.
66
-
67
- **Other notes:**
68
- - Return shape unchanged: `XAccount = { address, xChainType, publicKey? }`.
69
- - When a valid chain is supplied but no wallet is connected, `address` is `undefined` while `xChainType` is filled — same as v1's connected-empty state.
70
-
71
- ---
72
-
73
- ## `useXConnectors`
74
-
75
- ```ts
76
- // v1 ❌
77
- const connectors = useXConnectors('EVM');
78
-
79
- // v2 ✅
80
- const connectors = useXConnectors({ xChainType: 'EVM' });
81
- ```
82
-
83
- **Other notes:**
84
- - Return type changed from `XConnector[]` to `IXConnector[]` (interface). For most consumers this is invisible — both expose `id`, `name`, `icon`, `xChainType`, `connect()`, `disconnect()`.
85
- - v2 enriches each connector with `isInstalled`, `installUrl`, `icon` (read at access time from `window.*`).
86
- - v2 returns `[]` and logs a one-time warning if the chain isn't in `enabledChains`. v1 returned `[]` silently.
87
-
88
- ---
89
-
90
- ## `useXConnection`
91
-
92
- ```ts
93
- // v1 ❌
94
- const connection = useXConnection('EVM');
95
-
96
- // v2 ✅
97
- const connection = useXConnection({ xChainType: 'EVM' });
98
- ```
99
-
100
- Return shape unchanged: `XConnection | undefined = { xAccount, xConnectorId } | undefined`.
101
-
102
- ---
103
-
104
- ## `useXService`
105
-
106
- ```ts
107
- // v1 ❌
108
- const service = useXService('EVM');
109
-
110
- // v2 ✅
111
- const service = useXService({ xChainType: 'EVM' });
112
- ```
113
-
114
- Return type unchanged.
115
-
116
- ---
117
-
118
- ## `useWalletProvider`
119
-
120
- ```ts
121
- // v1 ❌ — positional spokeChainId, returns wide union
122
- const wp = useWalletProvider('sui');
123
-
124
- // v2 ✅ — options object, narrowest type when xChainId is passed
125
- import { ChainKeys } from '@sodax/types';
126
-
127
- const wp = useWalletProvider({ xChainId: ChainKeys.SUI_MAINNET });
128
- // ^ inferred as ISuiWalletProvider | undefined
129
-
130
- const wp2 = useWalletProvider({ xChainType: 'EVM' });
131
- // ^ inferred as IEvmWalletProvider | undefined
132
-
133
- const wp3 = useWalletProvider();
134
- // ^ inferred as IWalletProvider | undefined (any)
135
- ```
136
-
137
- **Other notes:**
138
- - Pass either `xChainId` (`SpokeChainKey`) or `xChainType` (`ChainType`), never both. Chain key gives narrower TypeScript inference.
139
- - Returns `undefined` when the chain isn't enabled in `walletConfig` (logs a one-time warning) or when no wallet is connected.
140
-
141
- ---
142
-
143
- ## `useXConnect`
144
-
145
- ```ts
146
- // v1 ✅ AND v2 ✅ — same signature
147
- const { mutateAsync: connect } = useXConnect();
148
- await connect(connector);
149
- ```
150
-
151
- No change in shape. The `connector` argument type is `IXConnector` in v2 (was `XConnector` abstract class in v1) — runtime behavior identical for any connector returned by `useXConnectors`.
152
-
153
- ---
154
-
155
- ## `useXDisconnect`
156
-
157
- ```ts
158
- // v1 ❌ — returned function takes positional ChainType
159
- const disconnect = useXDisconnect();
160
- await disconnect('EVM');
161
-
162
- // v2 ✅ — returned function takes options object
163
- const disconnect = useXDisconnect();
164
- await disconnect({ xChainType: 'EVM' });
165
- ```
166
-
167
- The hook itself takes no args in both versions. The **returned function** changed: v1 was positional `(xChainType: ChainType) => Promise<void>`; v2 is `(args: UseXDisconnectArgs) => Promise<void>` where `UseXDisconnectArgs = { xChainType: ChainType }`. Same forward-compat reason as the other hooks — see [`../breaking-changes.md`](../breaking-changes.md) §3.
168
-
169
- **Common breakage:** `await disconnect(xChainType)` raises `TS2345: Argument of type 'string' is not assignable to parameter of type 'UseXDisconnectArgs'`. Wrap in an object.
170
-
171
- ---
172
-
173
- ## `useXSignMessage`
174
-
175
- ```ts
176
- // v1 ✅ AND v2 ✅ — same signature
177
- const { mutateAsync: signMessage } = useXSignMessage();
178
- const sig = await signMessage({ xChainType: 'EVM', message: 'hello' });
179
- ```
180
-
181
- No change.
182
-
183
- ---
184
-
185
- ## `useXAccounts`
186
-
187
- ```ts
188
- // v1
189
- const accounts = useXAccounts();
190
-
191
- // v2 — return type is now strictly typed
192
- const accounts = useXAccounts();
193
- // → Partial<Record<ChainType, XAccount>>
194
- ```
195
-
196
- Call signature unchanged. **Indexing tightened**: `accounts[chainType]` returns `XAccount | undefined`. The index variable must be typed as `ChainType` (not `string` or `any`) — otherwise you'll see `TS7053: Element implicitly has an 'any' type`.
197
-
198
- ```ts
199
- // ❌ FAILS — chainType is `string`, can't index Partial<Record<ChainType, ...>>
200
- const chainType = someStringFromConfig;
201
- const account = accounts[chainType];
202
-
203
- // ✅ FIX 1 — narrow with getXChainType (returns ChainType | undefined)
204
- import { getXChainType } from '@sodax/wallet-sdk-react';
205
- const chainType = getXChainType(chainId);
206
- const account = chainType ? accounts[chainType] : undefined;
207
-
208
- // ✅ FIX 2 — call useXAccount per-chain instead of indexing
209
- const account = useXAccount({ xChainType: 'EVM' });
210
- ```
211
-
212
- ---
213
-
214
- ## `useEvmSwitchChain`
215
-
216
- ```ts
217
- // v1 ❌ — positional `expectedXChainId: ChainId`
218
- const { isWrongChain, handleSwitchChain } = useEvmSwitchChain(chainId);
219
-
220
- // v2 ✅ — options object; `xChainId: SpokeChainKey`
221
- import { ChainKeys } from '@sodax/types';
222
-
223
- const { isWrongChain, handleSwitchChain } = useEvmSwitchChain({
224
- xChainId: ChainKeys.ETHEREUM_MAINNET,
225
- });
226
-
227
- if (isWrongChain) handleSwitchChain();
228
- ```
229
-
230
- **Breaking changes:**
231
-
232
- - **Call shape**: positional → options object. Same forward-compat reason as the other hooks.
233
- - **Parameter type**: `ChainId` → `SpokeChainKey` (rename in `@sodax/types`). If the chain key value comes from `XToken.chainKey` (v2) or any `ChainKeys.*` constant, no value change is needed — the rename is type-only.
234
-
235
- **Return shape is unchanged** — both v1 and v2 return `{ isWrongChain: boolean, handleSwitchChain: () => void }`. The hook compares the connected EVM chain to the chain expected by `xChainId` and exposes `isWrongChain` so UI can render a "switch network" CTA without recomputing.
236
-
237
- **Behavior added in v2:**
238
-
239
- - **Injective + MetaMask auto-switch.** When the user connects to Injective via MetaMask, v2 automatically targets Ethereum mainnet underneath. v1 had no Injective awareness.
240
- - **Safe when EVM is disabled.** v2 returns no-op values (`isWrongChain: false`, `handleSwitchChain: () => {}`) if `walletConfig.EVM` is absent, so UI doesn't need to branch.
241
-
242
- ---
243
-
244
- ## `useEthereumChainId`
245
-
246
- **Removed from the public barrel in v2.** Despite the generic-sounding name, the v1 hook was **Injective + MetaMask specific** — it read the underlying Ethereum chain ID exposed by Injective's wallet strategy and was almost always used to drive the "switch back to Ethereum mainnet" UX. v2 makes the hook internal because `useEvmSwitchChain` now handles that Injective auto-switch case directly.
247
-
248
- Migration:
249
-
250
- ```diff
251
- - // v1 ❌ — manual chain-ID comparison for Injective + MetaMask UX
252
- - import { useEthereumChainId } from '@sodax/wallet-sdk-react';
253
- - const chainId = useEthereumChainId();
254
- - if (chainId !== 1) /* prompt user to switch to Ethereum mainnet */;
255
- + // v2 ✅ — useEvmSwitchChain auto-handles Injective + MetaMask underneath
256
- + import { useEvmSwitchChain } from '@sodax/wallet-sdk-react';
257
- + import { ChainKeys } from '@sodax/types';
258
- + const { isWrongChain, handleSwitchChain } = useEvmSwitchChain({
259
- + xChainId: ChainKeys.INJECTIVE_MAINNET,
260
- + });
261
- + if (isWrongChain) handleSwitchChain();
262
- ```
263
-
264
- If you genuinely need the raw EVM chain ID (rare — almost no usage outside the Injective case), wagmi's `useAccount().chainId` is the underlying source. Prefer staying inside `@sodax/wallet-sdk-react` hooks where possible.
265
-
266
- ---
267
-
268
- ## Removed in v2
269
-
270
- | Hook | Replacement |
271
- |---|---|
272
- | `useXBalances` | Moved to `@sodax/dapp-kit`. See [`../breaking-changes.md`](../breaking-changes.md) §10. |
273
-
274
- ---
275
-
276
- ## Added in v2 (no v1 equivalent)
277
-
278
- See [`imports.md`](./imports.md) § "Added in v2" for the full list (`useWalletModal`, `useChainGroups`, `useBatchConnect`, etc.). These are not migration items — they are new capabilities you may opt into.