@sodax/wallet-sdk-react 1.5.7-beta → 2.0.0-rc.1

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 (211) hide show
  1. package/README.md +103 -145
  2. package/ai-exported/AGENTS.md +122 -0
  3. package/ai-exported/integration/README.md +102 -0
  4. package/ai-exported/integration/ai-rules.md +136 -0
  5. package/ai-exported/integration/architecture.md +181 -0
  6. package/ai-exported/integration/examples/01-minimal-evm.tsx +75 -0
  7. package/ai-exported/integration/examples/02-multi-chain-modal.tsx +169 -0
  8. package/ai-exported/integration/examples/03-nextjs-app-router.tsx +99 -0
  9. package/ai-exported/integration/examples/04-walletconnect-setup.tsx +89 -0
  10. package/ai-exported/integration/examples/README.md +29 -0
  11. package/ai-exported/integration/recipes/batch-operations.md +223 -0
  12. package/ai-exported/integration/recipes/bridge-to-sdk.md +164 -0
  13. package/ai-exported/integration/recipes/chain-detection.md +254 -0
  14. package/ai-exported/integration/recipes/connect-button.md +156 -0
  15. package/ai-exported/integration/recipes/multi-chain-modal.md +199 -0
  16. package/ai-exported/integration/recipes/setup.md +158 -0
  17. package/ai-exported/integration/recipes/sign-message.md +137 -0
  18. package/ai-exported/integration/recipes/sub-path-imports.md +95 -0
  19. package/ai-exported/integration/recipes/switch-chain.md +141 -0
  20. package/ai-exported/integration/recipes/walletconnect-setup.md +139 -0
  21. package/ai-exported/integration/reference/api-surface.md +175 -0
  22. package/ai-exported/integration/reference/chain-support.md +78 -0
  23. package/ai-exported/integration/reference/connectors.md +74 -0
  24. package/ai-exported/integration/reference/hooks.md +204 -0
  25. package/ai-exported/integration/reference/wallet-brands.md +106 -0
  26. package/ai-exported/migration/README.md +49 -0
  27. package/ai-exported/migration/ai-rules.md +144 -0
  28. package/ai-exported/migration/breaking-changes.md +305 -0
  29. package/ai-exported/migration/checklist.md +159 -0
  30. package/ai-exported/migration/recipes/connect-button.md +166 -0
  31. package/ai-exported/migration/recipes/multi-chain-modal.md +244 -0
  32. package/ai-exported/migration/recipes/ssr-setup.md +162 -0
  33. package/ai-exported/migration/recipes/walletconnect-migration.md +168 -0
  34. package/ai-exported/migration/reference/components.md +73 -0
  35. package/ai-exported/migration/reference/config.md +307 -0
  36. package/ai-exported/migration/reference/hooks.md +278 -0
  37. package/ai-exported/migration/reference/imports.md +157 -0
  38. package/dist/XConnector-B9YQTVJ4.d.ts +146 -0
  39. package/dist/chunk-2BOUGCJ7.mjs +150 -0
  40. package/dist/chunk-2BOUGCJ7.mjs.map +1 -0
  41. package/dist/chunk-66BAUK56.mjs +202 -0
  42. package/dist/chunk-66BAUK56.mjs.map +1 -0
  43. package/dist/chunk-7ULB6DW4.mjs +102 -0
  44. package/dist/chunk-7ULB6DW4.mjs.map +1 -0
  45. package/dist/chunk-BKJB527E.mjs +125 -0
  46. package/dist/chunk-BKJB527E.mjs.map +1 -0
  47. package/dist/chunk-BXJLBR4G.mjs +88 -0
  48. package/dist/chunk-BXJLBR4G.mjs.map +1 -0
  49. package/dist/chunk-E5IAZ7E6.mjs +186 -0
  50. package/dist/chunk-E5IAZ7E6.mjs.map +1 -0
  51. package/dist/chunk-MAQ47Q52.mjs +33 -0
  52. package/dist/chunk-MAQ47Q52.mjs.map +1 -0
  53. package/dist/chunk-MXZVF5HR.mjs +34 -0
  54. package/dist/chunk-MXZVF5HR.mjs.map +1 -0
  55. package/dist/chunk-N5A2TMF6.mjs +33 -0
  56. package/dist/chunk-N5A2TMF6.mjs.map +1 -0
  57. package/dist/chunk-NY7U7OJW.mjs +64 -0
  58. package/dist/chunk-NY7U7OJW.mjs.map +1 -0
  59. package/dist/chunk-PJLEJVAU.mjs +140 -0
  60. package/dist/chunk-PJLEJVAU.mjs.map +1 -0
  61. package/dist/chunk-PLCA4ZDJ.mjs +1585 -0
  62. package/dist/chunk-PLCA4ZDJ.mjs.map +1 -0
  63. package/dist/chunk-TZMKDXFA.mjs +3 -0
  64. package/dist/chunk-TZMKDXFA.mjs.map +1 -0
  65. package/dist/chunk-X2MHIWXO.mjs +100 -0
  66. package/dist/chunk-X2MHIWXO.mjs.map +1 -0
  67. package/dist/chunk-XZ7CHO2S.mjs +41 -0
  68. package/dist/chunk-XZ7CHO2S.mjs.map +1 -0
  69. package/dist/config-OlnzyEUE.d.ts +146 -0
  70. package/dist/index.cjs +2784 -1594
  71. package/dist/index.cjs.map +1 -1
  72. package/dist/index.d.ts +768 -1498
  73. package/dist/index.mjs +463 -2004
  74. package/dist/index.mjs.map +1 -1
  75. package/dist/xchains/bitcoin/index.cjs +1927 -0
  76. package/dist/xchains/bitcoin/index.cjs.map +1 -0
  77. package/dist/xchains/bitcoin/index.d.ts +125 -0
  78. package/dist/xchains/bitcoin/index.mjs +16 -0
  79. package/dist/xchains/bitcoin/index.mjs.map +1 -0
  80. package/dist/xchains/evm/index.cjs +316 -0
  81. package/dist/xchains/evm/index.cjs.map +1 -0
  82. package/dist/xchains/evm/index.d.ts +39 -0
  83. package/dist/xchains/evm/index.mjs +5 -0
  84. package/dist/xchains/evm/index.mjs.map +1 -0
  85. package/dist/xchains/icon/index.cjs +311 -0
  86. package/dist/xchains/icon/index.cjs.map +1 -0
  87. package/dist/xchains/icon/index.d.ts +37 -0
  88. package/dist/xchains/icon/index.mjs +7 -0
  89. package/dist/xchains/icon/index.mjs.map +1 -0
  90. package/dist/xchains/injective/index.cjs +223 -0
  91. package/dist/xchains/injective/index.cjs.map +1 -0
  92. package/dist/xchains/injective/index.d.ts +35 -0
  93. package/dist/xchains/injective/index.mjs +5 -0
  94. package/dist/xchains/injective/index.mjs.map +1 -0
  95. package/dist/xchains/near/index.cjs +190 -0
  96. package/dist/xchains/near/index.cjs.map +1 -0
  97. package/dist/xchains/near/index.d.ts +34 -0
  98. package/dist/xchains/near/index.mjs +6 -0
  99. package/dist/xchains/near/index.mjs.map +1 -0
  100. package/dist/xchains/solana/index.cjs +186 -0
  101. package/dist/xchains/solana/index.cjs.map +1 -0
  102. package/dist/xchains/solana/index.d.ts +26 -0
  103. package/dist/xchains/solana/index.mjs +7 -0
  104. package/dist/xchains/solana/index.mjs.map +1 -0
  105. package/dist/xchains/stacks/index.cjs +240 -0
  106. package/dist/xchains/stacks/index.cjs.map +1 -0
  107. package/dist/xchains/stacks/index.d.ts +36 -0
  108. package/dist/xchains/stacks/index.mjs +5 -0
  109. package/dist/xchains/stacks/index.mjs.map +1 -0
  110. package/dist/xchains/stellar/index.cjs +322 -0
  111. package/dist/xchains/stellar/index.cjs.map +1 -0
  112. package/dist/xchains/stellar/index.d.ts +44 -0
  113. package/dist/xchains/stellar/index.mjs +6 -0
  114. package/dist/xchains/stellar/index.mjs.map +1 -0
  115. package/dist/xchains/sui/index.cjs +248 -0
  116. package/dist/xchains/sui/index.cjs.map +1 -0
  117. package/dist/xchains/sui/index.d.ts +37 -0
  118. package/dist/xchains/sui/index.mjs +7 -0
  119. package/dist/xchains/sui/index.mjs.map +1 -0
  120. package/docs/ADDING_A_NEW_CHAIN.md +440 -0
  121. package/docs/ARCHITECTURE.md +291 -0
  122. package/docs/BATCH_OPERATIONS.md +267 -0
  123. package/docs/CHAIN_DETECTION.md +216 -0
  124. package/docs/CONFIGURE_PROVIDER.md +360 -0
  125. package/docs/CONNECTORS.md +247 -0
  126. package/docs/CONNECT_FLOW.md +276 -0
  127. package/docs/EVM_SWITCH_CHAIN.md +161 -0
  128. package/docs/SIGN_MESSAGE.md +213 -0
  129. package/docs/SUB_PATH_EXPORTS.md +246 -0
  130. package/docs/WALLETCONNECT.md +154 -0
  131. package/docs/WALLET_MODAL.md +331 -0
  132. package/docs/WALLET_PROVIDER_BRIDGE.md +226 -0
  133. package/package.json +34 -9
  134. package/skills/SKILLS.md +84 -0
  135. package/skills/bridge-to-sdk.md +148 -0
  136. package/skills/connect-button.md +116 -0
  137. package/skills/evm-only-walletconnect.md +111 -0
  138. package/skills/multi-chain-modal.md +178 -0
  139. package/skills/setup.md +107 -0
  140. package/dist/index.d.cts +0 -1579
  141. package/src/Hydrate.ts +0 -65
  142. package/src/SodaxWalletProvider.tsx +0 -97
  143. package/src/actions/getXChainType.ts +0 -8
  144. package/src/actions/getXService.ts +0 -33
  145. package/src/actions/index.ts +0 -2
  146. package/src/assets/wallets/hana.svg +0 -6
  147. package/src/assets/wallets/havah.svg +0 -76
  148. package/src/assets/wallets/keplr.svg +0 -30
  149. package/src/assets/wallets/metamask.svg +0 -60
  150. package/src/assets/wallets/phantom.svg +0 -4
  151. package/src/assets/wallets/sui.svg +0 -20
  152. package/src/core/XConnector.ts +0 -54
  153. package/src/core/XService.ts +0 -85
  154. package/src/core/index.ts +0 -2
  155. package/src/hooks/index.ts +0 -11
  156. package/src/hooks/useEthereumChainId.ts +0 -44
  157. package/src/hooks/useEvmSwitchChain.ts +0 -91
  158. package/src/hooks/useWalletProvider.ts +0 -206
  159. package/src/hooks/useXAccount.ts +0 -51
  160. package/src/hooks/useXAccounts.ts +0 -56
  161. package/src/hooks/useXBalances.ts +0 -65
  162. package/src/hooks/useXConnect.ts +0 -118
  163. package/src/hooks/useXConnection.ts +0 -72
  164. package/src/hooks/useXConnectors.ts +0 -72
  165. package/src/hooks/useXDisconnect.ts +0 -73
  166. package/src/hooks/useXService.ts +0 -8
  167. package/src/hooks/useXSignMessage.ts +0 -82
  168. package/src/index.ts +0 -19
  169. package/src/types/index.ts +0 -22
  170. package/src/useXWagmiStore.ts +0 -116
  171. package/src/utils/index.ts +0 -21
  172. package/src/xchains/bitcoin/BitcoinXConnector.ts +0 -34
  173. package/src/xchains/bitcoin/BitcoinXService.ts +0 -40
  174. package/src/xchains/bitcoin/OKXXConnector.ts +0 -117
  175. package/src/xchains/bitcoin/UnisatXConnector.ts +0 -117
  176. package/src/xchains/bitcoin/XverseXConnector.ts +0 -232
  177. package/src/xchains/bitcoin/index.ts +0 -7
  178. package/src/xchains/bitcoin/useBitcoinXConnectors.ts +0 -14
  179. package/src/xchains/evm/EvmXConnector.ts +0 -27
  180. package/src/xchains/evm/EvmXService.ts +0 -211
  181. package/src/xchains/evm/index.ts +0 -3
  182. package/src/xchains/icon/IconHanaXConnector.ts +0 -39
  183. package/src/xchains/icon/IconXService.ts +0 -117
  184. package/src/xchains/icon/actions.ts +0 -28
  185. package/src/xchains/icon/iconex/index.tsx +0 -46
  186. package/src/xchains/icon/index.ts +0 -2
  187. package/src/xchains/injective/InjectiveXConnector.ts +0 -60
  188. package/src/xchains/injective/InjectiveXService.ts +0 -62
  189. package/src/xchains/injective/actions.ts +0 -32
  190. package/src/xchains/injective/index.ts +0 -2
  191. package/src/xchains/near/NearXConnector.ts +0 -42
  192. package/src/xchains/near/NearXService.ts +0 -46
  193. package/src/xchains/near/useNearXConnectors.ts +0 -23
  194. package/src/xchains/solana/SolanaXConnector.ts +0 -26
  195. package/src/xchains/solana/SolanaXService.ts +0 -46
  196. package/src/xchains/solana/index.ts +0 -2
  197. package/src/xchains/stacks/StacksXConnector.ts +0 -63
  198. package/src/xchains/stacks/StacksXService.ts +0 -59
  199. package/src/xchains/stacks/constants.ts +0 -42
  200. package/src/xchains/stacks/index.ts +0 -4
  201. package/src/xchains/stacks/useStacksXConnectors.ts +0 -7
  202. package/src/xchains/stellar/CustomSorobanServer.ts +0 -93
  203. package/src/xchains/stellar/StellarWalletsKitXConnector.ts +0 -53
  204. package/src/xchains/stellar/StellarXService.ts +0 -93
  205. package/src/xchains/stellar/actions.ts +0 -24
  206. package/src/xchains/stellar/index.tsx +0 -2
  207. package/src/xchains/stellar/useStellarXConnectors.ts +0 -21
  208. package/src/xchains/stellar/utils.ts +0 -49
  209. package/src/xchains/sui/SuiXConnector.ts +0 -28
  210. package/src/xchains/sui/SuiXService.ts +0 -66
  211. package/src/xchains/sui/index.ts +0 -2
