@sodax/wallet-sdk-react 2.0.0-rc.2 → 2.0.0-rc.21

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 (141) hide show
  1. package/README.md +14 -7
  2. package/dist/{XConnector-B9YQTVJ4.d.ts → XConnector-12q0OVe5.d.ts} +1 -1
  3. package/dist/{chunk-NY7U7OJW.mjs → chunk-7V7O3Q7Y.mjs} +0 -2
  4. package/dist/{chunk-BXJLBR4G.mjs → chunk-C6M34IVL.mjs} +2 -4
  5. package/dist/{chunk-PLCA4ZDJ.mjs → chunk-HEY7NRFG.mjs} +254 -52
  6. package/dist/{chunk-X2MHIWXO.mjs → chunk-IFXZQW4C.mjs} +0 -2
  7. package/dist/{chunk-7ULB6DW4.mjs → chunk-JQ4H4GJ5.mjs} +3 -5
  8. package/dist/{chunk-E5IAZ7E6.mjs → chunk-LM7R5APS.mjs} +22 -11
  9. package/dist/{chunk-BKJB527E.mjs → chunk-MWWVB7TD.mjs} +2 -4
  10. package/dist/{chunk-MXZVF5HR.mjs → chunk-NAKCAL2M.mjs} +0 -2
  11. package/dist/{chunk-PJLEJVAU.mjs → chunk-OPX55MQO.mjs} +11 -6
  12. package/dist/chunk-QMXBY3UI.mjs +1 -0
  13. package/dist/{chunk-MAQ47Q52.mjs → chunk-TACW7Z4D.mjs} +0 -2
  14. package/dist/chunk-VPNYFVP6.mjs +53 -0
  15. package/dist/{chunk-2BOUGCJ7.mjs → chunk-WPZOLGVB.mjs} +4 -6
  16. package/dist/{chunk-66BAUK56.mjs → chunk-X7BHR7WS.mjs} +4 -6
  17. package/dist/{chunk-N5A2TMF6.mjs → chunk-XJA2MJMG.mjs} +2 -4
  18. package/dist/{config-OlnzyEUE.d.ts → config-DEsqgrG1.d.ts} +10 -5
  19. package/dist/index.d.ts +6 -6
  20. package/dist/index.mjs +20 -31
  21. package/dist/xchains/bitcoin/index.d.ts +20 -3
  22. package/dist/xchains/bitcoin/index.mjs +14 -16
  23. package/dist/xchains/evm/index.d.ts +3 -3
  24. package/dist/xchains/evm/index.mjs +3 -5
  25. package/dist/xchains/icon/index.d.ts +1 -1
  26. package/dist/xchains/icon/index.mjs +5 -7
  27. package/dist/xchains/injective/index.d.ts +2 -2
  28. package/dist/xchains/injective/index.mjs +3 -5
  29. package/dist/xchains/near/index.d.ts +1 -1
  30. package/dist/xchains/near/index.mjs +4 -6
  31. package/dist/xchains/solana/index.d.ts +1 -1
  32. package/dist/xchains/solana/index.mjs +5 -7
  33. package/dist/xchains/stacks/index.d.ts +10 -4
  34. package/dist/xchains/stacks/index.mjs +3 -5
  35. package/dist/xchains/stellar/index.d.ts +1 -1
  36. package/dist/xchains/stellar/index.mjs +4 -6
  37. package/dist/xchains/sui/index.d.ts +1 -1
  38. package/dist/xchains/sui/index.mjs +5 -7
  39. package/package.json +37 -29
  40. package/ai-exported/AGENTS.md +0 -122
  41. package/ai-exported/integration/README.md +0 -102
  42. package/ai-exported/integration/ai-rules.md +0 -136
  43. package/ai-exported/integration/architecture.md +0 -181
  44. package/ai-exported/integration/examples/01-minimal-evm.tsx +0 -75
  45. package/ai-exported/integration/examples/02-multi-chain-modal.tsx +0 -169
  46. package/ai-exported/integration/examples/03-nextjs-app-router.tsx +0 -99
  47. package/ai-exported/integration/examples/04-walletconnect-setup.tsx +0 -89
  48. package/ai-exported/integration/examples/README.md +0 -29
  49. package/ai-exported/integration/recipes/batch-operations.md +0 -223
  50. package/ai-exported/integration/recipes/bridge-to-sdk.md +0 -164
  51. package/ai-exported/integration/recipes/chain-detection.md +0 -254
  52. package/ai-exported/integration/recipes/connect-button.md +0 -156
  53. package/ai-exported/integration/recipes/multi-chain-modal.md +0 -199
  54. package/ai-exported/integration/recipes/setup.md +0 -158
  55. package/ai-exported/integration/recipes/sign-message.md +0 -137
  56. package/ai-exported/integration/recipes/sub-path-imports.md +0 -95
  57. package/ai-exported/integration/recipes/switch-chain.md +0 -141
  58. package/ai-exported/integration/recipes/walletconnect-setup.md +0 -139
  59. package/ai-exported/integration/reference/api-surface.md +0 -175
  60. package/ai-exported/integration/reference/chain-support.md +0 -78
  61. package/ai-exported/integration/reference/connectors.md +0 -74
  62. package/ai-exported/integration/reference/hooks.md +0 -204
  63. package/ai-exported/integration/reference/wallet-brands.md +0 -106
  64. package/ai-exported/migration/README.md +0 -49
  65. package/ai-exported/migration/ai-rules.md +0 -144
  66. package/ai-exported/migration/breaking-changes.md +0 -305
  67. package/ai-exported/migration/checklist.md +0 -159
  68. package/ai-exported/migration/recipes/connect-button.md +0 -166
  69. package/ai-exported/migration/recipes/multi-chain-modal.md +0 -244
  70. package/ai-exported/migration/recipes/ssr-setup.md +0 -162
  71. package/ai-exported/migration/recipes/walletconnect-migration.md +0 -168
  72. package/ai-exported/migration/reference/components.md +0 -73
  73. package/ai-exported/migration/reference/config.md +0 -307
  74. package/ai-exported/migration/reference/hooks.md +0 -278
  75. package/ai-exported/migration/reference/imports.md +0 -157
  76. package/dist/chunk-2BOUGCJ7.mjs.map +0 -1
  77. package/dist/chunk-66BAUK56.mjs.map +0 -1
  78. package/dist/chunk-7ULB6DW4.mjs.map +0 -1
  79. package/dist/chunk-BKJB527E.mjs.map +0 -1
  80. package/dist/chunk-BXJLBR4G.mjs.map +0 -1
  81. package/dist/chunk-E5IAZ7E6.mjs.map +0 -1
  82. package/dist/chunk-MAQ47Q52.mjs.map +0 -1
  83. package/dist/chunk-MXZVF5HR.mjs.map +0 -1
  84. package/dist/chunk-N5A2TMF6.mjs.map +0 -1
  85. package/dist/chunk-NY7U7OJW.mjs.map +0 -1
  86. package/dist/chunk-PJLEJVAU.mjs.map +0 -1
  87. package/dist/chunk-PLCA4ZDJ.mjs.map +0 -1
  88. package/dist/chunk-TZMKDXFA.mjs +0 -3
  89. package/dist/chunk-TZMKDXFA.mjs.map +0 -1
  90. package/dist/chunk-X2MHIWXO.mjs.map +0 -1
  91. package/dist/chunk-XZ7CHO2S.mjs +0 -41
  92. package/dist/chunk-XZ7CHO2S.mjs.map +0 -1
  93. package/dist/index.cjs +0 -3337
  94. package/dist/index.cjs.map +0 -1
  95. package/dist/index.mjs.map +0 -1
  96. package/dist/xchains/bitcoin/index.cjs +0 -1927
  97. package/dist/xchains/bitcoin/index.cjs.map +0 -1
  98. package/dist/xchains/bitcoin/index.mjs.map +0 -1
  99. package/dist/xchains/evm/index.cjs +0 -316
  100. package/dist/xchains/evm/index.cjs.map +0 -1
  101. package/dist/xchains/evm/index.mjs.map +0 -1
  102. package/dist/xchains/icon/index.cjs +0 -311
  103. package/dist/xchains/icon/index.cjs.map +0 -1
  104. package/dist/xchains/icon/index.mjs.map +0 -1
  105. package/dist/xchains/injective/index.cjs +0 -223
  106. package/dist/xchains/injective/index.cjs.map +0 -1
  107. package/dist/xchains/injective/index.mjs.map +0 -1
  108. package/dist/xchains/near/index.cjs +0 -190
  109. package/dist/xchains/near/index.cjs.map +0 -1
  110. package/dist/xchains/near/index.mjs.map +0 -1
  111. package/dist/xchains/solana/index.cjs +0 -186
  112. package/dist/xchains/solana/index.cjs.map +0 -1
  113. package/dist/xchains/solana/index.mjs.map +0 -1
  114. package/dist/xchains/stacks/index.cjs +0 -240
  115. package/dist/xchains/stacks/index.cjs.map +0 -1
  116. package/dist/xchains/stacks/index.mjs.map +0 -1
  117. package/dist/xchains/stellar/index.cjs +0 -322
  118. package/dist/xchains/stellar/index.cjs.map +0 -1
  119. package/dist/xchains/stellar/index.mjs.map +0 -1
  120. package/dist/xchains/sui/index.cjs +0 -248
  121. package/dist/xchains/sui/index.cjs.map +0 -1
  122. package/dist/xchains/sui/index.mjs.map +0 -1
  123. package/docs/ADDING_A_NEW_CHAIN.md +0 -440
  124. package/docs/ARCHITECTURE.md +0 -291
  125. package/docs/BATCH_OPERATIONS.md +0 -267
  126. package/docs/CHAIN_DETECTION.md +0 -216
  127. package/docs/CONFIGURE_PROVIDER.md +0 -360
  128. package/docs/CONNECTORS.md +0 -247
  129. package/docs/CONNECT_FLOW.md +0 -276
  130. package/docs/EVM_SWITCH_CHAIN.md +0 -161
  131. package/docs/SIGN_MESSAGE.md +0 -213
  132. package/docs/SUB_PATH_EXPORTS.md +0 -246
  133. package/docs/WALLETCONNECT.md +0 -154
  134. package/docs/WALLET_MODAL.md +0 -331
  135. package/docs/WALLET_PROVIDER_BRIDGE.md +0 -226
  136. package/skills/SKILLS.md +0 -84
  137. package/skills/bridge-to-sdk.md +0 -148
  138. package/skills/connect-button.md +0 -116
  139. package/skills/evm-only-walletconnect.md +0 -111
  140. package/skills/multi-chain-modal.md +0 -178
  141. package/skills/setup.md +0 -107
