otx-btc-wallet-react 0.1.0

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.
package/dist/index.mjs ADDED
@@ -0,0 +1,573 @@
1
+ import { createContext, useContext, useRef, useEffect, useSyncExternalStore, useState, useCallback, useMemo } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ // src/provider.tsx
5
+ var BtcWalletContext = createContext(null);
6
+ function useConfig() {
7
+ const config = useContext(BtcWalletContext);
8
+ if (!config) {
9
+ throw new Error(
10
+ "useConfig must be used within a BtcWalletProvider. Wrap your app in <BtcWalletProvider config={config}>."
11
+ );
12
+ }
13
+ return config;
14
+ }
15
+ function BtcWalletProvider({
16
+ config,
17
+ children
18
+ }) {
19
+ const initializedRef = useRef(false);
20
+ if (!config) {
21
+ throw new Error(
22
+ "BtcWalletProvider requires a config prop. Create one with createConfig() from otx-btc-wallet-core."
23
+ );
24
+ }
25
+ if (!config.store) {
26
+ throw new Error(
27
+ "Invalid config: missing store. Make sure you created the config with createConfig()."
28
+ );
29
+ }
30
+ useEffect(() => {
31
+ if (initializedRef.current)
32
+ return;
33
+ initializedRef.current = true;
34
+ if (config.autoConnect && typeof window !== "undefined") {
35
+ const state = config.store.getState();
36
+ if (state.connectorId && state.status === "disconnected") {
37
+ void state.reconnect(config.connectors);
38
+ }
39
+ }
40
+ }, [config]);
41
+ return /* @__PURE__ */ jsx(BtcWalletContext.Provider, { value: config, children });
42
+ }
43
+ function useAccount() {
44
+ const config = useConfig();
45
+ const { store } = config;
46
+ const state = useSyncExternalStore(
47
+ store.subscribe,
48
+ () => store.getState(),
49
+ () => store.getState()
50
+ );
51
+ return {
52
+ address: state.account?.address,
53
+ publicKey: state.account?.publicKey,
54
+ addressType: state.account?.type,
55
+ account: state.account ?? void 0,
56
+ connector: state.connector ?? void 0,
57
+ status: state.status,
58
+ isConnected: state.status === "connected",
59
+ isConnecting: state.status === "connecting",
60
+ isDisconnected: state.status === "disconnected",
61
+ isReconnecting: state.status === "reconnecting"
62
+ };
63
+ }
64
+ function useConnect() {
65
+ const config = useConfig();
66
+ const { store, connectors } = config;
67
+ const [state, setState] = useState({
68
+ isLoading: false,
69
+ isError: false,
70
+ isSuccess: false,
71
+ error: null
72
+ });
73
+ const connectAsync = useCallback(
74
+ async ({ connector, network }) => {
75
+ setState({
76
+ isLoading: true,
77
+ isError: false,
78
+ isSuccess: false,
79
+ error: null
80
+ });
81
+ try {
82
+ const account = await store.getState().connect(connector, network);
83
+ setState({
84
+ isLoading: false,
85
+ isError: false,
86
+ isSuccess: true,
87
+ error: null
88
+ });
89
+ return account;
90
+ } catch (error) {
91
+ setState({
92
+ isLoading: false,
93
+ isError: true,
94
+ isSuccess: false,
95
+ error
96
+ });
97
+ throw error;
98
+ }
99
+ },
100
+ [store]
101
+ );
102
+ const connect = useCallback(
103
+ (args) => {
104
+ connectAsync(args).catch(() => {
105
+ });
106
+ },
107
+ [connectAsync]
108
+ );
109
+ const reset = useCallback(() => {
110
+ setState({
111
+ isLoading: false,
112
+ isError: false,
113
+ isSuccess: false,
114
+ error: null
115
+ });
116
+ }, []);
117
+ return useMemo(
118
+ () => ({
119
+ connect,
120
+ connectAsync,
121
+ connectors,
122
+ error: state.error,
123
+ isLoading: state.isLoading,
124
+ isError: state.isError,
125
+ isSuccess: state.isSuccess,
126
+ reset
127
+ }),
128
+ [connect, connectAsync, connectors, state, reset]
129
+ );
130
+ }
131
+ function useDisconnect() {
132
+ const config = useConfig();
133
+ const { store } = config;
134
+ const [state, setState] = useState({
135
+ isLoading: false,
136
+ isError: false,
137
+ isSuccess: false,
138
+ error: null
139
+ });
140
+ const disconnectAsync = useCallback(async () => {
141
+ setState({
142
+ isLoading: true,
143
+ isError: false,
144
+ isSuccess: false,
145
+ error: null
146
+ });
147
+ try {
148
+ await store.getState().disconnect();
149
+ setState({
150
+ isLoading: false,
151
+ isError: false,
152
+ isSuccess: true,
153
+ error: null
154
+ });
155
+ } catch (error) {
156
+ setState({
157
+ isLoading: false,
158
+ isError: true,
159
+ isSuccess: false,
160
+ error
161
+ });
162
+ throw error;
163
+ }
164
+ }, [store]);
165
+ const disconnect = useCallback(() => {
166
+ disconnectAsync().catch(() => {
167
+ });
168
+ }, [disconnectAsync]);
169
+ return useMemo(
170
+ () => ({
171
+ disconnect,
172
+ disconnectAsync,
173
+ isLoading: state.isLoading,
174
+ isError: state.isError,
175
+ isSuccess: state.isSuccess,
176
+ error: state.error
177
+ }),
178
+ [disconnect, disconnectAsync, state]
179
+ );
180
+ }
181
+ function useNetwork() {
182
+ const config = useConfig();
183
+ const { store } = config;
184
+ const network = useSyncExternalStore(
185
+ store.subscribe,
186
+ () => store.getState().network,
187
+ () => store.getState().network
188
+ );
189
+ return { network };
190
+ }
191
+ function useSendTransaction() {
192
+ const config = useConfig();
193
+ const { store } = config;
194
+ const [state, setState] = useState({
195
+ data: void 0,
196
+ error: null,
197
+ isLoading: false,
198
+ isError: false,
199
+ isSuccess: false
200
+ });
201
+ const sendTransactionAsync = useCallback(
202
+ async ({ to, amount }) => {
203
+ const { connector } = store.getState();
204
+ if (!connector) {
205
+ throw new Error("Not connected");
206
+ }
207
+ setState({
208
+ data: void 0,
209
+ error: null,
210
+ isLoading: true,
211
+ isError: false,
212
+ isSuccess: false
213
+ });
214
+ try {
215
+ const txid = await connector.sendTransaction(to, amount);
216
+ setState({
217
+ data: txid,
218
+ error: null,
219
+ isLoading: false,
220
+ isError: false,
221
+ isSuccess: true
222
+ });
223
+ return txid;
224
+ } catch (error) {
225
+ setState({
226
+ data: void 0,
227
+ error,
228
+ isLoading: false,
229
+ isError: true,
230
+ isSuccess: false
231
+ });
232
+ throw error;
233
+ }
234
+ },
235
+ [store]
236
+ );
237
+ const sendTransaction = useCallback(
238
+ ({ to, amount }) => {
239
+ sendTransactionAsync({ to, amount }).catch(() => {
240
+ });
241
+ },
242
+ [sendTransactionAsync]
243
+ );
244
+ const reset = useCallback(() => {
245
+ setState({
246
+ data: void 0,
247
+ error: null,
248
+ isLoading: false,
249
+ isError: false,
250
+ isSuccess: false
251
+ });
252
+ }, []);
253
+ return useMemo(
254
+ () => ({
255
+ sendTransaction,
256
+ sendTransactionAsync,
257
+ data: state.data,
258
+ error: state.error,
259
+ isLoading: state.isLoading,
260
+ isError: state.isError,
261
+ isSuccess: state.isSuccess,
262
+ reset
263
+ }),
264
+ [sendTransaction, sendTransactionAsync, state, reset]
265
+ );
266
+ }
267
+ function useSignMessage() {
268
+ const config = useConfig();
269
+ const { store } = config;
270
+ const [state, setState] = useState({
271
+ data: void 0,
272
+ error: null,
273
+ isLoading: false,
274
+ isError: false,
275
+ isSuccess: false
276
+ });
277
+ const signMessageAsync = useCallback(
278
+ async ({ message }) => {
279
+ const { connector } = store.getState();
280
+ if (!connector) {
281
+ throw new Error("Not connected");
282
+ }
283
+ setState({
284
+ data: void 0,
285
+ error: null,
286
+ isLoading: true,
287
+ isError: false,
288
+ isSuccess: false
289
+ });
290
+ try {
291
+ const signature = await connector.signMessage(message);
292
+ setState({
293
+ data: signature,
294
+ error: null,
295
+ isLoading: false,
296
+ isError: false,
297
+ isSuccess: true
298
+ });
299
+ return signature;
300
+ } catch (error) {
301
+ setState({
302
+ data: void 0,
303
+ error,
304
+ isLoading: false,
305
+ isError: true,
306
+ isSuccess: false
307
+ });
308
+ throw error;
309
+ }
310
+ },
311
+ [store]
312
+ );
313
+ const signMessage = useCallback(
314
+ ({ message }) => {
315
+ signMessageAsync({ message }).catch(() => {
316
+ });
317
+ },
318
+ [signMessageAsync]
319
+ );
320
+ const reset = useCallback(() => {
321
+ setState({
322
+ data: void 0,
323
+ error: null,
324
+ isLoading: false,
325
+ isError: false,
326
+ isSuccess: false
327
+ });
328
+ }, []);
329
+ return useMemo(
330
+ () => ({
331
+ signMessage,
332
+ signMessageAsync,
333
+ data: state.data,
334
+ error: state.error,
335
+ isLoading: state.isLoading,
336
+ isError: state.isError,
337
+ isSuccess: state.isSuccess,
338
+ reset
339
+ }),
340
+ [signMessage, signMessageAsync, state, reset]
341
+ );
342
+ }
343
+ function useSignPsbt() {
344
+ const config = useConfig();
345
+ const { store } = config;
346
+ const [state, setState] = useState({
347
+ data: void 0,
348
+ error: null,
349
+ isLoading: false,
350
+ isError: false,
351
+ isSuccess: false
352
+ });
353
+ const signPsbtAsync = useCallback(
354
+ async ({ psbt, options }) => {
355
+ const { connector } = store.getState();
356
+ if (!connector) {
357
+ throw new Error("Not connected");
358
+ }
359
+ setState({
360
+ data: void 0,
361
+ error: null,
362
+ isLoading: true,
363
+ isError: false,
364
+ isSuccess: false
365
+ });
366
+ try {
367
+ const signedPsbt = await connector.signPsbt(psbt, options);
368
+ setState({
369
+ data: signedPsbt,
370
+ error: null,
371
+ isLoading: false,
372
+ isError: false,
373
+ isSuccess: true
374
+ });
375
+ return signedPsbt;
376
+ } catch (error) {
377
+ setState({
378
+ data: void 0,
379
+ error,
380
+ isLoading: false,
381
+ isError: true,
382
+ isSuccess: false
383
+ });
384
+ throw error;
385
+ }
386
+ },
387
+ [store]
388
+ );
389
+ const signPsbt = useCallback(
390
+ ({ psbt, options }) => {
391
+ const args = options !== void 0 ? { psbt, options } : { psbt };
392
+ signPsbtAsync(args).catch(() => {
393
+ });
394
+ },
395
+ [signPsbtAsync]
396
+ );
397
+ const reset = useCallback(() => {
398
+ setState({
399
+ data: void 0,
400
+ error: null,
401
+ isLoading: false,
402
+ isError: false,
403
+ isSuccess: false
404
+ });
405
+ }, []);
406
+ return useMemo(
407
+ () => ({
408
+ signPsbt,
409
+ signPsbtAsync,
410
+ data: state.data,
411
+ error: state.error,
412
+ isLoading: state.isLoading,
413
+ isError: state.isError,
414
+ isSuccess: state.isSuccess,
415
+ reset
416
+ }),
417
+ [signPsbt, signPsbtAsync, state, reset]
418
+ );
419
+ }
420
+ function useSignPsbts() {
421
+ const config = useConfig();
422
+ const { store } = config;
423
+ const [state, setState] = useState({
424
+ data: void 0,
425
+ error: null,
426
+ isLoading: false,
427
+ isError: false,
428
+ isSuccess: false
429
+ });
430
+ const isSupported = useMemo(() => {
431
+ const { connector } = store.getState();
432
+ return typeof connector?.signPsbts === "function";
433
+ }, [store]);
434
+ const signPsbtsAsync = useCallback(
435
+ async ({
436
+ psbts,
437
+ options
438
+ }) => {
439
+ const { connector } = store.getState();
440
+ if (!connector) {
441
+ throw new Error("Not connected");
442
+ }
443
+ if (!connector.signPsbts) {
444
+ throw new Error("Batch signing is not supported by this wallet");
445
+ }
446
+ setState({
447
+ data: void 0,
448
+ error: null,
449
+ isLoading: true,
450
+ isError: false,
451
+ isSuccess: false
452
+ });
453
+ try {
454
+ const signedPsbts = await connector.signPsbts(psbts, options);
455
+ setState({
456
+ data: signedPsbts,
457
+ error: null,
458
+ isLoading: false,
459
+ isError: false,
460
+ isSuccess: true
461
+ });
462
+ return signedPsbts;
463
+ } catch (error) {
464
+ setState({
465
+ data: void 0,
466
+ error,
467
+ isLoading: false,
468
+ isError: true,
469
+ isSuccess: false
470
+ });
471
+ throw error;
472
+ }
473
+ },
474
+ [store]
475
+ );
476
+ const signPsbts = useCallback(
477
+ ({ psbts, options }) => {
478
+ const args = options !== void 0 ? { psbts, options } : { psbts };
479
+ signPsbtsAsync(args).catch(() => {
480
+ });
481
+ },
482
+ [signPsbtsAsync]
483
+ );
484
+ const reset = useCallback(() => {
485
+ setState({
486
+ data: void 0,
487
+ error: null,
488
+ isLoading: false,
489
+ isError: false,
490
+ isSuccess: false
491
+ });
492
+ }, []);
493
+ return useMemo(
494
+ () => ({
495
+ signPsbts,
496
+ signPsbtsAsync,
497
+ data: state.data,
498
+ error: state.error,
499
+ isLoading: state.isLoading,
500
+ isError: state.isError,
501
+ isSuccess: state.isSuccess,
502
+ isSupported,
503
+ reset
504
+ }),
505
+ [signPsbts, signPsbtsAsync, state, isSupported, reset]
506
+ );
507
+ }
508
+ function useMultiAddress() {
509
+ const config = useConfig();
510
+ const { store } = config;
511
+ const [addresses, setAddresses] = useState([]);
512
+ const [primaryAddress, setPrimaryAddressState] = useState(null);
513
+ const [isLoading, setIsLoading] = useState(false);
514
+ const fetchAddresses = useCallback(async () => {
515
+ const { connector } = store.getState();
516
+ if (!connector) {
517
+ setAddresses([]);
518
+ setPrimaryAddressState(null);
519
+ return;
520
+ }
521
+ setIsLoading(true);
522
+ try {
523
+ const accounts = await connector.getAccounts();
524
+ setAddresses(accounts);
525
+ if (accounts.length > 0 && !primaryAddress) {
526
+ setPrimaryAddressState(accounts[0] ?? null);
527
+ }
528
+ } catch {
529
+ setAddresses([]);
530
+ } finally {
531
+ setIsLoading(false);
532
+ }
533
+ }, [store, primaryAddress]);
534
+ useEffect(() => {
535
+ const unsubscribe = store.subscribe(
536
+ (state) => state.connector,
537
+ () => {
538
+ void fetchAddresses();
539
+ }
540
+ );
541
+ void fetchAddresses();
542
+ return unsubscribe;
543
+ }, [store, fetchAddresses]);
544
+ const { paymentAddress, ordinalsAddress } = useMemo(() => {
545
+ const payment = addresses.find(
546
+ (a) => a.type === "segwit" || a.type === "nested-segwit"
547
+ ) ?? addresses[0] ?? null;
548
+ const ordinals = addresses.find((a) => a.type === "taproot") ?? null;
549
+ return { paymentAddress: payment, ordinalsAddress: ordinals };
550
+ }, [addresses]);
551
+ const setPrimaryAddress = useCallback((address) => {
552
+ setPrimaryAddressState(address);
553
+ }, []);
554
+ const refresh = useCallback(async () => {
555
+ await fetchAddresses();
556
+ }, [fetchAddresses]);
557
+ return useMemo(
558
+ () => ({
559
+ addresses,
560
+ paymentAddress,
561
+ ordinalsAddress,
562
+ primaryAddress,
563
+ setPrimaryAddress,
564
+ isLoading,
565
+ refresh
566
+ }),
567
+ [addresses, paymentAddress, ordinalsAddress, primaryAddress, setPrimaryAddress, isLoading, refresh]
568
+ );
569
+ }
570
+
571
+ export { BtcWalletContext, BtcWalletProvider, useAccount, useConfig, useConnect, useDisconnect, useMultiAddress, useNetwork, useSendTransaction, useSignMessage, useSignPsbt, useSignPsbts };
572
+ //# sourceMappingURL=out.js.map
573
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/provider.tsx","../src/context.tsx","../src/hooks/useAccount.ts","../src/hooks/useConnect.ts","../src/hooks/useDisconnect.ts","../src/hooks/useNetwork.ts","../src/hooks/useSendTransaction.ts","../src/hooks/useSignMessage.ts","../src/hooks/useSignPsbt.ts","../src/hooks/useSignPsbts.ts","../src/hooks/useMultiAddress.ts"],"names":["useCallback","useMemo","useState","useSyncExternalStore","useEffect"],"mappings":"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","sourcesContent":["import { type ReactNode, useEffect, useRef } from 'react';\nimport type { ResolvedConfig } from 'otx-btc-wallet-core';\nimport { BtcWalletContext } from './context';\n\nexport interface BtcWalletProviderProps {\n /** Configuration created with createConfig() */\n config: ResolvedConfig;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Provider component for otx-btc-wallet\n *\n * @example\n * ```tsx\n * import { BtcWalletProvider } from 'otx-btc-wallet-react';\n * import { config } from './config';\n *\n * function App() {\n * return (\n * <BtcWalletProvider config={config}>\n * <YourApp />\n * </BtcWalletProvider>\n * );\n * }\n * ```\n */\nexport function BtcWalletProvider({\n config,\n children,\n}: BtcWalletProviderProps): ReactNode {\n const initializedRef = useRef(false);\n\n // Validate config\n if (!config) {\n throw new Error(\n 'BtcWalletProvider requires a config prop. ' +\n 'Create one with createConfig() from otx-btc-wallet-core.'\n );\n }\n\n if (!config.store) {\n throw new Error(\n 'Invalid config: missing store. ' +\n 'Make sure you created the config with createConfig().'\n );\n }\n\n // Handle auto-reconnect on mount\n useEffect(() => {\n if (initializedRef.current) return;\n initializedRef.current = true;\n\n // Auto-reconnect is handled by createConfig, but we can\n // trigger it here if needed for SSR hydration\n if (config.autoConnect && typeof window !== 'undefined') {\n const state = config.store.getState();\n if (state.connectorId && state.status === 'disconnected') {\n void state.reconnect(config.connectors);\n }\n }\n }, [config]);\n\n return (\n <BtcWalletContext.Provider value={config}>\n {children}\n </BtcWalletContext.Provider>\n );\n}\n","import { createContext, useContext } from 'react';\nimport type { ResolvedConfig } from 'otx-btc-wallet-core';\n\n/**\n * Context for otx-btc-wallet configuration\n */\nexport const BtcWalletContext = createContext<ResolvedConfig | null>(null);\n\n/**\n * Hook to access the otx-btc-wallet config\n * @throws Error if used outside of BtcWalletProvider\n */\nexport function useConfig(): ResolvedConfig {\n const config = useContext(BtcWalletContext);\n\n if (!config) {\n throw new Error(\n 'useConfig must be used within a BtcWalletProvider. ' +\n 'Wrap your app in <BtcWalletProvider config={config}>.'\n );\n }\n\n return config;\n}\n","import { useSyncExternalStore } from 'react';\nimport type {\n WalletAccount,\n BitcoinConnector,\n ConnectionStatus,\n AddressType,\n} from 'otx-btc-wallet-core';\nimport { useConfig } from '../context';\n\nexport interface UseAccountReturn {\n /** Connected address */\n address: string | undefined;\n /** Connected public key */\n publicKey: string | undefined;\n /** Address type */\n addressType: AddressType | undefined;\n /** Full account object */\n account: WalletAccount | undefined;\n /** Active connector */\n connector: BitcoinConnector | undefined;\n /** Connection status */\n status: ConnectionStatus;\n /** Is connected */\n isConnected: boolean;\n /** Is connecting */\n isConnecting: boolean;\n /** Is disconnected */\n isDisconnected: boolean;\n /** Is reconnecting */\n isReconnecting: boolean;\n}\n\n/**\n * Hook to get current account state\n *\n * @example\n * ```tsx\n * function Profile() {\n * const { address, isConnected, connector } = useAccount();\n *\n * if (!isConnected) return <div>Not connected</div>;\n *\n * return (\n * <div>\n * <p>Address: {address}</p>\n * <p>Connected via {connector?.name}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useAccount(): UseAccountReturn {\n const config = useConfig();\n const { store } = config;\n\n const state = useSyncExternalStore(\n store.subscribe,\n () => store.getState(),\n () => store.getState()\n );\n\n return {\n address: state.account?.address,\n publicKey: state.account?.publicKey,\n addressType: state.account?.type,\n account: state.account ?? undefined,\n connector: state.connector ?? undefined,\n status: state.status,\n isConnected: state.status === 'connected',\n isConnecting: state.status === 'connecting',\n isDisconnected: state.status === 'disconnected',\n isReconnecting: state.status === 'reconnecting',\n };\n}\n","import { useCallback, useMemo, useState } from 'react';\nimport type {\n BitcoinConnector,\n BitcoinNetwork,\n WalletAccount,\n} from 'otx-btc-wallet-core';\nimport { useConfig } from '../context';\n\nexport type ConnectArgs = {\n connector: BitcoinConnector;\n network?: BitcoinNetwork;\n};\n\nexport interface UseConnectReturn {\n /** Connect to a wallet (fire-and-forget) */\n connect: (args: ConnectArgs) => void;\n /** Connect to a wallet (returns promise) */\n connectAsync: (args: ConnectArgs) => Promise<WalletAccount>;\n /** Available connectors */\n connectors: BitcoinConnector[];\n /** Last error */\n error: Error | null;\n /** Is currently connecting */\n isLoading: boolean;\n /** Did connection fail */\n isError: boolean;\n /** Did connection succeed */\n isSuccess: boolean;\n /** Reset state */\n reset: () => void;\n}\n\n/**\n * Hook to connect to a wallet\n *\n * @example\n * ```tsx\n * function ConnectButtons() {\n * const { connect, connectors, isLoading, error } = useConnect();\n *\n * return (\n * <div>\n * {connectors.map((connector) => (\n * <button\n * key={connector.id}\n * onClick={() => connect({ connector })}\n * disabled={isLoading}\n * >\n * Connect {connector.name}\n * </button>\n * ))}\n * {error && <p>Error: {error.message}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useConnect(): UseConnectReturn {\n const config = useConfig();\n const { store, connectors } = config;\n\n const [state, setState] = useState<{\n isLoading: boolean;\n isError: boolean;\n isSuccess: boolean;\n error: Error | null;\n }>({\n isLoading: false,\n isError: false,\n isSuccess: false,\n error: null,\n });\n\n const connectAsync = useCallback(\n async ({ connector, network }: ConnectArgs) => {\n setState({\n isLoading: true,\n isError: false,\n isSuccess: false,\n error: null,\n });\n\n try {\n const account = await store.getState().connect(connector, network);\n setState({\n isLoading: false,\n isError: false,\n isSuccess: true,\n error: null,\n });\n return account;\n } catch (error) {\n setState({\n isLoading: false,\n isError: true,\n isSuccess: false,\n error: error as Error,\n });\n throw error;\n }\n },\n [store]\n );\n\n const connect = useCallback(\n (args: ConnectArgs) => {\n connectAsync(args).catch(() => {\n // Error is already captured in state\n });\n },\n [connectAsync]\n );\n\n const reset = useCallback(() => {\n setState({\n isLoading: false,\n isError: false,\n isSuccess: false,\n error: null,\n });\n }, []);\n\n return useMemo(\n () => ({\n connect,\n connectAsync,\n connectors,\n error: state.error,\n isLoading: state.isLoading,\n isError: state.isError,\n isSuccess: state.isSuccess,\n reset,\n }),\n [connect, connectAsync, connectors, state, reset]\n );\n}\n","import { useCallback, useMemo, useState } from 'react';\nimport { useConfig } from '../context';\n\nexport interface UseDisconnectReturn {\n /** Disconnect from wallet (fire-and-forget) */\n disconnect: () => void;\n /** Disconnect from wallet (returns promise) */\n disconnectAsync: () => Promise<void>;\n /** Is currently disconnecting */\n isLoading: boolean;\n /** Did disconnect fail */\n isError: boolean;\n /** Did disconnect succeed */\n isSuccess: boolean;\n /** Last error */\n error: Error | null;\n}\n\n/**\n * Hook to disconnect from wallet\n *\n * @example\n * ```tsx\n * function DisconnectButton() {\n * const { disconnect, isLoading } = useDisconnect();\n *\n * return (\n * <button onClick={disconnect} disabled={isLoading}>\n * Disconnect\n * </button>\n * );\n * }\n * ```\n */\nexport function useDisconnect(): UseDisconnectReturn {\n const config = useConfig();\n const { store } = config;\n\n const [state, setState] = useState<{\n isLoading: boolean;\n isError: boolean;\n isSuccess: boolean;\n error: Error | null;\n }>({\n isLoading: false,\n isError: false,\n isSuccess: false,\n error: null,\n });\n\n const disconnectAsync = useCallback(async () => {\n setState({\n isLoading: true,\n isError: false,\n isSuccess: false,\n error: null,\n });\n\n try {\n await store.getState().disconnect();\n setState({\n isLoading: false,\n isError: false,\n isSuccess: true,\n error: null,\n });\n } catch (error) {\n setState({\n isLoading: false,\n isError: true,\n isSuccess: false,\n error: error as Error,\n });\n throw error;\n }\n }, [store]);\n\n const disconnect = useCallback(() => {\n disconnectAsync().catch(() => {\n // Error is already captured in state\n });\n }, [disconnectAsync]);\n\n return useMemo(\n () => ({\n disconnect,\n disconnectAsync,\n isLoading: state.isLoading,\n isError: state.isError,\n isSuccess: state.isSuccess,\n error: state.error,\n }),\n [disconnect, disconnectAsync, state]\n );\n}\n","import { useSyncExternalStore } from 'react';\nimport type { BitcoinNetwork } from 'otx-btc-wallet-core';\nimport { useConfig } from '../context';\n\nexport interface UseNetworkReturn {\n /** Current network */\n network: BitcoinNetwork;\n}\n\n/**\n * Hook to get current network\n *\n * @example\n * ```tsx\n * function NetworkInfo() {\n * const { network } = useNetwork();\n *\n * return <p>Network: {network}</p>;\n * }\n * ```\n */\nexport function useNetwork(): UseNetworkReturn {\n const config = useConfig();\n const { store } = config;\n\n const network = useSyncExternalStore(\n store.subscribe,\n () => store.getState().network,\n () => store.getState().network\n );\n\n return { network };\n}\n","import { useCallback, useMemo, useState } from 'react';\nimport { useConfig } from '../context';\n\nexport interface UseSendTransactionReturn {\n /** Send transaction (fire-and-forget) */\n sendTransaction: (args: { to: string; amount: number }) => void;\n /** Send transaction (returns promise with txid) */\n sendTransactionAsync: (args: { to: string; amount: number }) => Promise<string>;\n /** Transaction ID */\n data: string | undefined;\n /** Last error */\n error: Error | null;\n /** Is sending */\n isLoading: boolean;\n /** Did send fail */\n isError: boolean;\n /** Did send succeed */\n isSuccess: boolean;\n /** Reset state */\n reset: () => void;\n}\n\n/**\n * Hook to send a Bitcoin transaction\n *\n * @example\n * ```tsx\n * function SendForm() {\n * const { sendTransaction, isLoading, data, error } = useSendTransaction();\n *\n * const handleSend = () => {\n * sendTransaction({ to: 'bc1q...', amount: 10000 }); // 10000 sats\n * };\n *\n * return (\n * <div>\n * <button onClick={handleSend} disabled={isLoading}>\n * Send 10,000 sats\n * </button>\n * {data && <p>TX: {data}</p>}\n * {error && <p>Error: {error.message}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useSendTransaction(): UseSendTransactionReturn {\n const config = useConfig();\n const { store } = config;\n\n const [state, setState] = useState<{\n data: string | undefined;\n error: Error | null;\n isLoading: boolean;\n isError: boolean;\n isSuccess: boolean;\n }>({\n data: undefined,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: false,\n });\n\n const sendTransactionAsync = useCallback(\n async ({ to, amount }: { to: string; amount: number }) => {\n const { connector } = store.getState();\n\n if (!connector) {\n throw new Error('Not connected');\n }\n\n setState({\n data: undefined,\n error: null,\n isLoading: true,\n isError: false,\n isSuccess: false,\n });\n\n try {\n const txid = await connector.sendTransaction(to, amount);\n setState({\n data: txid,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: true,\n });\n return txid;\n } catch (error) {\n setState({\n data: undefined,\n error: error as Error,\n isLoading: false,\n isError: true,\n isSuccess: false,\n });\n throw error;\n }\n },\n [store]\n );\n\n const sendTransaction = useCallback(\n ({ to, amount }: { to: string; amount: number }) => {\n sendTransactionAsync({ to, amount }).catch(() => {\n // Error is already captured in state\n });\n },\n [sendTransactionAsync]\n );\n\n const reset = useCallback(() => {\n setState({\n data: undefined,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: false,\n });\n }, []);\n\n return useMemo(\n () => ({\n sendTransaction,\n sendTransactionAsync,\n data: state.data,\n error: state.error,\n isLoading: state.isLoading,\n isError: state.isError,\n isSuccess: state.isSuccess,\n reset,\n }),\n [sendTransaction, sendTransactionAsync, state, reset]\n );\n}\n","import { useCallback, useMemo, useState } from 'react';\nimport { useConfig } from '../context';\n\nexport interface UseSignMessageReturn {\n /** Sign message (fire-and-forget) */\n signMessage: (args: { message: string }) => void;\n /** Sign message (returns promise with signature) */\n signMessageAsync: (args: { message: string }) => Promise<string>;\n /** Signature */\n data: string | undefined;\n /** Last error */\n error: Error | null;\n /** Is signing */\n isLoading: boolean;\n /** Did signing fail */\n isError: boolean;\n /** Did signing succeed */\n isSuccess: boolean;\n /** Reset state */\n reset: () => void;\n}\n\n/**\n * Hook to sign a message\n *\n * @example\n * ```tsx\n * function SignMessage() {\n * const { signMessage, isLoading, data } = useSignMessage();\n *\n * const handleSign = () => {\n * signMessage({ message: 'Hello, Bitcoin!' });\n * };\n *\n * return (\n * <div>\n * <button onClick={handleSign} disabled={isLoading}>\n * Sign Message\n * </button>\n * {data && <p>Signature: {data}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useSignMessage(): UseSignMessageReturn {\n const config = useConfig();\n const { store } = config;\n\n const [state, setState] = useState<{\n data: string | undefined;\n error: Error | null;\n isLoading: boolean;\n isError: boolean;\n isSuccess: boolean;\n }>({\n data: undefined,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: false,\n });\n\n const signMessageAsync = useCallback(\n async ({ message }: { message: string }) => {\n const { connector } = store.getState();\n\n if (!connector) {\n throw new Error('Not connected');\n }\n\n setState({\n data: undefined,\n error: null,\n isLoading: true,\n isError: false,\n isSuccess: false,\n });\n\n try {\n const signature = await connector.signMessage(message);\n setState({\n data: signature,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: true,\n });\n return signature;\n } catch (error) {\n setState({\n data: undefined,\n error: error as Error,\n isLoading: false,\n isError: true,\n isSuccess: false,\n });\n throw error;\n }\n },\n [store]\n );\n\n const signMessage = useCallback(\n ({ message }: { message: string }) => {\n signMessageAsync({ message }).catch(() => {\n // Error is already captured in state\n });\n },\n [signMessageAsync]\n );\n\n const reset = useCallback(() => {\n setState({\n data: undefined,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: false,\n });\n }, []);\n\n return useMemo(\n () => ({\n signMessage,\n signMessageAsync,\n data: state.data,\n error: state.error,\n isLoading: state.isLoading,\n isError: state.isError,\n isSuccess: state.isSuccess,\n reset,\n }),\n [signMessage, signMessageAsync, state, reset]\n );\n}\n","import { useCallback, useMemo, useState } from 'react';\nimport type { SignPsbtOptions } from 'otx-btc-wallet-core';\nimport { useConfig } from '../context';\n\nexport interface UseSignPsbtReturn {\n /** Sign PSBT (fire-and-forget) */\n signPsbt: (args: { psbt: string; options?: SignPsbtOptions }) => void;\n /** Sign PSBT (returns promise with signed PSBT hex) */\n signPsbtAsync: (args: {\n psbt: string;\n options?: SignPsbtOptions;\n }) => Promise<string>;\n /** Signed PSBT hex */\n data: string | undefined;\n /** Last error */\n error: Error | null;\n /** Is signing */\n isLoading: boolean;\n /** Did signing fail */\n isError: boolean;\n /** Did signing succeed */\n isSuccess: boolean;\n /** Reset state */\n reset: () => void;\n}\n\n/**\n * Hook to sign a PSBT\n *\n * @example\n * ```tsx\n * function SignPsbt() {\n * const { signPsbt, isLoading, data } = useSignPsbt();\n *\n * const handleSign = () => {\n * signPsbt({\n * psbt: '70736274ff01...',\n * options: { autoFinalize: true }\n * });\n * };\n *\n * return (\n * <div>\n * <button onClick={handleSign} disabled={isLoading}>\n * Sign PSBT\n * </button>\n * {data && <p>Signed: {data.slice(0, 20)}...</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useSignPsbt(): UseSignPsbtReturn {\n const config = useConfig();\n const { store } = config;\n\n const [state, setState] = useState<{\n data: string | undefined;\n error: Error | null;\n isLoading: boolean;\n isError: boolean;\n isSuccess: boolean;\n }>({\n data: undefined,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: false,\n });\n\n const signPsbtAsync = useCallback(\n async ({ psbt, options }: { psbt: string; options?: SignPsbtOptions }) => {\n const { connector } = store.getState();\n\n if (!connector) {\n throw new Error('Not connected');\n }\n\n setState({\n data: undefined,\n error: null,\n isLoading: true,\n isError: false,\n isSuccess: false,\n });\n\n try {\n const signedPsbt = await connector.signPsbt(psbt, options);\n setState({\n data: signedPsbt,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: true,\n });\n return signedPsbt;\n } catch (error) {\n setState({\n data: undefined,\n error: error as Error,\n isLoading: false,\n isError: true,\n isSuccess: false,\n });\n throw error;\n }\n },\n [store]\n );\n\n const signPsbt = useCallback(\n ({ psbt, options }: { psbt: string; options?: SignPsbtOptions }) => {\n const args = options !== undefined ? { psbt, options } : { psbt };\n signPsbtAsync(args).catch(() => {\n // Error is already captured in state\n });\n },\n [signPsbtAsync]\n );\n\n const reset = useCallback(() => {\n setState({\n data: undefined,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: false,\n });\n }, []);\n\n return useMemo(\n () => ({\n signPsbt,\n signPsbtAsync,\n data: state.data,\n error: state.error,\n isLoading: state.isLoading,\n isError: state.isError,\n isSuccess: state.isSuccess,\n reset,\n }),\n [signPsbt, signPsbtAsync, state, reset]\n );\n}\n","import { useCallback, useMemo, useState } from 'react';\nimport type { SignPsbtOptions } from 'otx-btc-wallet-core';\nimport { useConfig } from '../context';\n\nexport interface UseSignPsbtsReturn {\n /** Sign multiple PSBTs (fire-and-forget) */\n signPsbts: (args: { psbts: string[]; options?: SignPsbtOptions }) => void;\n /** Sign multiple PSBTs (returns promise with signed PSBT hexes) */\n signPsbtsAsync: (args: {\n psbts: string[];\n options?: SignPsbtOptions;\n }) => Promise<string[]>;\n /** Signed PSBT hexes */\n data: string[] | undefined;\n /** Last error */\n error: Error | null;\n /** Is signing */\n isLoading: boolean;\n /** Did signing fail */\n isError: boolean;\n /** Did signing succeed */\n isSuccess: boolean;\n /** Is batch signing supported by current connector */\n isSupported: boolean;\n /** Reset state */\n reset: () => void;\n}\n\n/**\n * Hook to sign multiple PSBTs (batch signing)\n *\n * @example\n * ```tsx\n * function BatchSign() {\n * const { signPsbts, isLoading, isSupported, data } = useSignPsbts();\n *\n * if (!isSupported) {\n * return <p>Batch signing not supported by this wallet</p>;\n * }\n *\n * const handleSign = () => {\n * signPsbts({\n * psbts: ['70736274ff01...', '70736274ff02...'],\n * options: { autoFinalize: true }\n * });\n * };\n *\n * return (\n * <button onClick={handleSign} disabled={isLoading}>\n * Sign {2} PSBTs\n * </button>\n * );\n * }\n * ```\n */\nexport function useSignPsbts(): UseSignPsbtsReturn {\n const config = useConfig();\n const { store } = config;\n\n const [state, setState] = useState<{\n data: string[] | undefined;\n error: Error | null;\n isLoading: boolean;\n isError: boolean;\n isSuccess: boolean;\n }>({\n data: undefined,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: false,\n });\n\n // Check if current connector supports batch signing\n const isSupported = useMemo(() => {\n const { connector } = store.getState();\n return typeof connector?.signPsbts === 'function';\n }, [store]);\n\n const signPsbtsAsync = useCallback(\n async ({\n psbts,\n options,\n }: {\n psbts: string[];\n options?: SignPsbtOptions;\n }) => {\n const { connector } = store.getState();\n\n if (!connector) {\n throw new Error('Not connected');\n }\n\n if (!connector.signPsbts) {\n throw new Error('Batch signing is not supported by this wallet');\n }\n\n setState({\n data: undefined,\n error: null,\n isLoading: true,\n isError: false,\n isSuccess: false,\n });\n\n try {\n const signedPsbts = await connector.signPsbts(psbts, options);\n setState({\n data: signedPsbts,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: true,\n });\n return signedPsbts;\n } catch (error) {\n setState({\n data: undefined,\n error: error as Error,\n isLoading: false,\n isError: true,\n isSuccess: false,\n });\n throw error;\n }\n },\n [store]\n );\n\n const signPsbts = useCallback(\n ({ psbts, options }: { psbts: string[]; options?: SignPsbtOptions }) => {\n const args = options !== undefined ? { psbts, options } : { psbts };\n signPsbtsAsync(args).catch(() => {\n // Error is already captured in state\n });\n },\n [signPsbtsAsync]\n );\n\n const reset = useCallback(() => {\n setState({\n data: undefined,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: false,\n });\n }, []);\n\n return useMemo(\n () => ({\n signPsbts,\n signPsbtsAsync,\n data: state.data,\n error: state.error,\n isLoading: state.isLoading,\n isError: state.isError,\n isSuccess: state.isSuccess,\n isSupported,\n reset,\n }),\n [signPsbts, signPsbtsAsync, state, isSupported, reset]\n );\n}\n","import { useCallback, useMemo, useState, useEffect } from 'react';\nimport type { WalletAccount } from 'otx-btc-wallet-core';\nimport { useConfig } from '../context';\n\nexport interface UseMultiAddressReturn {\n /** All available addresses from the wallet */\n addresses: WalletAccount[];\n /** Payment address (for sending/receiving BTC) */\n paymentAddress: WalletAccount | null;\n /** Ordinals address (for NFTs/inscriptions) */\n ordinalsAddress: WalletAccount | null;\n /** Currently selected primary address */\n primaryAddress: WalletAccount | null;\n /** Set the primary address */\n setPrimaryAddress: (address: WalletAccount) => void;\n /** Is loading addresses */\n isLoading: boolean;\n /** Refresh addresses from wallet */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook to manage multiple addresses from a connected wallet\n *\n * Xverse and Leather wallets provide both payment and ordinals addresses.\n * This hook helps manage and switch between them.\n *\n * @example\n * ```tsx\n * function MultiAddressDisplay() {\n * const {\n * paymentAddress,\n * ordinalsAddress,\n * primaryAddress,\n * setPrimaryAddress\n * } = useMultiAddress();\n *\n * return (\n * <div>\n * <h3>Payment: {paymentAddress?.address}</h3>\n * <h3>Ordinals: {ordinalsAddress?.address}</h3>\n * <select onChange={(e) => {\n * const addr = e.target.value === 'payment' ? paymentAddress : ordinalsAddress;\n * if (addr) setPrimaryAddress(addr);\n * }}>\n * <option value=\"payment\">Payment</option>\n * <option value=\"ordinals\">Ordinals</option>\n * </select>\n * </div>\n * );\n * }\n * ```\n */\nexport function useMultiAddress(): UseMultiAddressReturn {\n const config = useConfig();\n const { store } = config;\n\n const [addresses, setAddresses] = useState<WalletAccount[]>([]);\n const [primaryAddress, setPrimaryAddressState] = useState<WalletAccount | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n // Fetch addresses from connector\n const fetchAddresses = useCallback(async () => {\n const { connector } = store.getState();\n if (!connector) {\n setAddresses([]);\n setPrimaryAddressState(null);\n return;\n }\n\n setIsLoading(true);\n try {\n const accounts = await connector.getAccounts();\n setAddresses(accounts);\n\n // Set primary address to first one if not set\n if (accounts.length > 0 && !primaryAddress) {\n setPrimaryAddressState(accounts[0] ?? null);\n }\n } catch {\n setAddresses([]);\n } finally {\n setIsLoading(false);\n }\n }, [store, primaryAddress]);\n\n // Fetch addresses when connector changes\n useEffect(() => {\n const unsubscribe = store.subscribe(\n (state) => state.connector,\n () => {\n void fetchAddresses();\n }\n );\n\n // Initial fetch\n void fetchAddresses();\n\n return unsubscribe;\n }, [store, fetchAddresses]);\n\n // Derive payment and ordinals addresses\n const { paymentAddress, ordinalsAddress } = useMemo(() => {\n // Payment addresses are typically segwit (bc1q) or nested-segwit (3)\n const payment = addresses.find(\n (a) => a.type === 'segwit' || a.type === 'nested-segwit'\n ) ?? addresses[0] ?? null;\n\n // Ordinals addresses are typically taproot (bc1p)\n const ordinals = addresses.find((a) => a.type === 'taproot') ?? null;\n\n return { paymentAddress: payment, ordinalsAddress: ordinals };\n }, [addresses]);\n\n const setPrimaryAddress = useCallback((address: WalletAccount) => {\n setPrimaryAddressState(address);\n }, []);\n\n const refresh = useCallback(async () => {\n await fetchAddresses();\n }, [fetchAddresses]);\n\n return useMemo(\n () => ({\n addresses,\n paymentAddress,\n ordinalsAddress,\n primaryAddress,\n setPrimaryAddress,\n isLoading,\n refresh,\n }),\n [addresses, paymentAddress, ordinalsAddress, primaryAddress, setPrimaryAddress, isLoading, refresh]\n );\n}\n"]}