@sodax/wallet-sdk-react 1.5.6-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,226 @@
1
+ # Wallet Provider Bridge
2
+
3
+ `@sodax/wallet-sdk-react` is the bridge between the connected browser wallet and the chain-agnostic SDK call surface in `@sodax/sdk`. After a user connects a wallet, `useWalletProvider` returns a typed `IXxxWalletProvider` (from `@sodax/sdk`) that you pass directly into any SDK method — the SDK signs and broadcasts via that provider.
4
+
5
+ The canonical interfaces are defined in [`@sodax/sdk`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/src/index.ts) (`IEvmWalletProvider`, `ISolanaWalletProvider`, …) and re-exported through `@sodax/wallet-sdk-core`.
6
+
7
+ ## Table of contents
8
+
9
+ 1. [Why a bridge layer](#why-a-bridge-layer)
10
+ 2. [`useWalletProvider` — typed provider for one chain](#usewalletprovider--typed-provider-for-one-chain)
11
+ 3. [End-to-end example](#end-to-end-example)
12
+ 4. [Service hooks (`useXService` / `useXServices`)](#service-hooks-usexservice--usexservices)
13
+ 5. [How wallet providers are populated](#how-wallet-providers-are-populated)
14
+ 6. [Disabled chains return `undefined`](#disabled-chains-return-undefined)
15
+ 7. [Bypassing the bridge — when to skip `useWalletProvider`](#bypassing-the-bridge--when-to-skip-usewalletprovider)
16
+
17
+ ---
18
+
19
+ ## Why a bridge layer
20
+
21
+ `@sodax/sdk` is wallet-library-agnostic — it accepts any object implementing the per-chain `IXxxWalletProvider` interface (see [`packages/sdk/docs/WALLET_PROVIDERS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/WALLET_PROVIDERS.md)). The implementation can come from:
22
+
23
+ - **Browser dApp** — `@sodax/wallet-sdk-react` Hydrators wrap `wagmi` / `@solana/wallet-adapter` / `@mysten/dapp-kit` etc. into provider instances and store them in the Zustand store. `useWalletProvider` reads them out.
24
+ - **Server / script / bot** — `@sodax/wallet-sdk-core` exposes the same provider classes (`EvmWalletProvider`, `SolanaWalletProvider`, …) constructed directly from a private key. No React, no wallet-sdk-react.
25
+
26
+ `useWalletProvider` is the React-side bridge. It hides the per-chain construction details and gives you a typed handle that fits the SDK call slot exactly:
27
+
28
+ ```typescript
29
+ // SDK call shape (signed mode)
30
+ sodax.swaps.swap({
31
+ params: { srcChainKey: ChainKeys.BSC_MAINNET, /* ... */ },
32
+ walletProvider, // must satisfy IEvmWalletProvider for BSC
33
+ });
34
+ ```
35
+
36
+ `useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET })` returns exactly `IEvmWalletProvider | undefined` — TypeScript narrows the return type from the chain key.
37
+
38
+ ---
39
+
40
+ ## `useWalletProvider` — typed provider for one chain
41
+
42
+ Two overloads, mutually exclusive: pass `xChainId` (a `SpokeChainKey`) **or** `xChainType` (a `ChainType`), never both.
43
+
44
+ ### By chain id — narrowest typing
45
+
46
+ ```typescript
47
+ import { useWalletProvider } from '@sodax/wallet-sdk-react';
48
+ import { ChainKeys } from '@sodax/types';
49
+
50
+ const walletProvider = useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET });
51
+ // walletProvider: IEvmWalletProvider | undefined
52
+ ```
53
+
54
+ The chain id (`BSC_MAINNET`, `SOLANA_MAINNET`, etc.) resolves to its family at compile time via `GetChainType<S>` and the return type is the matching `IXxxWalletProvider`.
55
+
56
+ ### By chain type — family-level typing
57
+
58
+ ```typescript
59
+ const evmProvider = useWalletProvider({ xChainType: 'EVM' });
60
+ // evmProvider: IEvmWalletProvider | undefined
61
+
62
+ const solProvider = useWalletProvider({ xChainType: 'SOLANA' });
63
+ // solProvider: ISolanaWalletProvider | undefined
64
+ ```
65
+
66
+ Use this when the surrounding component is family-level (e.g. an EVM dashboard that doesn't care which specific EVM chain is active). For EVM specifically, one wagmi connection covers all configured EVM networks — the same provider is returned for every `xChainId` in the EVM family.
67
+
68
+ ### No-arg form
69
+
70
+ ```typescript
71
+ const wp = useWalletProvider();
72
+ // wp: undefined — no chain specified
73
+ ```
74
+
75
+ Both fields are optional but at least one must be set for the hook to return anything.
76
+
77
+ ---
78
+
79
+ ## End-to-end example
80
+
81
+ Connect once, then drive an SDK call with the resulting provider:
82
+
83
+ ```tsx
84
+ import { useWalletProvider, useXAccount } from '@sodax/wallet-sdk-react';
85
+ import { useSodaxContext } from '@sodax/dapp-kit'; // or hold a Sodax instance directly
86
+ import { ChainKeys } from '@sodax/types';
87
+ import type { CreateIntentParams } from '@sodax/sdk';
88
+
89
+ function SwapButton({ params }: { params: CreateIntentParams<typeof ChainKeys.BSC_MAINNET> }) {
90
+ const walletProvider = useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET });
91
+ const account = useXAccount({ xChainId: ChainKeys.BSC_MAINNET });
92
+ const { sodax } = useSodaxContext();
93
+
94
+ const handleSwap = async () => {
95
+ if (!walletProvider) return;
96
+ const result = await sodax.swaps.swap({
97
+ params,
98
+ walletProvider, // typed as IEvmWalletProvider — matches BSC src chain
99
+ });
100
+ if (!result.ok) {
101
+ console.error('swap failed:', result.error);
102
+ return;
103
+ }
104
+ console.log('swap submitted:', result.value);
105
+ };
106
+
107
+ return (
108
+ <button onClick={handleSwap} disabled={!walletProvider || !account.address}>
109
+ Swap
110
+ </button>
111
+ );
112
+ }
113
+ ```
114
+
115
+ The same pattern works for every SDK feature service — `sodax.bridge.bridge`, `sodax.moneyMarket.supply`, `sodax.staking.stake`, `sodax.dex.deposit`, etc. See [`packages/sdk/docs/`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/) for per-feature method signatures.
116
+
117
+ ---
118
+
119
+ ## Service hooks (`useXService` / `useXServices`)
120
+
121
+ Lower-level than `useWalletProvider` — these expose the chain's `XService` instance, used for:
122
+
123
+ - Reading per-chain balances (`xService.getBalance(address, xToken)`)
124
+ - Listing connectors (`xService.getXConnectors()`)
125
+ - Looking up a connector by id (`xService.getXConnectorById(id)`)
126
+ - Custom integrations against the `IXService` contract
127
+
128
+ ```typescript
129
+ import { useXService, useXServices } from '@sodax/wallet-sdk-react';
130
+
131
+ const evmService = useXService({ xChainType: 'EVM' });
132
+ // evmService: XService | undefined — chain-specific instance (EvmXService)
133
+
134
+ const allServices = useXServices();
135
+ // allServices: Partial<Record<ChainType, XService>>
136
+ ```
137
+
138
+ For typed access, depend on the public [`IXService`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/src/types/interfaces.ts) interface rather than the concrete `XService` class. Concrete classes (`EvmXService`, `BitcoinXService`, …) are not exported from the package barrel; if you need a concrete class for `instanceof`, use the deep-import sub-path — see [`CONNECTORS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECTORS.md).
139
+
140
+ ---
141
+
142
+ ## How wallet providers are populated
143
+
144
+ The store's `walletProviders` map is populated by two distinct mechanisms depending on chain type:
145
+
146
+ ### Provider-managed chains (EVM, Solana, Sui)
147
+
148
+ The chain's **Hydrator** is the sole writer. It subscribes to the native SDK hooks (e.g. `useAccount` from wagmi) and writes a fresh `EvmWalletProvider` (from `@sodax/wallet-sdk-core`) into the store every time the underlying client changes:
149
+
150
+ ```
151
+ wagmi connection observed → EvmHydrator constructs EvmWalletProvider({ walletClient, publicClient })
152
+
153
+
154
+ store.walletProviders.EVM = provider
155
+ ```
156
+
157
+ `useWalletProvider({ xChainType: 'EVM' })` reads that slot — no chain-specific switch case in user code.
158
+
159
+ ### Non-provider chains (Bitcoin, ICON, Injective, Stellar, NEAR, Stacks)
160
+
161
+ The provider is created as a side-effect of `setXConnection()` inside the store. When `useXConnect` resolves a successful connection, the store's setter constructs the chain-specific provider (`BitcoinWalletProvider`, `IconWalletProvider`, …) and writes it to `walletProviders`.
162
+
163
+ In both cases, the bridge layer owns the construction — consumers never call `new EvmWalletProvider(...)` themselves in dApp code.
164
+
165
+ ---
166
+
167
+ ## Disabled chains return `undefined`
168
+
169
+ If `xChainType` resolves to a chain that isn't enabled in `SodaxWalletProvider` config, `useWalletProvider` returns `undefined` and logs a one-time warning per chain:
170
+
171
+ ```
172
+ [useWalletProvider] chain "BITCOIN" is not enabled in SodaxWalletProvider config.chains — returning undefined
173
+ ```
174
+
175
+ This is by design — `useWalletProvider` is meant to be called unconditionally inside components, and chains can be disabled without changing the call sites. Always null-check the return value:
176
+
177
+ ```typescript
178
+ const walletProvider = useWalletProvider({ xChainId: ChainKeys.BITCOIN_MAINNET });
179
+ if (!walletProvider) return null; // chain disabled, or no wallet connected for that chain yet
180
+ ```
181
+
182
+ The warning fires only once per chain per session — repeated disabled-chain reads don't spam the console.
183
+
184
+ ---
185
+
186
+ ## Bypassing the bridge — when to skip `useWalletProvider`
187
+
188
+ Skip the bridge in two cases:
189
+
190
+ **Server / Node.js scripts** — no React, no wallet-sdk-react. Use `@sodax/wallet-sdk-core` directly:
191
+
192
+ ```typescript
193
+ import { Sodax } from '@sodax/sdk';
194
+ import { EvmWalletProvider } from '@sodax/wallet-sdk-core';
195
+ import { ChainKeys } from '@sodax/types';
196
+
197
+ const sodax = new Sodax();
198
+ const walletProvider = new EvmWalletProvider({
199
+ privateKey: process.env.PRIVATE_KEY!,
200
+ chainId: ChainKeys.BSC_MAINNET,
201
+ rpcUrl: 'https://bsc-dataseed.binance.org',
202
+ });
203
+ const result = await sodax.swaps.swap({ params: /* ... */, walletProvider });
204
+ ```
205
+
206
+ **Raw transactions** — when you only need unsigned transaction data (for gas estimation, manual relay, or external signing). SDK methods that accept `raw: true` don't need a wallet provider:
207
+
208
+ ```typescript
209
+ const result = await sodax.swaps.createIntent({
210
+ params,
211
+ raw: true, // no walletProvider — returns unsigned tx
212
+ });
213
+ ```
214
+
215
+ See [`packages/sdk/docs/SWAPS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/SWAPS.md) for the full raw-vs-signed matrix per method.
216
+
217
+ ---
218
+
219
+ ## Related docs
220
+
221
+ - [Configure SodaxWalletProvider](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONFIGURE_PROVIDER.md) — chain-type slots and per-chain wallet defaults
222
+ - [Connect Flow](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECT_FLOW.md) — discover, connect, read, disconnect
223
+ - [Connectors](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECTORS.md) — `IXConnector`, deep imports, custom connectors
224
+ - [SDK Wallet Providers Reference](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/WALLET_PROVIDERS.md) — `IXxxWalletProvider` interfaces, custom implementations
225
+ - [SDK Swaps](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/SWAPS.md) — example consumer of a wallet provider
226
+ - [`@sodax/wallet-sdk-core`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-core/README.md) — Node-side provider construction
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sodax/wallet-sdk-react",
3
3
  "license": "MIT",
4
- "version": "1.5.6-beta",
4
+ "version": "2.0.0-rc.1",
5
5
  "description": "Wallet SDK of Sodax",
6
6
  "type": "module",
7
7
  "main": "./dist/index.cjs",
@@ -9,18 +9,33 @@
9
9
  "types": "./dist/index.d.ts",
10
10
  "files": [
11
11
  "dist",
12
- "src"
12
+ "README.md",
13
+ "docs",
14
+ "skills",
15
+ "ai-exported"
13
16
  ],
14
17
  "exports": {
15
18
  ".": {
16
19
  "types": "./dist/index.d.ts",
17
20
  "import": "./dist/index.mjs",
18
21
  "require": "./dist/index.cjs"
22
+ },
23
+ "./xchains/*": {
24
+ "types": "./dist/xchains/*/index.d.ts",
25
+ "import": "./dist/xchains/*/index.mjs",
26
+ "require": "./dist/xchains/*/index.cjs"
27
+ }
28
+ },
29
+ "typesVersions": {
30
+ "*": {
31
+ "xchains/*": [
32
+ "./dist/xchains/*/index.d.ts"
33
+ ]
19
34
  }
20
35
  },
21
36
  "repository": {
22
37
  "type": "git",
23
- "url": "https://github.com/icon-project/sodax-frontend"
38
+ "url": "https://github.com/icon-project/sodax-sdks"
24
39
  },
25
40
  "dependencies": {
26
41
  "@stacks/connect": "8.2.6",
@@ -43,7 +58,8 @@
43
58
  "@solana/wallet-adapter-react": "0.15.35",
44
59
  "@solana/wallet-adapter-wallets": "0.19.30",
45
60
  "@solana/web3.js": "1.98.0",
46
- "@stellar/stellar-sdk": "12.3.0",
61
+ "@stellar/stellar-sdk": "15.1.0",
62
+ "@walletconnect/ethereum-provider": "^2.23.9",
47
63
  "icon-sdk-js": "1.5.3",
48
64
  "immer": "10.1.1",
49
65
  "sats-connect": "^4.2.1",
@@ -51,15 +67,19 @@
51
67
  "wagmi": "2.16.9",
52
68
  "zustand": "4.5.2",
53
69
  "bs58": "6.0.0",
54
- "@sodax/types": "1.5.6-beta",
55
- "@sodax/wallet-sdk-core": "1.5.6-beta"
70
+ "@sodax/types": "2.0.0-rc.1",
71
+ "@sodax/wallet-sdk-core": "2.0.0-rc.1"
56
72
  },
57
73
  "devDependencies": {
74
+ "@testing-library/react": "^16.1.0",
58
75
  "@types/react": "^19.0.8",
76
+ "@types/react-dom": "^19.0.3",
77
+ "happy-dom": "^20.8.9",
59
78
  "knip": "5.30.5",
79
+ "react-dom": "19.1.4",
60
80
  "tsup": "8.5.0",
61
81
  "typescript": "5.5.4",
62
- "vitest": "^2.1.3"
82
+ "vitest": "2.1.9"
63
83
  },
64
84
  "peerDependencies": {
65
85
  "@tanstack/react-query": "5.x",
@@ -69,12 +89,17 @@
69
89
  "node": ">=18.0.0"
70
90
  },
71
91
  "scripts": {
72
- "build": "tsup",
92
+ "build": "NODE_OPTIONS=--max-old-space-size=8192 tsup",
73
93
  "dev": "tsup --watch ./src",
74
94
  "clean": "rm -rf dist && rm -rf node_modules && rm -rf .turbo",
75
95
  "pretty": "biome format . --write",
76
96
  "checkTs": "tsc --noEmit",
97
+ "checkTs:examples": "tsc --noEmit -p tsconfig.examples.json",
98
+ "test": "vitest run",
77
99
  "knip": "knip",
78
- "lint": "biome lint . --write"
100
+ "lint": "biome lint . --write",
101
+ "check:ai-exported": "bash ./scripts/check-ai-exported.sh",
102
+ "check:ai-links": "bash ./scripts/check-ai-links.sh",
103
+ "check:ai-imports": "bash ./scripts/check-ai-imports.sh"
79
104
  }
80
105
  }
@@ -0,0 +1,84 @@
1
+ # @sodax/wallet-sdk-react Skills
2
+
3
+ Scaffolding guides that let you wire SODAX wallet connectivity into a React app in one prompt. Built for and tested with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) — point it at a skill file and it generates the correct providers, hooks, and types.
4
+
5
+ ## Quick Start
6
+
7
+ Skills ship with the npm package. After installing `@sodax/wallet-sdk-react`:
8
+
9
+ **1. Set up providers** (do this first)
10
+
11
+ > Read `node_modules/@sodax/wallet-sdk-react/skills/setup.md` and wire `SodaxWalletProvider` into my app.
12
+
13
+ **2. Pick a connect UX**
14
+
15
+ > Read `node_modules/@sodax/wallet-sdk-react/skills/connect-button.md` and add a single-chain connect button.
16
+
17
+ > Read `node_modules/@sodax/wallet-sdk-react/skills/multi-chain-modal.md` and add a multi-chain wallet modal.
18
+
19
+ **3. Add advanced features as needed**
20
+
21
+ > Read `node_modules/@sodax/wallet-sdk-react/skills/evm-only-walletconnect.md` and enable WalletConnect for enterprise custody (Fireblocks, etc.).
22
+
23
+ > Read `node_modules/@sodax/wallet-sdk-react/skills/bridge-to-sdk.md` and pass the connected wallet provider to a `@sodax/sdk` swap call.
24
+
25
+ The pattern is always: `Read node_modules/@sodax/wallet-sdk-react/skills/<skill>.md` + what you want to build.
26
+
27
+ ### Tips
28
+
29
+ - One skill per prompt gets better results than asking for everything at once.
30
+ - Always do setup before any other skill.
31
+ - Pair `connect-button.md` (one chain at a time) OR `multi-chain-modal.md` (chain picker + connector picker) — they're alternatives, not additive.
32
+
33
+ ---
34
+
35
+ *Internal devs working in this monorepo: use `skills/<skill>.md` instead of the `node_modules` path, and reference sibling docs in `docs/` for the underlying API.*
36
+
37
+ ## Dependency Graph
38
+
39
+ ```
40
+ setup
41
+ ├── connect-button (single-chain connect/disconnect)
42
+ ├── multi-chain-modal (modal-driven multi-chain UX)
43
+ ├── evm-only-walletconnect (Fireblocks / custody opt-in)
44
+ └── bridge-to-sdk (pass walletProvider to @sodax/sdk calls)
45
+ ```
46
+
47
+ ## Skill Index
48
+
49
+ | Skill | File | Description | Depends On |
50
+ |-------|------|-------------|------------|
51
+ | Setup | [setup.md](setup.md) | Install + wire `SodaxWalletProvider` with chain-type slots | None |
52
+ | Connect Button | [connect-button.md](connect-button.md) | `useXConnectors` + `useXConnect` + `useXDisconnect` for one chain | `setup` |
53
+ | Multi-chain Modal | [multi-chain-modal.md](multi-chain-modal.md) | `useWalletModal` headless state machine + `useChainGroups` | `setup` |
54
+ | EVM-only WalletConnect | [evm-only-walletconnect.md](evm-only-walletconnect.md) | Enable WalletConnect for Fireblocks / Ledger / mobile-only wallets | `setup` |
55
+ | Bridge to SDK | [bridge-to-sdk.md](bridge-to-sdk.md) | `useWalletProvider` → typed `IXxxWalletProvider` for `@sodax/sdk` calls | `setup`, one of `connect-button` / `multi-chain-modal` |
56
+
57
+ ## Conventions
58
+
59
+ ### Single object parameter
60
+
61
+ Every hook in `@sodax/wallet-sdk-react` accepts one options object:
62
+
63
+ ```typescript
64
+ useXConnectors({ xChainType: 'EVM' });
65
+ useXAccount({ xChainId: ChainKeys.BSC_MAINNET });
66
+ useWalletProvider({ xChainType: 'EVM' });
67
+ ```
68
+
69
+ `useXAccount` / `useWalletProvider` accept either `xChainId` (chain key) **or** `xChainType` (family) — never both.
70
+
71
+ ### Mutation pattern (`useXConnect`)
72
+
73
+ `useXConnect` is a React Query mutation. Pass an `IXConnector` to `mutate` / `mutateAsync`:
74
+
75
+ ```typescript
76
+ const { mutateAsync: connect } = useXConnect();
77
+ await connect(connector);
78
+ ```
79
+
80
+ For provider-managed chains (EVM/Solana/Sui), the resolved value is `undefined` — read the connected account via `useXAccount` after the mutation lands. See [Connect Flow caveat](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECT_FLOW.md#provider-managed-chains-caveat).
81
+
82
+ ### Persisted connections
83
+
84
+ Connections survive page reloads via `localStorage` (key `xwagmi-store`). Gate UI on hydration to avoid flicker — `useConnectedChains().status === 'ready'` is the official signal.
@@ -0,0 +1,148 @@
1
+ # Skill: Bridge to SDK
2
+
3
+ Pass the user's connected wallet to `@sodax/sdk` calls — `useWalletProvider` returns a typed `IXxxWalletProvider` ready to plug into any SDK method.
4
+
5
+ **Depends on:** [setup.md](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/skills/setup.md), one of [connect-button.md](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/skills/connect-button.md) / [multi-chain-modal.md](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/skills/multi-chain-modal.md)
6
+
7
+ ## Hooks
8
+
9
+ | Hook | Purpose |
10
+ |------|---------|
11
+ | `useWalletProvider({ xChainId })` | Typed `IXxxWalletProvider` (chain-narrowed by chain id) |
12
+ | `useWalletProvider({ xChainType })` | Family-level provider (same shape for every chain id in family) |
13
+ | `useXAccount({ xChainId })` | Read connected address |
14
+ | `useXService({ xChainType })` | Lower-level — chain `XService` instance for advanced reads |
15
+
16
+ Pass either `xChainId` (a `SpokeChainKey`) or `xChainType` (a `ChainType`), never both.
17
+
18
+ ## Pattern — drive an SDK swap from a connected wallet
19
+
20
+ ```tsx
21
+ import { useWalletProvider, useXAccount } from '@sodax/wallet-sdk-react';
22
+ import { Sodax, ChainKeys } from '@sodax/sdk';
23
+ import type { CreateIntentParams } from '@sodax/sdk';
24
+
25
+ const sodax = new Sodax(); // or hold one in context / pass via @sodax/dapp-kit
26
+
27
+ export function SwapButton({ params }: { params: CreateIntentParams<typeof ChainKeys.BSC_MAINNET> }) {
28
+ const walletProvider = useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET });
29
+ const account = useXAccount({ xChainId: ChainKeys.BSC_MAINNET });
30
+
31
+ const handleSwap = async () => {
32
+ if (!walletProvider) return;
33
+ const result = await sodax.swaps.swap({
34
+ params,
35
+ walletProvider, // typed as IEvmWalletProvider — must match BSC src chain
36
+ });
37
+ if (!result.ok) {
38
+ console.error('swap failed:', result.error);
39
+ return;
40
+ }
41
+ console.log('swap submitted:', result.value);
42
+ };
43
+
44
+ return (
45
+ <button onClick={handleSwap} disabled={!walletProvider || !account.address}>
46
+ Swap
47
+ </button>
48
+ );
49
+ }
50
+ ```
51
+
52
+ The pattern works for every SDK feature service:
53
+
54
+ ```typescript
55
+ sodax.swaps.swap({ params, walletProvider });
56
+ sodax.bridge.bridge({ params, walletProvider });
57
+ sodax.moneyMarket.supply({ params, walletProvider });
58
+ sodax.staking.stake({ params, walletProvider });
59
+ sodax.dex.deposit({ params, walletProvider });
60
+ ```
61
+
62
+ See [`packages/sdk/docs/`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/) for per-feature method signatures.
63
+
64
+ ## TypeScript narrowing
65
+
66
+ ```typescript
67
+ import { useWalletProvider } from '@sodax/wallet-sdk-react';
68
+ import { ChainKeys } from '@sodax/types';
69
+
70
+ // By chain id — narrowest typing
71
+ const evm = useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET });
72
+ // evm: IEvmWalletProvider | undefined
73
+
74
+ const sol = useWalletProvider({ xChainId: ChainKeys.SOLANA_MAINNET });
75
+ // sol: ISolanaWalletProvider | undefined
76
+
77
+ // By chain type — family-level (one wagmi connection covers all EVM chains)
78
+ const evmFamily = useWalletProvider({ xChainType: 'EVM' });
79
+ // evmFamily: IEvmWalletProvider | undefined
80
+ ```
81
+
82
+ The chain-narrowing is automatic — passing the wrong wallet provider type to an SDK call (e.g. `ISolanaWalletProvider` to a `srcChainKey: BSC_MAINNET` swap) is a **compile error**.
83
+
84
+ ## EVM — single connection across all networks
85
+
86
+ `useWalletProvider({ xChainId: ChainKeys.BSC_MAINNET })` and `useWalletProvider({ xChainId: ChainKeys.ARBITRUM_MAINNET })` return the **same** `EvmWalletProvider` instance — wagmi maintains one connection across all configured EVM networks. To switch the **active** EVM network, see [`useEvmSwitchChain`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/EVM_SWITCH_CHAIN.md):
87
+
88
+ ```tsx
89
+ import { useEvmSwitchChain } from '@sodax/wallet-sdk-react';
90
+
91
+ const { isWrongChain, handleSwitchChain } = useEvmSwitchChain({
92
+ xChainId: ChainKeys.BSC_MAINNET,
93
+ });
94
+
95
+ if (isWrongChain) {
96
+ return <button onClick={handleSwitchChain}>Switch to BSC</button>;
97
+ }
98
+ ```
99
+
100
+ ## Disabled chains return `undefined`
101
+
102
+ If `xChainType` resolves to a chain not enabled in `SodaxWalletProvider` config, `useWalletProvider` returns `undefined` and logs a one-time warning:
103
+
104
+ ```
105
+ [useWalletProvider] chain "BITCOIN" is not enabled in SodaxWalletProvider config.chains — returning undefined
106
+ ```
107
+
108
+ Always null-check before passing to an SDK call.
109
+
110
+ ## Raw transactions — skip the bridge
111
+
112
+ If you only need unsigned transaction data (manual relay, gas estimation, external signing), pass `raw: true` to the SDK and skip `walletProvider`:
113
+
114
+ ```typescript
115
+ const result = await sodax.swaps.createIntent({
116
+ params,
117
+ raw: true, // walletProvider must be absent — compile error if passed
118
+ });
119
+ // result.value.tx is an EvmRawTransaction
120
+ ```
121
+
122
+ See [`packages/sdk/docs/SWAPS.md`](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/SWAPS.md) for the full raw-vs-signed matrix per method.
123
+
124
+ ## Server / scripts — use `@sodax/wallet-sdk-core` directly
125
+
126
+ For Node.js scripts / bots, skip wallet-sdk-react entirely:
127
+
128
+ ```typescript
129
+ import { Sodax } from '@sodax/sdk';
130
+ import { EvmWalletProvider } from '@sodax/wallet-sdk-core';
131
+ import { ChainKeys } from '@sodax/types';
132
+
133
+ const sodax = new Sodax();
134
+ const walletProvider = new EvmWalletProvider({
135
+ privateKey: process.env.PRIVATE_KEY!,
136
+ chainId: ChainKeys.BSC_MAINNET,
137
+ rpcUrl: 'https://bsc-dataseed.binance.org',
138
+ });
139
+ const result = await sodax.swaps.swap({ params, walletProvider });
140
+ ```
141
+
142
+ ## Reference docs
143
+
144
+ - [Wallet Provider Bridge](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/WALLET_PROVIDER_BRIDGE.md) — `useWalletProvider` + `useXService` reference
145
+ - [SDK Wallet Providers Reference](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/WALLET_PROVIDERS.md) — per-chain `IXxxWalletProvider` interfaces
146
+ - [SDK Swaps](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/SWAPS.md) — example consumer of a wallet provider
147
+ - [EVM Switch Chain](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/EVM_SWITCH_CHAIN.md) — switch active EVM network
148
+ - [`packages/dapp-kit`](https://github.com/icon-project/sodax-sdks/blob/main/packages/dapp-kit/README.md) — higher-level React hooks that wrap SDK calls + `useWalletProvider`
@@ -0,0 +1,116 @@
1
+ # Skill: Connect Button
2
+
3
+ Single-chain connect/disconnect button — pick a connector, connect, read the account, disconnect.
4
+
5
+ **Depends on:** [setup.md](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/skills/setup.md)
6
+
7
+ ## Hooks
8
+
9
+ | Hook | Purpose |
10
+ |------|---------|
11
+ | `useXConnectors({ xChainType })` | List available connectors for the chain family |
12
+ | `useXConnect()` | React Query mutation — `mutate(connector)` |
13
+ | `useXAccount({ xChainType })` | Read connected account (always returns object — `address` is `undefined` when disconnected) |
14
+ | `useXDisconnect()` | Returns `(args) => Promise<void>` |
15
+ | `sortConnectors(list, { preferred })` | Optional — rank installed/preferred wallets first |
16
+
17
+ ## Connect button
18
+
19
+ ```tsx
20
+ import {
21
+ useXConnectors,
22
+ useXConnect,
23
+ useXAccount,
24
+ useXDisconnect,
25
+ sortConnectors,
26
+ type IXConnector,
27
+ } from '@sodax/wallet-sdk-react';
28
+
29
+ const PREFERRED = ['hana', 'metamask'] as const;
30
+
31
+ export function EvmConnectButton() {
32
+ const raw = useXConnectors({ xChainType: 'EVM' });
33
+ const connectors = sortConnectors(raw, { preferred: PREFERRED });
34
+ const { mutateAsync: connect, isPending, error } = useXConnect();
35
+ const account = useXAccount({ xChainType: 'EVM' });
36
+ const disconnect = useXDisconnect();
37
+
38
+ if (account.address) {
39
+ return (
40
+ <div>
41
+ <code>{account.address}</code>
42
+ <button onClick={() => disconnect({ xChainType: 'EVM' })}>Disconnect</button>
43
+ </div>
44
+ );
45
+ }
46
+
47
+ return (
48
+ <div>
49
+ {connectors.map((connector) => (
50
+ <button
51
+ key={connector.id}
52
+ onClick={() => connect(connector).catch(() => {})}
53
+ disabled={isPending}
54
+ >
55
+ {connector.icon && <img src={connector.icon} alt="" width={20} height={20} />}
56
+ {connector.name}
57
+ {!connector.isInstalled && ' (not installed)'}
58
+ </button>
59
+ ))}
60
+ {error && <p style={{ color: 'red' }}>{error.message}</p>}
61
+ </div>
62
+ );
63
+ }
64
+ ```
65
+
66
+ ## Install CTA for missing wallets
67
+
68
+ ```tsx
69
+ {connectors.map((connector) =>
70
+ connector.isInstalled ? (
71
+ <button key={connector.id} onClick={() => connect(connector)}>
72
+ {connector.name}
73
+ </button>
74
+ ) : (
75
+ <a key={connector.id} href={connector.installUrl} target="_blank" rel="noreferrer">
76
+ Install {connector.name}
77
+ </a>
78
+ ),
79
+ )}
80
+ ```
81
+
82
+ `isInstalled` reads `window.*` at render time (no extra subscription). For batch install detection across wallet brands, use [`useIsWalletInstalled`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CHAIN_DETECTION.md#useiswalletinstalled--install-detection).
83
+
84
+ ## Caveat — provider-managed chains resolve with `undefined`
85
+
86
+ For EVM, Solana, and Sui, `connect(connector)` resolves with `undefined` because connection state is set by the chain's Hydrator after the native SDK reports `connected`. Always read the account via `useXAccount`, not the mutation's return value:
87
+
88
+ ```typescript
89
+ const { mutateAsync: connect } = useXConnect();
90
+ const account = useXAccount({ xChainType: 'EVM' });
91
+
92
+ await connect(connector); // resolves with undefined for EVM
93
+ // account.address is populated on the next render
94
+ ```
95
+
96
+ Non-provider chains (Bitcoin, ICON, Injective, Stellar, NEAR, Stacks) return the resolved `XAccount` from `connect()` — but reading via `useXAccount` works for both, so default to it.
97
+
98
+ ## Multiple chains, one button
99
+
100
+ For a "connect EVM + Solana + Bitcoin in one click" pattern, use [`useBatchConnect`](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/BATCH_OPERATIONS.md):
101
+
102
+ ```tsx
103
+ import { useBatchConnect } from '@sodax/wallet-sdk-react';
104
+
105
+ const { run, status } = useBatchConnect({ connectors: ['hana'] });
106
+ // Connects every chain Hana supports — sequential, errors collected.
107
+ <button onClick={run} disabled={status === 'running'}>
108
+ Connect Hana on all chains
109
+ </button>;
110
+ ```
111
+
112
+ ## Reference docs
113
+
114
+ - [Connect Flow](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECT_FLOW.md) — full lifecycle reference + error handling
115
+ - [Connectors](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/CONNECTORS.md) — `IXConnector` shape, deep imports for concrete classes
116
+ - [Batch Operations](https://github.com/icon-project/sodax-sdks/blob/main/packages/wallet-sdk-react/docs/BATCH_OPERATIONS.md) — multi-chain connect by wallet identifier