@@ -1,199 +0,0 @@
1
- # Recipe: Multi-Chain Wallet Modal
2
-
3
- Headless wallet-connect modal that walks the user through `chainSelect → walletSelect → connecting → success | error`. Pair with `useChainGroups` for the chain picker and `useXConnectors` for the wallet picker. Render-agnostic — works with any dialog/drawer/inline UI.
4
-
5
- **Depends on:** [`setup.md`](./setup.md)
6
-
7
- ---
8
-
9
- ## Hooks used
10
-
11
- | Hook | Purpose |
12
- |------|---------|
13
- | `useWalletModal({ onConnected? })` | State machine + actions (`open`, `close`, `back`, `selectChain`, `selectWallet`, `retry`) |
14
- | `useChainGroups({ order? })` | One row per enabled chain family (EVM collapses to one row) |
15
- | `useXConnectors({ xChainType })` | Wallet list for the chosen chain family |
16
- | `useXAccount({ xChainType })` | Read the connected account when needed |
17
-
18
- ---
19
-
20
- ## Render switch
21
-
22
- ```tsx
23
- 'use client';
24
-
25
- import {
26
- useWalletModal,
27
- useChainGroups,
28
- useXConnectors,
29
- type IXConnector,
30
- } from '@sodax/wallet-sdk-react';
31
-
32
- export function WalletModalRoot() {
33
- const modal = useWalletModal({
34
- onConnected: async (chainType, account) => {
35
- console.log('connected', chainType, account.address);
36
- },
37
- });
38
-
39
- switch (modal.state.kind) {
40
- case 'closed':
41
- return <button onClick={modal.open}>Connect Wallet</button>;
42
-
43
- case 'chainSelect':
44
- return <ChainPicker onPick={modal.selectChain} onClose={modal.close} />;
45
-
46
- case 'walletSelect':
47
- return (
48
- <WalletPicker
49
- chainType={modal.state.chainType}
50
- onPick={modal.selectWallet}
51
- onBack={modal.back}
52
- onClose={modal.close}
53
- />
54
- );
55
-
56
- case 'connecting':
57
- // Hide modal while wagmi's QR modal is up for WalletConnect
58
- if (modal.state.connector.id === 'walletConnect') return null;
59
- return (
60
- <Dialog onClose={modal.close}>
61
- <p>Approve in {modal.state.connector.name}…</p>
62
- <button onClick={modal.back}>Cancel</button>
63
- </Dialog>
64
- );
65
-
66
- case 'success':
67
- // onConnected fired; close after a beat
68
- setTimeout(modal.close, 0);
69
- return null;
70
-
71
- case 'error':
72
- return (
73
- <Dialog onClose={modal.close}>
74
- <p>{modal.state.error.message}</p>
75
- {!modal.state.connector.isInstalled && modal.state.connector.installUrl && (
76
- <a href={modal.state.connector.installUrl}>Install {modal.state.connector.name}</a>
77
- )}
78
- <button onClick={modal.retry}>Retry</button>
79
- <button onClick={modal.back}>Pick another wallet</button>
80
- </Dialog>
81
- );
82
- }
83
- }
84
- ```
85
-
86
- Render `<WalletModalRoot />` once at the app root — any other component can dispatch `useWalletModal().open()` to show it.
87
-
88
- ---
89
-
90
- ## Chain picker
91
-
92
- ```tsx
93
- import { useChainGroups } from '@sodax/wallet-sdk-react';
94
- import type { ChainType } from '@sodax/types';
95
-
96
- function ChainPicker({ onPick, onClose }: { onPick: (c: ChainType) => void; onClose: () => void }) {
97
- const groups = useChainGroups({ order: ['EVM', 'SOLANA', 'BITCOIN', 'ICON'] });
98
-
99
- return (
100
- <Dialog onClose={onClose}>
101
- <h2>Select a chain</h2>
102
- {groups.map((group) => (
103
- <button key={group.chainType} onClick={() => onPick(group.chainType)}>
104
- {group.iconUrl && <img src={group.iconUrl} alt="" width={24} height={24} />}
105
- <span>{group.displayName}</span>
106
- {group.isConnected && <span>Connected</span>}
107
- </button>
108
- ))}
109
- </Dialog>
110
- );
111
- }
112
- ```
113
-
114
- EVM collapses to a single group covering every configured EVM network — this matches reality (wagmi maintains one connection across all EVM chains).
115
-
116
- ---
117
-
118
- ## Wallet picker
119
-
120
- ```tsx
121
- import { useXConnectors, sortConnectors, type IXConnector } from '@sodax/wallet-sdk-react';
122
- import type { ChainType } from '@sodax/types';
123
-
124
- function WalletPicker({
125
- chainType,
126
- onPick,
127
- onBack,
128
- onClose,
129
- }: {
130
- chainType: ChainType;
131
- onPick: (c: IXConnector) => void;
132
- onBack: () => void;
133
- onClose: () => void;
134
- }) {
135
- const connectors = sortConnectors(useXConnectors({ xChainType: chainType }), {
136
- preferred: ['hana', 'metamask', 'phantom'],
137
- });
138
-
139
- return (
140
- <Dialog onClose={onClose}>
141
- <button onClick={onBack}>← Back</button>
142
- <h2>Select a wallet</h2>
143
- {connectors.map((connector) => (
144
- <button key={connector.id} onClick={() => onPick(connector)}>
145
- {connector.icon && <img src={connector.icon} alt="" />}
146
- {connector.name}
147
- {!connector.isInstalled && ' (not installed)'}
148
- </button>
149
- ))}
150
- </Dialog>
151
- );
152
- }
153
- ```
154
-
155
- ---
156
-
157
- ## Concurrency rules
158
-
159
- - **Same connector double-click** → returns the same in-flight promise (no double popup).
160
- - **Different connector mid-attempt** → starts a new attempt; previous one's late resolution is dropped.
161
- - **`back()` / `close()` mid-attempt** → cancellation guard inside the modal layer; the wallet may still approve in the background but `success`/`error` won't fire. To roll back, call `useXDisconnect()(xChainType)` from the same handler.
162
-
163
- ---
164
-
165
- ## `onConnected` is non-fatal
166
-
167
- Throwing inside `onConnected` is logged but **does not** downgrade `success` → `error`. The connection is already persisted; the user is genuinely connected.
168
-
169
- ---
170
-
171
- ## Non-modal alternative — `useConnectionFlow`
172
-
173
- For a single-button flow without the multi-step modal:
174
-
175
- ```tsx
176
- import { useConnectionFlow } from '@sodax/wallet-sdk-react';
177
-
178
- const { status, error, connect, retry, activeConnector } = useConnectionFlow();
179
-
180
- return (
181
- <button onClick={() => connect(connector)} disabled={status === 'connecting'}>
182
- {status === 'connecting' ? 'Waiting…' : 'Connect'}
183
- </button>
184
- );
185
- ```
186
-
187
- `connect()` and `retry()` never throw — errors flow into `error` state.
188
-
189
- ---
190
-
191
- ## Verification
192
-
193
- ```bash
194
- # 1. Type check
195
- pnpm checkTs
196
-
197
- # 2. Manual — open modal, walk through chain → wallet → connecting → success → close
198
- # 3. Manual — pick non-installed wallet, confirm install link appears in error state
199
- ```
@@ -1,158 +0,0 @@
1
- # Recipe: Setup
2
-
3
- Install and wire `@sodax/wallet-sdk-react` into a React project. **Always do this first** — every other recipe assumes `SodaxWalletProvider` is mounted.
4
-
5
- **Depends on:** None
6
-
7
- ---
8
-
9
- ## Install
10
-
11
- ```bash
12
- pnpm add @sodax/wallet-sdk-react @tanstack/react-query
13
- ```
14
-
15
- Peer dependencies:
16
-
17
- ```json
18
- {
19
- "react": ">=19",
20
- "@tanstack/react-query": "5.x"
21
- }
22
- ```
23
-
24
- ---
25
-
26
- ## Wire `SodaxWalletProvider`
27
-
28
- Top-level keys on `SodaxWalletConfig` are chain-type slots — **omit a slot to skip mounting that adapter**, pass `{}` to mount with SDK defaults. `<QueryClientProvider>` must wrap `<SodaxWalletProvider>`.
29
-
30
- ```tsx
31
- // providers.tsx
32
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
33
- import { SodaxWalletProvider, type SodaxWalletConfig } from '@sodax/wallet-sdk-react';
34
- import { ChainKeys } from '@sodax/types';
35
-
36
- const queryClient = new QueryClient();
37
-
38
- const walletConfig: SodaxWalletConfig = {
39
- EVM: {
40
- ssr: true, // Next.js — keep true for SSR-safe hydration. Drop for Vite/CRA.
41
- chains: {
42
- [ChainKeys.SONIC_MAINNET]: { rpcUrl: 'https://rpc.soniclabs.com' },
43
- [ChainKeys.ETHEREUM_MAINNET]: { rpcUrl: 'https://ethereum-rpc.publicnode.com' },
44
- [ChainKeys.BSC_MAINNET]: { rpcUrl: 'https://bsc-dataseed.binance.org' },
45
- },
46
- },
47
- ICON: {
48
- chains: { [ChainKeys.ICON_MAINNET]: { rpcUrl: 'https://ctz.solidwallet.io/api/v3' } },
49
- },
50
- // BITCOIN: {}, // mount with SDK defaults
51
- // SOLANA: { chains: { [ChainKeys.SOLANA_MAINNET]: { rpcUrl: '...' } } },
52
- };
53
-
54
- export function Providers({ children }: { children: React.ReactNode }) {
55
- return (
56
- <QueryClientProvider client={queryClient}>
57
- <SodaxWalletProvider config={walletConfig}>{children}</SodaxWalletProvider>
58
- </QueryClientProvider>
59
- );
60
- }
61
- ```
62
-
63
- ---
64
-
65
- ## Mount point per framework
66
-
67
- | Framework | Where to mount `<Providers>` | `EVM.ssr` |
68
- |---|---|---|
69
- | Next.js (App Router) | `app/layout.tsx`, inside `<body>`. Mark the providers file `'use client'`. Pair with [`recipes/ssr-setup.md`](../../migration/recipes/ssr-setup.md) if you need wagmi cookie hydration. | `true` |
70
- | Vite + React | `main.tsx`, wrap `<App />` directly. | omit (defaults `false`) |
71
- | Create React App | `index.tsx`, wrap `<App />` directly. | omit |
72
- | Remix / Tanstack Start | Root route component, marked client-only. Same as Next.js. | `true` |
73
-
74
- ---
75
-
76
- ## Chain-type slots
77
-
78
- | Slot | React adapter mounted? | Notes |
79
- |---|---|---|
80
- | `EVM` | ✅ wagmi | One connection across every configured EVM chain. WalletConnect opt-in via `EVM.walletConnect.projectId`. |
81
- | `SOLANA` | ✅ `@solana/wallet-adapter-react` | `autoConnect` defaults to `true`. |
82
- | `SUI` | ✅ `@mysten/dapp-kit` | `network` defaults to `'mainnet'`. |
83
- | `BITCOIN` / `STELLAR` / `ICON` / `INJECTIVE` / `NEAR` / `STACKS` | ❌ no React adapter | Service auto-registered at mount. Connector list shipped per chain. |
84
-
85
- For chain key constants and per-chain entry shapes, see [`../reference/chain-support.md`](../reference/chain-support.md).
86
-
87
- ---
88
-
89
- ## Enable WalletConnect (optional)
90
-
91
- Add WalletConnect support for Fireblocks / Ledger Live / mobile-only EVM wallets by setting `EVM.walletConnect.projectId`:
92
-
93
- ```tsx
94
- const walletConfig: SodaxWalletConfig = {
95
- EVM: {
96
- ssr: true,
97
- walletConnect: {
98
- projectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID!,
99
- // Optional: showQrModal, metadata, qrModalOptions — see WalletConnectParameters
100
- },
101
- chains: { /* ... */ },
102
- },
103
- };
104
- ```
105
-
106
- Get a project ID from [cloud.walletconnect.com](https://cloud.walletconnect.com). Omit `walletConnect` entirely to disable — v2 falls back to EIP-6963 injected wallets only. Full pattern in [`walletconnect-setup.md`](./walletconnect-setup.md).
107
-
108
- ---
109
-
110
- ## Config is captured once on mount
111
-
112
- `SodaxWalletProvider` freezes the `config` prop on first render. Subsequent re-renders with a new reference have **no effect**. To swap config at runtime, remount with a new `key`:
113
-
114
- ```tsx
115
- <SodaxWalletProvider key={configVersion} config={walletConfig}>
116
- {children}
117
- </SodaxWalletProvider>
118
- ```
119
-
120
- ---
121
-
122
- ## Pair with `@sodax/dapp-kit` (optional)
123
-
124
- If you also use `@sodax/dapp-kit` for SDK feature hooks, mount `SodaxProvider` outermost:
125
-
126
- ```tsx
127
- <SodaxProvider config={sodaxConfig}>
128
- <QueryClientProvider client={queryClient}>
129
- <SodaxWalletProvider config={walletConfig}>{children}</SodaxWalletProvider>
130
- </QueryClientProvider>
131
- </SodaxProvider>
132
- ```
133
-
134
- `SodaxProvider` (from dapp-kit) wraps the lot. `QueryClientProvider` must wrap `SodaxWalletProvider` because hooks inside use React Query.
135
-
136
- ---
137
-
138
- ## Verification
139
-
140
- ```bash
141
- # 1. Type check
142
- pnpm checkTs
143
-
144
- # 2. Provider mounted exactly once
145
- grep -rn "SodaxWalletProvider" <user-src> --include="*.tsx" | grep -v "import" | wc -l
146
- # expect 1
147
-
148
- # 3. QueryClientProvider wraps SodaxWalletProvider
149
- # (manual — confirm nesting in providers.tsx)
150
- ```
151
-
152
- ---
153
-
154
- ## Next steps
155
-
156
- - [`connect-button.md`](./connect-button.md) — single-chain connect/disconnect button
157
- - [`multi-chain-modal.md`](./multi-chain-modal.md) — multi-chain headless wallet modal
158
- - [`bridge-to-sdk.md`](./bridge-to-sdk.md) — pass `walletProvider` to `@sodax/sdk` calls
@@ -1,137 +0,0 @@
1
- # Recipe: Sign Message
2
-
3
- `useXSignMessage` is a single React Query mutation that delegates message signing to the connected wallet's per-chain `signMessage` implementation. The signature shape and encoding rules differ per chain — Bitcoin in particular auto-selects between BIP-322 and ECDSA based on the connected address type.
4
-
5
- **Depends on:** [`setup.md`](./setup.md), one of [`connect-button.md`](./connect-button.md) / [`multi-chain-modal.md`](./multi-chain-modal.md)
6
-
7
- ---
8
-
9
- ## Hook API
10
-
11
- ```typescript
12
- import { useXSignMessage } from '@sodax/wallet-sdk-react';
13
-
14
- const sign = useXSignMessage();
15
-
16
- const signature = await sign.mutateAsync({
17
- xChainType: 'EVM',
18
- message: 'Sign in to MyDApp\nNonce: abc123',
19
- });
20
- // signature: `0x${string}` | Uint8Array | string | undefined
21
- ```
22
-
23
- | Field | Type | Notes |
24
- |-------|------|-------|
25
- | `xChainType` | `ChainType` | Which chain to sign with (`'EVM'`, `'BITCOIN'`, …) |
26
- | `message` | `string` | Plain UTF-8; per-chain wrappers handle encoding |
27
-
28
- Return type is the discriminated union `` `0x${string}` | Uint8Array | string | undefined `` because each chain returns its native signature shape (hex for EVM, base64 for Stellar, base58 for Solana, etc.). Cast or branch on `xChainType` when consuming.
29
-
30
- `undefined` is returned (not thrown) when the chain doesn't implement `signMessage` — currently only ICON. A one-time `console.warn` accompanies the `undefined`.
31
-
32
- ---
33
-
34
- ## Per-chain support matrix
35
-
36
- | Chain | Implementation | Signature shape |
37
- |-------|----------------|-----------------|
38
- | EVM | `signMessageAsync` from wagmi → personal_sign | `` `0x${string}` `` |
39
- | Solana | `signMessage` from `@solana/wallet-adapter` | `Uint8Array` |
40
- | Sui | `signPersonalMessage` from `@mysten/dapp-kit` | `string` (base64 signature + bytes) |
41
- | Bitcoin | Auto-detect: BIP-322 (P2WPKH/P2TR) or ECDSA (P2SH/P2PKH) | `string` |
42
- | Stellar | `walletsKit.signMessage` from `@creit.tech/stellar-wallets-kit` | `string` (base64) |
43
- | Injective | `walletStrategy.signArbitrary` from `@injectivelabs/wallet-base` | `string` |
44
- | NEAR | NEAR connector's `signMessage` | `string` |
45
- | Stacks | `signMessage` from `@stacks/connect` | `string` |
46
- | **ICON** | **Not supported** — Hana wallet does not expose a signing API | `undefined` |
47
-
48
- ---
49
-
50
- ## Bitcoin — BIP-322 vs ECDSA auto-detect
51
-
52
- Bitcoin's signing flow inspects the connected address and picks the right method automatically:
53
-
54
- | Address type | Signing method | Connectors that support it |
55
- |--------------|----------------|----------------------------|
56
- | P2WPKH (native segwit, `bc1q…`) | BIP-322 | Unisat, Xverse, OKX |
57
- | P2TR (taproot, `bc1p…`) | BIP-322 | Unisat, Xverse, OKX |
58
- | P2SH (legacy multi-sig, `3…`) | ECDSA | Unisat, Xverse, OKX |
59
- | P2PKH (legacy, `1…`) | ECDSA | Unisat, Xverse, OKX |
60
-
61
- If a custom connector implements only one of the two methods, calling `signMessage` from a wrongly-typed address surfaces the error inline.
62
-
63
- The same logic mirrors the SDK's `BitcoinSpokeProvider.authenticateWithWallet` — the React layer doesn't reinvent the dispatch.
64
-
65
- ---
66
-
67
- ## ICON not supported
68
-
69
- Hana wallet on ICON exposes account / transaction APIs but no general-purpose `signMessage` endpoint. `sign.mutateAsync({ xChainType: 'ICON' })` returns `undefined` and logs:
70
-
71
- ```
72
- [useXSignMessage] signMessage not supported for chain "ICON"
73
- ```
74
-
75
- If you need a signature on ICON for SIWE-style auth, fall back to a transaction-based proof or skip ICON in your auth flow.
76
-
77
- ---
78
-
79
- ## Error handling
80
-
81
- ```tsx
82
- 'use client';
83
-
84
- import { useXSignMessage } from '@sodax/wallet-sdk-react';
85
-
86
- export function SignButton() {
87
- const sign = useXSignMessage();
88
-
89
- const handleSign = async () => {
90
- try {
91
- const signature = await sign.mutateAsync({
92
- xChainType: 'EVM',
93
- message: 'Sign in',
94
- });
95
- if (!signature) {
96
- // ICON or other unsupported chain
97
- return;
98
- }
99
- submitSignature(signature);
100
- } catch (error) {
101
- // User rejection, wallet disconnect mid-sign, address mismatch, etc.
102
- console.error('sign failed:', error);
103
- }
104
- };
105
-
106
- return (
107
- <button onClick={handleSign} disabled={sign.isPending}>
108
- {sign.isPending ? 'Waiting for wallet…' : 'Sign'}
109
- </button>
110
- );
111
- }
112
- ```
113
-
114
- Common error messages by chain:
115
-
116
- | Chain | Typical error |
117
- |-------|---------------|
118
- | EVM | `User rejected the request` (MetaMask), `User denied message signature` (Rabby) |
119
- | Solana | `WalletSignMessageError: User rejected the request` |
120
- | Sui | `User rejected the signature request` |
121
- | Bitcoin | `<connector.id> does not support BIP-322 signing` (mismatch with address type), `User canceled the request` |
122
- | Stellar | `Stellar signature not found` |
123
- | Injective | `Injective signature not found`, `Injective address not found` |
124
-
125
- `mutation.error` reflects the latest failure; `mutation.isError` / `mutation.isPending` follow standard React Query semantics.
126
-
127
- ---
128
-
129
- ## Verification
130
-
131
- ```bash
132
- # 1. Type check
133
- pnpm checkTs
134
-
135
- # 2. Manual — connect wallet, click sign button, approve in wallet, confirm signature in handler
136
- # 3. Manual — reject the signature, confirm error renders
137
- ```
@@ -1,95 +0,0 @@
1
- # Recipe: Sub-Path Imports (Advanced)
2
-
3
- When and how to use deep imports from `@sodax/wallet-sdk-react/xchains/<chain>`. Default to barrel imports — reach for sub-paths only when you need a concrete class for `instanceof` checks, custom connector lists, or chain-specific utilities not exposed through the public hooks.
4
-
5
- **Depends on:** [`setup.md`](./setup.md)
6
-
7
- ---
8
-
9
- ## When you need it
10
-
11
- The package barrel exports hooks, types, abstractions, and `SodaxWalletProvider`. Concrete chain-specific classes (`XverseXConnector`, `EvmXService`, `IconHanaXConnector`, …) live behind sub-paths to keep the barrel small. Reach for a sub-path import in three cases:
12
-
13
- | Use case | Example |
14
- |---|---|
15
- | Runtime type check on a connector | `if (connector instanceof XverseXConnector) { … }` |
16
- | Override the default connector list for a chain | Pass `connectors: [new MyConnector()]` to `ChainTypeConfig` |
17
- | Call a chain-specific method not on `IXConnector` | `xverseConnector.setAddressPurpose('payment')` |
18
-
19
- If none of the above applies, **stick with barrel imports** — sub-paths are not part of the typical surface.
20
-
21
- ---
22
-
23
- ## `instanceof` check (most common)
24
-
25
- Tag a connector by class to call methods specific to that wallet:
26
-
27
- ```tsx
28
- import { useXConnectors } from '@sodax/wallet-sdk-react';
29
- import { XverseXConnector } from '@sodax/wallet-sdk-react/xchains/bitcoin';
30
-
31
- function BitcoinConnectButton() {
32
- const connectors = useXConnectors({ xChainType: 'BITCOIN' });
33
-
34
- return (
35
- <>
36
- {connectors.map((connector) => (
37
- <button
38
- type="button"
39
- key={connector.id}
40
- onClick={async () => {
41
- // Pre-configure Xverse before connect
42
- if (connector instanceof XverseXConnector) {
43
- connector.setAddressPurpose('payment');
44
- }
45
- await connector.connect();
46
- }}
47
- >
48
- {connector.name}
49
- </button>
50
- ))}
51
- </>
52
- );
53
- }
54
- ```
55
-
56
- The barrel-typed `IXConnector` exposes only `connect()` / `disconnect()` / metadata fields. To reach `setAddressPurpose` (or any class-specific method), narrow via `instanceof` after a sub-path import.
57
-
58
- ---
59
-
60
- ## Custom connector list
61
-
62
- Override the default connectors a chain ships with by passing `connectors` on the `ChainTypeConfig`:
63
-
64
- ```tsx
65
- import type { SodaxWalletConfig } from '@sodax/wallet-sdk-react';
66
- import { XverseXConnector, UnisatXConnector } from '@sodax/wallet-sdk-react/xchains/bitcoin';
67
-
68
- const walletConfig: SodaxWalletConfig = {
69
- BITCOIN: {
70
- // Only mount Xverse + Unisat — drop the OKX connector that ships by default.
71
- connectors: [new XverseXConnector(), new UnisatXConnector()],
72
- },
73
- };
74
- ```
75
-
76
- Use sparingly — the default lists are tuned per chain. Override only when you need to remove a connector you do not support, or add a custom one you implemented yourself.
77
-
78
- ---
79
-
80
- ## Available sub-paths
81
-
82
- For the per-chain symbol list, see [`../reference/api-surface.md`](../reference/api-surface.md) § "Sub-path exports". That table is the single source of truth — `scripts/check-ai-exported.sh` validates it stays in sync with `src/xchains/`.
83
-
84
- ---
85
-
86
- ## Verification
87
-
88
- ```bash
89
- # 1. Type check
90
- pnpm checkTs
91
-
92
- # 2. Sub-path imports must resolve to a real chain folder
93
- grep -rnE "from '@sodax/wallet-sdk-react/xchains/[a-z]+'" <user-src>
94
- # Each match's <chain> must be one of: bitcoin, evm, icon, injective, near, solana, stacks, stellar, sui
95
- ```