@@ -0,0 +1,216 @@
1
+ # Chain Detection
2
+
3
+ Aggregate views over the wallet store — what's enabled, what's connected, what's installed. Use these hooks to render chain pickers, "manage connections" panels, and install CTAs without manually walking `xConnections` / `xConnectorsByChain`.
4
+
5
+ EVM **collapses to a single group / single row** in these views — wagmi maintains one connection across every configured EVM network, so reporting per-network rows would misrepresent the actual connection topology.
6
+
7
+ ## Table of contents
8
+
9
+ 1. [`useEnabledChains` — what's mounted](#useenabledchains--whats-mounted)
10
+ 2. [`useChainGroups` — picker model](#usechaingroups--picker-model)
11
+ 3. [`useConnectedChains` — connected list with hydration gate](#useconnectedchains--connected-list-with-hydration-gate)
12
+ 4. [`useIsWalletInstalled` — install detection](#useiswalletinstalled--install-detection)
13
+ 5. [Hydration status — gating reload flicker](#hydration-status--gating-reload-flicker)
14
+ 6. [Display ordering](#display-ordering)
15
+
16
+ ---
17
+
18
+ ## `useEnabledChains` — what's mounted
19
+
20
+ Returns the list of chain types currently enabled in `SodaxWalletProvider` config:
21
+
22
+ ```typescript
23
+ import { useEnabledChains } from '@sodax/wallet-sdk-react';
24
+
25
+ const enabled = useEnabledChains();
26
+ // e.g. ['EVM', 'SOLANA', 'BITCOIN']
27
+ ```
28
+
29
+ Source: the `enabledChains` slice of the Zustand store, populated by `initChainServices` from your `SodaxWalletConfig`. Reflects the **slot keys** in config (`config.EVM`, `config.SOLANA`, …), not which chains have a wallet connected.
30
+
31
+ Use cases:
32
+ - Render only chain rows the dApp opted into.
33
+ - Cross-reference with `useXConnections()` to compute "of N enabled chains, M are connected".
34
+ - Drive `<Tabs>` / `<Select>` UIs without hard-coding a list.
35
+
36
+ `useChainGroups` and `useConnectedChains` both already filter by `useEnabledChains` internally — reach for `useEnabledChains` directly only when you need the raw list.
37
+
38
+ ---
39
+
40
+ ## `useChainGroups` — picker model
41
+
42
+ Returns one `ChainGroup` per enabled chain type, with display metadata + connection status. Designed for chain-picker UIs (the "select a chain" step in [`useWalletModal`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/WALLET_MODAL.md)).
43
+
44
+ ```tsx
45
+ import { useChainGroups } from '@sodax/wallet-sdk-react';
46
+
47
+ function ChainPicker({ onPick }: { onPick: (chainType: ChainType) => void }) {
48
+ const groups = useChainGroups();
49
+
50
+ return groups.map(group => (
51
+ <button key={group.chainType} onClick={() => onPick(group.chainType)}>
52
+ {group.iconUrl && <img src={group.iconUrl} alt="" width={24} height={24} />}
53
+ <span>{group.displayName}</span>
54
+ {group.isConnected && <Badge>Connected</Badge>}
55
+ </button>
56
+ ));
57
+ }
58
+ ```
59
+
60
+ ### `ChainGroup` shape
61
+
62
+ | Field | Type | Source |
63
+ |-------|------|--------|
64
+ | `chainType` | `ChainType` | The slot key (`'EVM'`, `'SOLANA'`, …) |
65
+ | `chainIds` | `readonly SpokeChainKey[]` | All chain keys sharing this `chainType` (e.g. all 12 EVM `ChainKeys.*` for `'EVM'`) |
66
+ | `displayName` | `string` | From `chainRegistry[chainType].displayName`, fallback to `chainType` |
67
+ | `iconUrl` | `string \| undefined` | From `chainRegistry`. `undefined` = SDK doesn't ship one — provide your own |
68
+ | `isConnected` | `boolean` | `true` when `xConnections[chainType].xAccount.address` is set |
69
+ | `account` | `XAccount \| undefined` | Connected account (or `undefined`) |
70
+ | `connectorId` | `string \| undefined` | Active connector id when connected |
71
+
72
+ ### EVM collapses
73
+
74
+ EVM's `chainIds` lists every configured EVM `ChainKey`, but the group itself is **one row**. wagmi maintains a single connection across all those networks — there's no "per-network connection state" to render. If a user needs to switch the active EVM network, that's [`useEvmSwitchChain`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/EVM_SWITCH_CHAIN.md), not a separate group.
75
+
76
+ ### Custom display order
77
+
78
+ ```typescript
79
+ import { useChainGroups } from '@sodax/wallet-sdk-react';
80
+ import type { ChainType } from '@sodax/types';
81
+
82
+ const ORDER: readonly ChainType[] = ['EVM', 'ICON', 'SOLANA', 'SUI'];
83
+ const groups = useChainGroups({ order: ORDER });
84
+ // EVM first, then ICON, then SOLANA, then SUI; chains not in ORDER fall to the bottom alphabetically.
85
+ ```
86
+
87
+ Without `order`, groups follow `enabledChains` insertion order (driven by `SodaxWalletProvider` config object key order — not stable across reloads in some bundlers). Pass `order` for deterministic UIs.
88
+
89
+ ---
90
+
91
+ ## `useConnectedChains` — connected list with hydration gate
92
+
93
+ Returns one entry per **currently-connected** chain (skipping the rest), with enriched connector metadata (name + icon) for "manage connections" UIs and status badges.
94
+
95
+ ```tsx
96
+ import { useConnectedChains } from '@sodax/wallet-sdk-react';
97
+
98
+ function ConnectionList() {
99
+ const { chains, total, status } = useConnectedChains();
100
+
101
+ if (status === 'loading') return <Skeleton />;
102
+ if (total === 0) return <ConnectCta />;
103
+
104
+ return (
105
+ <ul>
106
+ {chains.map(chain => (
107
+ <li key={chain.chainType}>
108
+ {chain.connectorIcon && <img src={chain.connectorIcon} alt="" />}
109
+ <span>{chain.connectorName ?? chain.connectorId}</span>
110
+ <code>{chain.account.address}</code>
111
+ </li>
112
+ ))}
113
+ </ul>
114
+ );
115
+ }
116
+ ```
117
+
118
+ ### `ConnectedChain` shape
119
+
120
+ | Field | Type | Source |
121
+ |-------|------|--------|
122
+ | `chainType` | `ChainType` | |
123
+ | `account` | `XAccount` | Always populated (only included when address is non-empty) |
124
+ | `connectorId` | `string` | The persisted active connector |
125
+ | `connectorName` | `string \| undefined` | Looked up in `xConnectorsByChain` — `undefined` if connector list hasn't been registered yet |
126
+ | `connectorIcon` | `string \| undefined` | |
127
+
128
+ ### Result shape
129
+
130
+ ```typescript
131
+ type UseConnectedChainsResult = {
132
+ chains: ConnectedChain[];
133
+ total: number;
134
+ status: 'loading' | 'ready';
135
+ };
136
+ ```
137
+
138
+ `total` is `chains.length` — there for ergonomics in conditional rendering.
139
+
140
+ ---
141
+
142
+ ## `useIsWalletInstalled` — install detection
143
+
144
+ Read hook that pairs with the [batch operation](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/BATCH_OPERATIONS.md) hooks. Use it to gate "Connect" buttons on actual installation:
145
+
146
+ ```typescript
147
+ import { useIsWalletInstalled } from '@sodax/wallet-sdk-react';
148
+
149
+ // True if any Hana variant is installed (matches across all enabled chains)
150
+ const hasHana = useIsWalletInstalled({ connectors: ['hana'] });
151
+
152
+ // True if any wallet is installed for Bitcoin specifically
153
+ const hasBitcoinWallet = useIsWalletInstalled({ chainType: 'BITCOIN' });
154
+
155
+ // AND — Hana specifically on EVM
156
+ const hanaOnEvm = useIsWalletInstalled({ connectors: ['hana'], chainType: 'EVM' });
157
+ ```
158
+
159
+ Filters AND together. The type union enforces at compile time that **at least one of `connectors` / `chainType`** is present — `useIsWalletInstalled({})` is a type error. At runtime, bypassing the type union returns `false` plus a one-time warning (better than a render-tree crash).
160
+
161
+ `connectors: []` is explicit "match nothing" — returns `false`.
162
+
163
+ See [Identifier matching](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/BATCH_OPERATIONS.md#identifier-matching) for the substring-match rules.
164
+
165
+ ---
166
+
167
+ ## Hydration status — gating reload flicker
168
+
169
+ `useConnectedChains` exposes `status: 'loading' | 'ready'`. Use it to avoid the "Connect wallet" → "Connected" flash on page reload while Zustand rehydrates from `localStorage`:
170
+
171
+ ```tsx
172
+ const { chains, status } = useConnectedChains();
173
+
174
+ // ❌ Flicker — `chains` is empty for one render before hydration completes
175
+ return chains.length >= 1 ? <Connected /> : <ConnectCta />;
176
+
177
+ // ✅ No flicker — wait for hydration before deciding
178
+ return status === 'loading'
179
+ ? <Skeleton />
180
+ : chains.length >= 1 ? <Connected /> : <ConnectCta />;
181
+ ```
182
+
183
+ The flag tracks `useXWalletStore.persist.hasHydrated()` via `useSyncExternalStore`. `useChainGroups` does not expose this flag — its outputs are stable across hydration because the connection-status fields (`isConnected`, `account`) start as `false` / `undefined` and gain values atomically when the persist middleware finishes.
184
+
185
+ For first-paint correctness in SSR (Next.js), prefer `useConnectedChains.status` over an ad-hoc `useEffect(() => setMounted(true), [])` pattern — it's the official hydration signal.
186
+
187
+ ---
188
+
189
+ ## Display ordering
190
+
191
+ Both `useChainGroups` and `useConnectedChains` accept an `order?: readonly ChainType[]` option. Behavior:
192
+
193
+ 1. Chains in the array render in array order.
194
+ 2. Chains **not** in the array fall to the bottom, **sorted alphabetically among themselves**.
195
+ 3. Without `order`:
196
+ - `useChainGroups` follows `enabledChains` insertion order (driven by config key order).
197
+ - `useConnectedChains` follows the canonical `ChainTypeArr` order from `@sodax/types` — stable across reloads.
198
+
199
+ The compare function lives in [`utils/chainOrder.ts`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/src/utils/chainOrder.ts).
200
+
201
+ ```typescript
202
+ const groups = useChainGroups({ order: ['EVM', 'ICON'] });
203
+ // EVM → ICON → (alphabetical: BITCOIN, INJECTIVE, NEAR, SOLANA, STACKS, STELLAR, SUI)
204
+ ```
205
+
206
+ For custom-stable UIs (e.g. a header chain list that must not reflow on reload), always pass `order`.
207
+
208
+ ---
209
+
210
+ ## Related docs
211
+
212
+ - [Configure SodaxWalletProvider](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONFIGURE_PROVIDER.md) — which slots show up in `useEnabledChains`
213
+ - [Connect Flow](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECT_FLOW.md) — populates `xConnections` consumed here
214
+ - [Wallet Modal](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/WALLET_MODAL.md) — drives chain picker from `useChainGroups`
215
+ - [Batch Operations](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/BATCH_OPERATIONS.md) — `useIsWalletInstalled` shares the same identifier matcher
216
+ - [EVM Switch Chain](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/EVM_SWITCH_CHAIN.md) — the per-network EVM control absent from `useChainGroups`
@@ -0,0 +1,360 @@
1
+ # Configure SodaxWalletProvider
2
+
3
+ Learn how to configure `<SodaxWalletProvider>` for your dApp. The provider is the root component for wallet connectivity — it mounts only the chain-type adapters you opt into, holds per-chain RPC + wallet defaults, and bridges to `@sodax/wallet-sdk-core` so SDK calls receive a typed wallet provider.
4
+
5
+ The canonical TypeScript shape is [`SodaxWalletConfig`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/src/types/config.ts) in `@sodax/wallet-sdk-react`.
6
+
7
+ ## Table of contents
8
+
9
+ 1. [Quick start — minimal config](#quick-start--minimal-config)
10
+ 2. [`SodaxWalletConfig` overview](#sodaxwalletconfig-overview)
11
+ 3. [Chain-type slots — opt in by presence](#chain-type-slots--opt-in-by-presence)
12
+ 4. [Per-chain entries (`chains[ChainKey]`)](#per-chain-entries-chainschainkey)
13
+ 5. [Per-chain wallet defaults](#per-chain-wallet-defaults)
14
+ 6. [WalletConnect (EVM only)](#walletconnect-evm-only)
15
+ 7. [Config is captured once on mount](#config-is-captured-once-on-mount)
16
+ 8. [Single source of truth — `ChainMeta`](#single-source-of-truth--chainmeta)
17
+ 9. [Breaking changes from v1](#breaking-changes-from-v1)
18
+
19
+ ---
20
+
21
+ ## Quick start — minimal config
22
+
23
+ Mount `<SodaxWalletProvider>` inside `<QueryClientProvider>` with the chain-type slots your dApp needs. Omit any slot you don't need — its native adapter (wagmi, `@solana/wallet-adapter`, `@mysten/dapp-kit`) won't be mounted.
24
+
25
+ ```tsx
26
+ import { SodaxWalletProvider, type SodaxWalletConfig } from '@sodax/wallet-sdk-react';
27
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
28
+ import { ChainKeys } from '@sodax/types';
29
+
30
+ const queryClient = new QueryClient();
31
+
32
+ const walletConfig: SodaxWalletConfig = {
33
+ EVM: {
34
+ ssr: true,
35
+ chains: {
36
+ [ChainKeys.SONIC_MAINNET]: { rpcUrl: 'https://rpc.soniclabs.com' },
37
+ [ChainKeys.ETHEREUM_MAINNET]: { rpcUrl: 'https://ethereum-rpc.publicnode.com' },
38
+ },
39
+ },
40
+ SOLANA: {
41
+ chains: { [ChainKeys.SOLANA_MAINNET]: { rpcUrl: 'https://solana-mainnet.g.alchemy.com/v2/<KEY>' } },
42
+ },
43
+ BITCOIN: {}, // mount with SDK defaults
44
+ };
45
+
46
+ export function App({ children }: { children: React.ReactNode }) {
47
+ return (
48
+ <QueryClientProvider client={queryClient}>
49
+ <SodaxWalletProvider config={walletConfig}>{children}</SodaxWalletProvider>
50
+ </QueryClientProvider>
51
+ );
52
+ }
53
+ ```
54
+
55
+ `SodaxWalletProvider` mounts the EVM (wagmi), Solana (`@solana/wallet-adapter-react`), and Sui (`@mysten/dapp-kit`) React providers conditionally based on which slots are present, then registers chain services for non-provider chains (Bitcoin, ICON, Injective, Stellar, NEAR, Stacks).
56
+
57
+ ---
58
+
59
+ ## `SodaxWalletConfig` overview
60
+
61
+ Top-level keys are `ChainType` strings — one slot per chain family. **Every slot is optional**. Omitting a slot skips mounting that adapter; passing `{}` mounts it with SDK defaults.
62
+
63
+ | Key | Mounts | Adapter fields | Per-chain entries |
64
+ |-----|--------|----------------|-------------------|
65
+ | `EVM` | wagmi (12 EVM chains) | `ssr`, `reconnectOnMount`, `initialState`, `walletConnect` | `{ rpcUrl?, defaults? }` per `EvmChainKey` |
66
+ | `SOLANA` | `@solana/wallet-adapter-react` | `autoConnect` | `{ rpcUrl?, defaults? }` per `SolanaChainKey` |
67
+ | `SUI` | `@mysten/dapp-kit` | `autoConnect`, `network` | `{ rpcUrl?, defaults? }` per `SuiChainKey` |
68
+ | `ICON` | (no React adapter) | — | `{ rpcUrl?, defaults? }` per `IconChainKey` |
69
+ | `NEAR` | (no React adapter) | — | `{ rpcUrl?, defaults? }` per `NearChainKey` |
70
+ | `STELLAR` | (no React adapter) | — | `StellarRpcConfig & { defaults? }` per `StellarChainKey` |
71
+ | `BITCOIN` | (no React adapter) | — | `BitcoinRpcConfig & { defaults? }` per `BitcoinChainKey` |
72
+ | `INJECTIVE` | (no React adapter) | — | `InjectiveRpcConfig & { defaults? }` per `InjectiveChainKey` |
73
+ | `STACKS` | (no React adapter) | — | `StacksNetworkName \| (StacksNetworkLike & { defaults? })` |
74
+
75
+ **Provider-managed vs non-provider** — EVM, Solana, and Sui need React context providers from their native SDKs (Hydrator components sync state into the Zustand store). The remaining six chains use direct browser-extension APIs and skip the React adapter layer; their actions are registered during `initChainServices()` after the provider mounts.
76
+
77
+ Each slot also accepts an optional `connectors?: IXConnector[]` array to override the default connectors registered by `chainRegistry`.
78
+
79
+ ---
80
+
81
+ ## Chain-type slots — opt in by presence
82
+
83
+ The slot's mere presence enables the chain type. Adapter fields and per-chain entries are independent of each other — set whichever you need.
84
+
85
+ ```typescript
86
+ const walletConfig: SodaxWalletConfig = {
87
+ // Adapter fields only — wagmi mounts with the bundled chain set, no custom RPCs
88
+ EVM: { ssr: true },
89
+
90
+ // Per-chain entries only — wagmi adapter uses defaults
91
+ SOLANA: { chains: { [ChainKeys.SOLANA_MAINNET]: { rpcUrl: 'https://...' } } },
92
+
93
+ // Both
94
+ SUI: {
95
+ network: 'mainnet',
96
+ autoConnect: true,
97
+ chains: { [ChainKeys.SUI_MAINNET]: { rpcUrl: 'https://fullnode.mainnet.sui.io' } },
98
+ },
99
+
100
+ // Empty object — opt in with SDK defaults
101
+ BITCOIN: {},
102
+ };
103
+ ```
104
+
105
+ To **disable** a chain type, omit the slot entirely. `useEnabledChains()` reads back the slots that were set, and hooks like `useWalletProvider({ xChainType: 'EVM' })` return `undefined` for disabled chains (with a one-time console warning).
106
+
107
+ ---
108
+
109
+ ## Per-chain entries (`chains[ChainKey]`)
110
+
111
+ Each slot's `chains` field is keyed by `ChainKey` constants. The entry shape varies by chain family:
112
+
113
+ ### Simple chains — `{ rpcUrl?, defaults? }`
114
+
115
+ EVM, Solana, Sui, ICON, and NEAR share the simple shape — single RPC URL plus optional wallet provider defaults.
116
+
117
+ ```typescript
118
+ import { ChainKeys } from '@sodax/types';
119
+
120
+ const walletConfig: SodaxWalletConfig = {
121
+ EVM: {
122
+ chains: {
123
+ [ChainKeys.ARBITRUM_MAINNET]: {
124
+ rpcUrl: 'https://arb1.arbitrum.io/rpc',
125
+ defaults: { waitForTransactionReceipt: { confirmations: 1 } },
126
+ },
127
+ [ChainKeys.BASE_MAINNET]: { rpcUrl: 'https://base.drpc.org' },
128
+ },
129
+ },
130
+ ICON: {
131
+ chains: { [ChainKeys.ICON_MAINNET]: { rpcUrl: 'https://ctz.solidwallet.io/api/v3' } },
132
+ },
133
+ };
134
+ ```
135
+
136
+ ### Multi-field RPC — Stellar, Bitcoin, Injective
137
+
138
+ Stellar (Horizon + Soroban), Bitcoin (RPC + Radfi indexer), and Injective (gRPC + indexer) extend their existing `*RpcConfig` types from `@sodax/types`. Mirror the full shape:
139
+
140
+ ```typescript
141
+ import { ChainKeys } from '@sodax/types';
142
+
143
+ const walletConfig: SodaxWalletConfig = {
144
+ STELLAR: {
145
+ chains: {
146
+ [ChainKeys.STELLAR_MAINNET]: {
147
+ horizonRpcUrl: 'https://horizon.stellar.org',
148
+ sorobanRpcUrl: 'https://rpc.ankr.com/stellar_soroban',
149
+ defaults: { pollInterval: 1_000 },
150
+ },
151
+ },
152
+ },
153
+ BITCOIN: {
154
+ chains: {
155
+ [ChainKeys.BITCOIN_MAINNET]: {
156
+ // BitcoinRpcConfig fields + defaults
157
+ defaults: { defaultFinalize: true },
158
+ },
159
+ },
160
+ },
161
+ };
162
+ ```
163
+
164
+ ### Stacks — preset name OR network object
165
+
166
+ Stacks accepts either a preset name string (`'mainnet' | 'testnet'`) or a full `StacksNetworkLike` object:
167
+
168
+ ```typescript
169
+ const walletConfig: SodaxWalletConfig = {
170
+ STACKS: {
171
+ chains: {
172
+ [ChainKeys.STACKS_MAINNET]: 'mainnet', // preset
173
+ },
174
+ },
175
+ };
176
+
177
+ // Or with full network object:
178
+ const advanced: SodaxWalletConfig = {
179
+ STACKS: {
180
+ chains: {
181
+ [ChainKeys.STACKS_MAINNET]: {
182
+ // StacksNetworkLike fields...
183
+ defaults: { network: 'mainnet', postConditionMode: 'deny' },
184
+ },
185
+ },
186
+ },
187
+ };
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Per-chain wallet defaults
193
+
194
+ The `defaults` field on each chain entry forwards directly to `wallet-sdk-core`'s provider classes — these are the per-method defaults applied when the SDK calls `walletProvider.sendTransaction(...)` etc.
195
+
196
+ | Slot | `defaults` shape |
197
+ |------|------------------|
198
+ | `EVM` | `EvmWalletDefaults` — `sendTransaction`, `waitForTransactionReceipt`, `publicClient`, `walletClient`, `transport` |
199
+ | `SOLANA` | `SolanaWalletDefaults` — `connectionCommitment`, `connectionConfig`, `sendOptions`, `confirmCommitment` |
200
+ | `SUI` | `SuiWalletDefaults` — `signAndExecuteTxn`, `getCoins` |
201
+ | `ICON` | `IconWalletDefaults` — `stepLimit`, `version`, `timestampProvider`, `jsonRpcId` |
202
+ | `INJECTIVE` | `InjectiveWalletDefaults` — `defaultFunds`, `defaultMemo`, `sequence`, `accountNumber` |
203
+ | `STELLAR` | `StellarWalletDefaults` — `pollInterval`, `pollTimeout`, `networkPassphrase` |
204
+ | `STACKS` | `StacksWalletDefaults` — `network`, `postConditionMode` |
205
+ | `BITCOIN` | `BitcoinWalletDefaults` — `defaultFinalize` |
206
+ | `NEAR` | `NearWalletDefaults` — `throwOnFailure`, `waitUntil`, `gasDefault`, `depositDefault` |
207
+
208
+ Defaults merge **shallowly** — top-level keys only. Nested objects (e.g. `sendTransaction: { gas, maxFeePerGas }`) are replaced wholesale, not deep-merged. See [`packages/sdk/docs/WALLET_PROVIDERS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/WALLET_PROVIDERS.md) for full per-chain config reference.
209
+
210
+ ---
211
+
212
+ ## WalletConnect (EVM only)
213
+
214
+ Default EVM discovery uses [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963) — only browser-extension wallets. Partners using enterprise custody (Fireblocks, Ledger, etc.) cannot install browser extensions and need WalletConnect protocol.
215
+
216
+ The `walletConnect` field on the `EVM` slot extends wagmi's `WalletConnectParameters` directly — every wagmi option is available:
217
+
218
+ ```typescript
219
+ const walletConfig: SodaxWalletConfig = {
220
+ EVM: {
221
+ ssr: true,
222
+ chains: { [ChainKeys.SONIC_MAINNET]: { rpcUrl: 'https://rpc.soniclabs.com' } },
223
+ walletConnect: {
224
+ projectId: '<your-walletconnect-cloud-project-id>',
225
+ // showQrModal, isNewChainsStale, qrModalOptions, etc.
226
+ },
227
+ },
228
+ };
229
+ ```
230
+
231
+ When `walletConnect` is provided, a WalletConnect connector is added to the wagmi config and `EvmHydrator` discovers it automatically — no UI changes needed.
232
+
233
+ **Restrict modal to specific wallets** — pass `qrModalOptions` to filter the WalletConnect Explorer list:
234
+
235
+ ```typescript
236
+ walletConnect: {
237
+ projectId: '...',
238
+ qrModalOptions: {
239
+ explorerRecommendedWalletIds: ['<fireblocks-wallet-id>'],
240
+ explorerExcludedWalletIds: 'ALL', // hides everything except recommended
241
+ },
242
+ }
243
+ ```
244
+
245
+ If `projectId` is missing, the WalletConnect connector is silently skipped and a warning is logged. See [`WALLETCONNECT.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/WALLETCONNECT.md) for the partner integration guide.
246
+
247
+ ---
248
+
249
+ ## Config is captured once on mount
250
+
251
+ `SodaxWalletProvider` freezes the `config` prop on the **first render** via `useRef`. Subsequent re-renders with a new reference have **no effect** on the underlying providers, store, or wagmi config:
252
+
253
+ ```tsx
254
+ // ❌ Dynamic config — RPC change is ignored after first render
255
+ const walletConfig: SodaxWalletConfig = useMemo(() => ({
256
+ EVM: { chains: { [ChainKeys.BSC_MAINNET]: { rpcUrl: dynamicRpc } } },
257
+ }), [dynamicRpc]);
258
+
259
+ return <SodaxWalletProvider config={walletConfig}>{children}</SodaxWalletProvider>;
260
+ ```
261
+
262
+ To swap config at runtime, **remount** the provider with a new `key`:
263
+
264
+ ```tsx
265
+ return (
266
+ <SodaxWalletProvider key={configVersion} config={walletConfig}>
267
+ {children}
268
+ </SodaxWalletProvider>
269
+ );
270
+ ```
271
+
272
+ This avoids subtle bugs where Zustand persistence, wagmi reconnect, and Hydrator state-syncing diverge from a mid-flight config change.
273
+
274
+ ---
275
+
276
+ ## Single source of truth — `ChainMeta`
277
+
278
+ When adding a new chain type to the package, the only file you edit is [`ChainMeta`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/src/types/config.ts):
279
+
280
+ ```typescript
281
+ export type ChainMeta = {
282
+ EVM: { keys: EvmChainKey; entry: EvmChainEntry; defaults: EvmWalletDefaults; adapter: EvmAdapterFields };
283
+ // ... one entry per ChainType
284
+ };
285
+ ```
286
+
287
+ `SodaxWalletConfig`, `ChainTypeConfig<T>`, `ChainEntry<K>`, `WalletDefaultsByKey<K>` all derive automatically from `ChainMeta`. See [`ADDING_A_NEW_CHAIN.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/ADDING_A_NEW_CHAIN.md) for the full chain-onboarding workflow.
288
+
289
+ ---
290
+
291
+ ## Breaking changes from v1
292
+
293
+ The v2 config is **not backward-compatible** with v1's flat shape. If you're upgrading:
294
+
295
+ ### `rpcConfig` removed
296
+
297
+ ```tsx
298
+ // ❌ v1 — flat per-chain RPC map
299
+ <SodaxWalletProvider rpcConfig={{
300
+ sonic: 'https://rpc.soniclabs.com',
301
+ '0x38.bsc': 'https://bsc-dataseed1.binance.org',
302
+ solana: 'https://...',
303
+ }}>
304
+
305
+ // ✅ v2 — chain-type slots with nested per-chain entries
306
+ <SodaxWalletProvider config={{
307
+ EVM: {
308
+ chains: {
309
+ [ChainKeys.SONIC_MAINNET]: { rpcUrl: 'https://rpc.soniclabs.com' },
310
+ [ChainKeys.BSC_MAINNET]: { rpcUrl: 'https://bsc-dataseed1.binance.org' },
311
+ },
312
+ },
313
+ SOLANA: { chains: { [ChainKeys.SOLANA_MAINNET]: { rpcUrl: 'https://...' } } },
314
+ }}>
315
+ ```
316
+
317
+ ### `options` removed — fields moved to slot adapter fields
318
+
319
+ | v1 prop | v2 location |
320
+ |---------|-------------|
321
+ | `options.ssr` | `config.EVM.ssr` |
322
+ | `options.reconnectOnMount` | `config.EVM.reconnectOnMount` |
323
+ | `options.solanaAutoConnect` | `config.SOLANA.autoConnect` |
324
+ | `options.suiAutoConnect` | `config.SUI.autoConnect` |
325
+ | `options.suiNetwork` | `config.SUI.network` |
326
+ | `options.walletConnect` | `config.EVM.walletConnect` |
327
+
328
+ ### `initialState` removed — moved to slot
329
+
330
+ ```tsx
331
+ // ❌ v1
332
+ <SodaxWalletProvider rpcConfig={...} initialState={wagmiInitialState}>
333
+
334
+ // ✅ v2
335
+ <SodaxWalletProvider config={{ EVM: { initialState: wagmiInitialState, ... } }}>
336
+ ```
337
+
338
+ ### `chains: { EVM, SOLANA, ... }` wrapper removed
339
+
340
+ ```tsx
341
+ // ❌ v1
342
+ <SodaxWalletProvider config={{ chains: { EVM: { ... }, SOLANA: { ... } } }}>
343
+
344
+ // ✅ v2 — chain-type slots are top-level
345
+ <SodaxWalletProvider config={{ EVM: { ... }, SOLANA: { ... } }}>
346
+ ```
347
+
348
+ ### Persisted `xConnections` for now-disabled chains are cleaned up
349
+
350
+ If a previous session connected a chain that is no longer in `config`, the persisted connection in `localStorage` (key: `xwagmi-store`) is removed automatically by `cleanupDisabledConnections()` after persist hydration. No consumer action required.
351
+
352
+ ---
353
+
354
+ ## Related docs
355
+
356
+ - [Connect Flow](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECT_FLOW.md) — discover connectors, connect, read account, disconnect
357
+ - [Wallet Provider Bridge](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/WALLET_PROVIDER_BRIDGE.md) — `useWalletProvider` → typed `IXxxWalletProvider` for SDK calls
358
+ - [WalletConnect](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/WALLETCONNECT.md) — enterprise/custody wallet setup (Fireblocks, etc.)
359
+ - [Adding a New Chain](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/ADDING_A_NEW_CHAIN.md) — `ChainMeta` extension and chain registry
360
+ - [SDK Wallet Providers Reference](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/WALLET_PROVIDERS.md) — per-chain `defaults` shape reference