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/README.md +726 -0
- package/dist/index.d.mts +436 -0
- package/dist/index.d.ts +436 -0
- package/dist/index.js +586 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +573 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +45 -0
- package/src/context.tsx +24 -0
- package/src/hooks/useAccount.ts +74 -0
- package/src/hooks/useConnect.ts +136 -0
- package/src/hooks/useDisconnect.ts +95 -0
- package/src/hooks/useMultiAddress.ts +135 -0
- package/src/hooks/useNetwork.ts +33 -0
- package/src/hooks/useSendTransaction.ts +137 -0
- package/src/hooks/useSignMessage.ts +136 -0
- package/src/hooks/useSignPsbt.ts +144 -0
- package/src/hooks/useSignPsbts.ts +164 -0
- package/src/index.ts +31 -0
- package/src/provider.tsx +70 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
2
|
+
import { useConfig } from '../context';
|
|
3
|
+
|
|
4
|
+
export interface UseSignMessageReturn {
|
|
5
|
+
/** Sign message (fire-and-forget) */
|
|
6
|
+
signMessage: (args: { message: string }) => void;
|
|
7
|
+
/** Sign message (returns promise with signature) */
|
|
8
|
+
signMessageAsync: (args: { message: string }) => Promise<string>;
|
|
9
|
+
/** Signature */
|
|
10
|
+
data: string | undefined;
|
|
11
|
+
/** Last error */
|
|
12
|
+
error: Error | null;
|
|
13
|
+
/** Is signing */
|
|
14
|
+
isLoading: boolean;
|
|
15
|
+
/** Did signing fail */
|
|
16
|
+
isError: boolean;
|
|
17
|
+
/** Did signing succeed */
|
|
18
|
+
isSuccess: boolean;
|
|
19
|
+
/** Reset state */
|
|
20
|
+
reset: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Hook to sign a message
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* function SignMessage() {
|
|
29
|
+
* const { signMessage, isLoading, data } = useSignMessage();
|
|
30
|
+
*
|
|
31
|
+
* const handleSign = () => {
|
|
32
|
+
* signMessage({ message: 'Hello, Bitcoin!' });
|
|
33
|
+
* };
|
|
34
|
+
*
|
|
35
|
+
* return (
|
|
36
|
+
* <div>
|
|
37
|
+
* <button onClick={handleSign} disabled={isLoading}>
|
|
38
|
+
* Sign Message
|
|
39
|
+
* </button>
|
|
40
|
+
* {data && <p>Signature: {data}</p>}
|
|
41
|
+
* </div>
|
|
42
|
+
* );
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function useSignMessage(): UseSignMessageReturn {
|
|
47
|
+
const config = useConfig();
|
|
48
|
+
const { store } = config;
|
|
49
|
+
|
|
50
|
+
const [state, setState] = useState<{
|
|
51
|
+
data: string | undefined;
|
|
52
|
+
error: Error | null;
|
|
53
|
+
isLoading: boolean;
|
|
54
|
+
isError: boolean;
|
|
55
|
+
isSuccess: boolean;
|
|
56
|
+
}>({
|
|
57
|
+
data: undefined,
|
|
58
|
+
error: null,
|
|
59
|
+
isLoading: false,
|
|
60
|
+
isError: false,
|
|
61
|
+
isSuccess: false,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const signMessageAsync = useCallback(
|
|
65
|
+
async ({ message }: { message: string }) => {
|
|
66
|
+
const { connector } = store.getState();
|
|
67
|
+
|
|
68
|
+
if (!connector) {
|
|
69
|
+
throw new Error('Not connected');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
setState({
|
|
73
|
+
data: undefined,
|
|
74
|
+
error: null,
|
|
75
|
+
isLoading: true,
|
|
76
|
+
isError: false,
|
|
77
|
+
isSuccess: false,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
const signature = await connector.signMessage(message);
|
|
82
|
+
setState({
|
|
83
|
+
data: signature,
|
|
84
|
+
error: null,
|
|
85
|
+
isLoading: false,
|
|
86
|
+
isError: false,
|
|
87
|
+
isSuccess: true,
|
|
88
|
+
});
|
|
89
|
+
return signature;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
setState({
|
|
92
|
+
data: undefined,
|
|
93
|
+
error: error as Error,
|
|
94
|
+
isLoading: false,
|
|
95
|
+
isError: true,
|
|
96
|
+
isSuccess: false,
|
|
97
|
+
});
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
[store]
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const signMessage = useCallback(
|
|
105
|
+
({ message }: { message: string }) => {
|
|
106
|
+
signMessageAsync({ message }).catch(() => {
|
|
107
|
+
// Error is already captured in state
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
[signMessageAsync]
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const reset = useCallback(() => {
|
|
114
|
+
setState({
|
|
115
|
+
data: undefined,
|
|
116
|
+
error: null,
|
|
117
|
+
isLoading: false,
|
|
118
|
+
isError: false,
|
|
119
|
+
isSuccess: false,
|
|
120
|
+
});
|
|
121
|
+
}, []);
|
|
122
|
+
|
|
123
|
+
return useMemo(
|
|
124
|
+
() => ({
|
|
125
|
+
signMessage,
|
|
126
|
+
signMessageAsync,
|
|
127
|
+
data: state.data,
|
|
128
|
+
error: state.error,
|
|
129
|
+
isLoading: state.isLoading,
|
|
130
|
+
isError: state.isError,
|
|
131
|
+
isSuccess: state.isSuccess,
|
|
132
|
+
reset,
|
|
133
|
+
}),
|
|
134
|
+
[signMessage, signMessageAsync, state, reset]
|
|
135
|
+
);
|
|
136
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
2
|
+
import type { SignPsbtOptions } from 'otx-btc-wallet-core';
|
|
3
|
+
import { useConfig } from '../context';
|
|
4
|
+
|
|
5
|
+
export interface UseSignPsbtReturn {
|
|
6
|
+
/** Sign PSBT (fire-and-forget) */
|
|
7
|
+
signPsbt: (args: { psbt: string; options?: SignPsbtOptions }) => void;
|
|
8
|
+
/** Sign PSBT (returns promise with signed PSBT hex) */
|
|
9
|
+
signPsbtAsync: (args: {
|
|
10
|
+
psbt: string;
|
|
11
|
+
options?: SignPsbtOptions;
|
|
12
|
+
}) => Promise<string>;
|
|
13
|
+
/** Signed PSBT hex */
|
|
14
|
+
data: string | undefined;
|
|
15
|
+
/** Last error */
|
|
16
|
+
error: Error | null;
|
|
17
|
+
/** Is signing */
|
|
18
|
+
isLoading: boolean;
|
|
19
|
+
/** Did signing fail */
|
|
20
|
+
isError: boolean;
|
|
21
|
+
/** Did signing succeed */
|
|
22
|
+
isSuccess: boolean;
|
|
23
|
+
/** Reset state */
|
|
24
|
+
reset: () => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Hook to sign a PSBT
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* function SignPsbt() {
|
|
33
|
+
* const { signPsbt, isLoading, data } = useSignPsbt();
|
|
34
|
+
*
|
|
35
|
+
* const handleSign = () => {
|
|
36
|
+
* signPsbt({
|
|
37
|
+
* psbt: '70736274ff01...',
|
|
38
|
+
* options: { autoFinalize: true }
|
|
39
|
+
* });
|
|
40
|
+
* };
|
|
41
|
+
*
|
|
42
|
+
* return (
|
|
43
|
+
* <div>
|
|
44
|
+
* <button onClick={handleSign} disabled={isLoading}>
|
|
45
|
+
* Sign PSBT
|
|
46
|
+
* </button>
|
|
47
|
+
* {data && <p>Signed: {data.slice(0, 20)}...</p>}
|
|
48
|
+
* </div>
|
|
49
|
+
* );
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function useSignPsbt(): UseSignPsbtReturn {
|
|
54
|
+
const config = useConfig();
|
|
55
|
+
const { store } = config;
|
|
56
|
+
|
|
57
|
+
const [state, setState] = useState<{
|
|
58
|
+
data: string | undefined;
|
|
59
|
+
error: Error | null;
|
|
60
|
+
isLoading: boolean;
|
|
61
|
+
isError: boolean;
|
|
62
|
+
isSuccess: boolean;
|
|
63
|
+
}>({
|
|
64
|
+
data: undefined,
|
|
65
|
+
error: null,
|
|
66
|
+
isLoading: false,
|
|
67
|
+
isError: false,
|
|
68
|
+
isSuccess: false,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const signPsbtAsync = useCallback(
|
|
72
|
+
async ({ psbt, options }: { psbt: string; options?: SignPsbtOptions }) => {
|
|
73
|
+
const { connector } = store.getState();
|
|
74
|
+
|
|
75
|
+
if (!connector) {
|
|
76
|
+
throw new Error('Not connected');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
setState({
|
|
80
|
+
data: undefined,
|
|
81
|
+
error: null,
|
|
82
|
+
isLoading: true,
|
|
83
|
+
isError: false,
|
|
84
|
+
isSuccess: false,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const signedPsbt = await connector.signPsbt(psbt, options);
|
|
89
|
+
setState({
|
|
90
|
+
data: signedPsbt,
|
|
91
|
+
error: null,
|
|
92
|
+
isLoading: false,
|
|
93
|
+
isError: false,
|
|
94
|
+
isSuccess: true,
|
|
95
|
+
});
|
|
96
|
+
return signedPsbt;
|
|
97
|
+
} catch (error) {
|
|
98
|
+
setState({
|
|
99
|
+
data: undefined,
|
|
100
|
+
error: error as Error,
|
|
101
|
+
isLoading: false,
|
|
102
|
+
isError: true,
|
|
103
|
+
isSuccess: false,
|
|
104
|
+
});
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
[store]
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const signPsbt = useCallback(
|
|
112
|
+
({ psbt, options }: { psbt: string; options?: SignPsbtOptions }) => {
|
|
113
|
+
const args = options !== undefined ? { psbt, options } : { psbt };
|
|
114
|
+
signPsbtAsync(args).catch(() => {
|
|
115
|
+
// Error is already captured in state
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
[signPsbtAsync]
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const reset = useCallback(() => {
|
|
122
|
+
setState({
|
|
123
|
+
data: undefined,
|
|
124
|
+
error: null,
|
|
125
|
+
isLoading: false,
|
|
126
|
+
isError: false,
|
|
127
|
+
isSuccess: false,
|
|
128
|
+
});
|
|
129
|
+
}, []);
|
|
130
|
+
|
|
131
|
+
return useMemo(
|
|
132
|
+
() => ({
|
|
133
|
+
signPsbt,
|
|
134
|
+
signPsbtAsync,
|
|
135
|
+
data: state.data,
|
|
136
|
+
error: state.error,
|
|
137
|
+
isLoading: state.isLoading,
|
|
138
|
+
isError: state.isError,
|
|
139
|
+
isSuccess: state.isSuccess,
|
|
140
|
+
reset,
|
|
141
|
+
}),
|
|
142
|
+
[signPsbt, signPsbtAsync, state, reset]
|
|
143
|
+
);
|
|
144
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
2
|
+
import type { SignPsbtOptions } from 'otx-btc-wallet-core';
|
|
3
|
+
import { useConfig } from '../context';
|
|
4
|
+
|
|
5
|
+
export interface UseSignPsbtsReturn {
|
|
6
|
+
/** Sign multiple PSBTs (fire-and-forget) */
|
|
7
|
+
signPsbts: (args: { psbts: string[]; options?: SignPsbtOptions }) => void;
|
|
8
|
+
/** Sign multiple PSBTs (returns promise with signed PSBT hexes) */
|
|
9
|
+
signPsbtsAsync: (args: {
|
|
10
|
+
psbts: string[];
|
|
11
|
+
options?: SignPsbtOptions;
|
|
12
|
+
}) => Promise<string[]>;
|
|
13
|
+
/** Signed PSBT hexes */
|
|
14
|
+
data: string[] | undefined;
|
|
15
|
+
/** Last error */
|
|
16
|
+
error: Error | null;
|
|
17
|
+
/** Is signing */
|
|
18
|
+
isLoading: boolean;
|
|
19
|
+
/** Did signing fail */
|
|
20
|
+
isError: boolean;
|
|
21
|
+
/** Did signing succeed */
|
|
22
|
+
isSuccess: boolean;
|
|
23
|
+
/** Is batch signing supported by current connector */
|
|
24
|
+
isSupported: boolean;
|
|
25
|
+
/** Reset state */
|
|
26
|
+
reset: () => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Hook to sign multiple PSBTs (batch signing)
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* function BatchSign() {
|
|
35
|
+
* const { signPsbts, isLoading, isSupported, data } = useSignPsbts();
|
|
36
|
+
*
|
|
37
|
+
* if (!isSupported) {
|
|
38
|
+
* return <p>Batch signing not supported by this wallet</p>;
|
|
39
|
+
* }
|
|
40
|
+
*
|
|
41
|
+
* const handleSign = () => {
|
|
42
|
+
* signPsbts({
|
|
43
|
+
* psbts: ['70736274ff01...', '70736274ff02...'],
|
|
44
|
+
* options: { autoFinalize: true }
|
|
45
|
+
* });
|
|
46
|
+
* };
|
|
47
|
+
*
|
|
48
|
+
* return (
|
|
49
|
+
* <button onClick={handleSign} disabled={isLoading}>
|
|
50
|
+
* Sign {2} PSBTs
|
|
51
|
+
* </button>
|
|
52
|
+
* );
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export function useSignPsbts(): UseSignPsbtsReturn {
|
|
57
|
+
const config = useConfig();
|
|
58
|
+
const { store } = config;
|
|
59
|
+
|
|
60
|
+
const [state, setState] = useState<{
|
|
61
|
+
data: string[] | undefined;
|
|
62
|
+
error: Error | null;
|
|
63
|
+
isLoading: boolean;
|
|
64
|
+
isError: boolean;
|
|
65
|
+
isSuccess: boolean;
|
|
66
|
+
}>({
|
|
67
|
+
data: undefined,
|
|
68
|
+
error: null,
|
|
69
|
+
isLoading: false,
|
|
70
|
+
isError: false,
|
|
71
|
+
isSuccess: false,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Check if current connector supports batch signing
|
|
75
|
+
const isSupported = useMemo(() => {
|
|
76
|
+
const { connector } = store.getState();
|
|
77
|
+
return typeof connector?.signPsbts === 'function';
|
|
78
|
+
}, [store]);
|
|
79
|
+
|
|
80
|
+
const signPsbtsAsync = useCallback(
|
|
81
|
+
async ({
|
|
82
|
+
psbts,
|
|
83
|
+
options,
|
|
84
|
+
}: {
|
|
85
|
+
psbts: string[];
|
|
86
|
+
options?: SignPsbtOptions;
|
|
87
|
+
}) => {
|
|
88
|
+
const { connector } = store.getState();
|
|
89
|
+
|
|
90
|
+
if (!connector) {
|
|
91
|
+
throw new Error('Not connected');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!connector.signPsbts) {
|
|
95
|
+
throw new Error('Batch signing is not supported by this wallet');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
setState({
|
|
99
|
+
data: undefined,
|
|
100
|
+
error: null,
|
|
101
|
+
isLoading: true,
|
|
102
|
+
isError: false,
|
|
103
|
+
isSuccess: false,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
const signedPsbts = await connector.signPsbts(psbts, options);
|
|
108
|
+
setState({
|
|
109
|
+
data: signedPsbts,
|
|
110
|
+
error: null,
|
|
111
|
+
isLoading: false,
|
|
112
|
+
isError: false,
|
|
113
|
+
isSuccess: true,
|
|
114
|
+
});
|
|
115
|
+
return signedPsbts;
|
|
116
|
+
} catch (error) {
|
|
117
|
+
setState({
|
|
118
|
+
data: undefined,
|
|
119
|
+
error: error as Error,
|
|
120
|
+
isLoading: false,
|
|
121
|
+
isError: true,
|
|
122
|
+
isSuccess: false,
|
|
123
|
+
});
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
[store]
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const signPsbts = useCallback(
|
|
131
|
+
({ psbts, options }: { psbts: string[]; options?: SignPsbtOptions }) => {
|
|
132
|
+
const args = options !== undefined ? { psbts, options } : { psbts };
|
|
133
|
+
signPsbtsAsync(args).catch(() => {
|
|
134
|
+
// Error is already captured in state
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
[signPsbtsAsync]
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const reset = useCallback(() => {
|
|
141
|
+
setState({
|
|
142
|
+
data: undefined,
|
|
143
|
+
error: null,
|
|
144
|
+
isLoading: false,
|
|
145
|
+
isError: false,
|
|
146
|
+
isSuccess: false,
|
|
147
|
+
});
|
|
148
|
+
}, []);
|
|
149
|
+
|
|
150
|
+
return useMemo(
|
|
151
|
+
() => ({
|
|
152
|
+
signPsbts,
|
|
153
|
+
signPsbtsAsync,
|
|
154
|
+
data: state.data,
|
|
155
|
+
error: state.error,
|
|
156
|
+
isLoading: state.isLoading,
|
|
157
|
+
isError: state.isError,
|
|
158
|
+
isSuccess: state.isSuccess,
|
|
159
|
+
isSupported,
|
|
160
|
+
reset,
|
|
161
|
+
}),
|
|
162
|
+
[signPsbts, signPsbtsAsync, state, isSupported, reset]
|
|
163
|
+
);
|
|
164
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// otx-btc-wallet-react - React hooks and components
|
|
2
|
+
|
|
3
|
+
// Provider
|
|
4
|
+
export { BtcWalletProvider, type BtcWalletProviderProps } from './provider';
|
|
5
|
+
|
|
6
|
+
// Context
|
|
7
|
+
export { useConfig, BtcWalletContext } from './context';
|
|
8
|
+
|
|
9
|
+
// Hooks
|
|
10
|
+
export { useAccount, type UseAccountReturn } from './hooks/useAccount';
|
|
11
|
+
export {
|
|
12
|
+
useConnect,
|
|
13
|
+
type UseConnectReturn,
|
|
14
|
+
type ConnectArgs,
|
|
15
|
+
} from './hooks/useConnect';
|
|
16
|
+
export { useDisconnect, type UseDisconnectReturn } from './hooks/useDisconnect';
|
|
17
|
+
export { useNetwork, type UseNetworkReturn } from './hooks/useNetwork';
|
|
18
|
+
export {
|
|
19
|
+
useSendTransaction,
|
|
20
|
+
type UseSendTransactionReturn,
|
|
21
|
+
} from './hooks/useSendTransaction';
|
|
22
|
+
export {
|
|
23
|
+
useSignMessage,
|
|
24
|
+
type UseSignMessageReturn,
|
|
25
|
+
} from './hooks/useSignMessage';
|
|
26
|
+
export { useSignPsbt, type UseSignPsbtReturn } from './hooks/useSignPsbt';
|
|
27
|
+
export { useSignPsbts, type UseSignPsbtsReturn } from './hooks/useSignPsbts';
|
|
28
|
+
export {
|
|
29
|
+
useMultiAddress,
|
|
30
|
+
type UseMultiAddressReturn,
|
|
31
|
+
} from './hooks/useMultiAddress';
|
package/src/provider.tsx
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type ReactNode, useEffect, useRef } from 'react';
|
|
2
|
+
import type { ResolvedConfig } from 'otx-btc-wallet-core';
|
|
3
|
+
import { BtcWalletContext } from './context';
|
|
4
|
+
|
|
5
|
+
export interface BtcWalletProviderProps {
|
|
6
|
+
/** Configuration created with createConfig() */
|
|
7
|
+
config: ResolvedConfig;
|
|
8
|
+
/** Child components */
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Provider component for otx-btc-wallet
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* import { BtcWalletProvider } from 'otx-btc-wallet-react';
|
|
18
|
+
* import { config } from './config';
|
|
19
|
+
*
|
|
20
|
+
* function App() {
|
|
21
|
+
* return (
|
|
22
|
+
* <BtcWalletProvider config={config}>
|
|
23
|
+
* <YourApp />
|
|
24
|
+
* </BtcWalletProvider>
|
|
25
|
+
* );
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function BtcWalletProvider({
|
|
30
|
+
config,
|
|
31
|
+
children,
|
|
32
|
+
}: BtcWalletProviderProps): ReactNode {
|
|
33
|
+
const initializedRef = useRef(false);
|
|
34
|
+
|
|
35
|
+
// Validate config
|
|
36
|
+
if (!config) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
'BtcWalletProvider requires a config prop. ' +
|
|
39
|
+
'Create one with createConfig() from otx-btc-wallet-core.'
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!config.store) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
'Invalid config: missing store. ' +
|
|
46
|
+
'Make sure you created the config with createConfig().'
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Handle auto-reconnect on mount
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (initializedRef.current) return;
|
|
53
|
+
initializedRef.current = true;
|
|
54
|
+
|
|
55
|
+
// Auto-reconnect is handled by createConfig, but we can
|
|
56
|
+
// trigger it here if needed for SSR hydration
|
|
57
|
+
if (config.autoConnect && typeof window !== 'undefined') {
|
|
58
|
+
const state = config.store.getState();
|
|
59
|
+
if (state.connectorId && state.status === 'disconnected') {
|
|
60
|
+
void state.reconnect(config.connectors);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}, [config]);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<BtcWalletContext.Provider value={config}>
|
|
67
|
+
{children}
|
|
68
|
+
</BtcWalletContext.Provider>
|
|
69
|
+
);
|
|
70
|
+
}
|