@thru/react-sdk 0.0.4 → 0.0.6
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.d.ts +25 -6
- package/dist/index.js +89 -16
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/ThruContext.ts +8 -4
- package/src/ThruProvider.tsx +65 -13
- package/src/hooks/useAccounts.ts +38 -0
- package/src/hooks/useWallet.ts +5 -2
- package/src/index.ts +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { BrowserSDK, BrowserSDKConfig, ConnectOptions } from '@thru/browser-sdk';
|
|
2
2
|
export { BrowserSDK, BrowserSDKConfig, ConnectOptions, ErrorCode, SDKEvent } from '@thru/browser-sdk';
|
|
3
3
|
import * as _thru_chain_interfaces from '@thru/chain-interfaces';
|
|
4
|
-
import {
|
|
5
|
-
export { ConnectResult, IThruChain, SignMessageParams, SignMessageResult,
|
|
6
|
-
import { Thru } from '@thru/thru-sdk';
|
|
4
|
+
import { WalletAccount, IThruChain, ConnectResult } from '@thru/chain-interfaces';
|
|
5
|
+
export { ConnectResult, IThruChain, SignMessageParams, SignMessageResult, WalletAccount } from '@thru/chain-interfaces';
|
|
6
|
+
import { Thru } from '@thru/thru-sdk/client';
|
|
7
7
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
8
8
|
import { ReactNode } from 'react';
|
|
9
9
|
|
|
10
10
|
interface ThruContextValue {
|
|
11
11
|
wallet: BrowserSDK | null;
|
|
12
12
|
isConnected: boolean;
|
|
13
|
-
|
|
13
|
+
accounts: WalletAccount[];
|
|
14
14
|
isConnecting: boolean;
|
|
15
15
|
error: Error | null;
|
|
16
16
|
thru: Thru | null;
|
|
17
|
+
selectedAccount: WalletAccount | null;
|
|
18
|
+
selectAccount: (account: WalletAccount) => Promise<void>;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
interface ThruProviderProps {
|
|
@@ -26,6 +28,20 @@ interface ThruProviderProps {
|
|
|
26
28
|
*/
|
|
27
29
|
declare function ThruProvider({ children, config }: ThruProviderProps): react_jsx_runtime.JSX.Element;
|
|
28
30
|
|
|
31
|
+
interface UseAccountsResult {
|
|
32
|
+
accounts: WalletAccount[];
|
|
33
|
+
selectedAccount: WalletAccount | null;
|
|
34
|
+
isConnected: boolean;
|
|
35
|
+
isConnecting: boolean;
|
|
36
|
+
}
|
|
37
|
+
interface UseAccountsOptions {
|
|
38
|
+
onAccountSelect?: (account: WalletAccount) => void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* useAccounts - Exposes connected wallet accounts and selection helpers.
|
|
42
|
+
*/
|
|
43
|
+
declare function useAccounts(options?: UseAccountsOptions): UseAccountsResult;
|
|
44
|
+
|
|
29
45
|
/**
|
|
30
46
|
* useThru - Access the Thru SDK context
|
|
31
47
|
* Must be used within a ThruProvider
|
|
@@ -38,10 +54,13 @@ declare function useThru(): ThruContextValue;
|
|
|
38
54
|
*/
|
|
39
55
|
declare function useWallet(): {
|
|
40
56
|
wallet: IThruChain | undefined;
|
|
41
|
-
|
|
57
|
+
accounts: _thru_chain_interfaces.WalletAccount[];
|
|
42
58
|
connect: (options?: ConnectOptions) => Promise<ConnectResult>;
|
|
43
59
|
disconnect: () => Promise<void>;
|
|
44
60
|
isConnected: boolean;
|
|
61
|
+
isConnecting: boolean;
|
|
62
|
+
selectedAccount: _thru_chain_interfaces.WalletAccount | null;
|
|
63
|
+
selectAccount: (account: _thru_chain_interfaces.WalletAccount) => Promise<void>;
|
|
45
64
|
};
|
|
46
65
|
|
|
47
|
-
export { type ThruContextValue, ThruProvider, type ThruProviderProps, useThru, useWallet };
|
|
66
|
+
export { type ThruContextValue, ThruProvider, type ThruProviderProps, type UseAccountsOptions, type UseAccountsResult, useAccounts, useThru, useWallet };
|
package/dist/index.js
CHANGED
|
@@ -1,29 +1,43 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { BrowserSDK } from '@thru/browser-sdk';
|
|
3
3
|
export { BrowserSDK, ErrorCode } from '@thru/browser-sdk';
|
|
4
|
-
import { createContext, useState, useEffect, useContext, useRef } from 'react';
|
|
4
|
+
import { createContext, useState, useEffect, useCallback, useContext, useMemo, useRef } from 'react';
|
|
5
5
|
import { jsx } from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
var defaultContextValue = {
|
|
8
8
|
wallet: null,
|
|
9
9
|
isConnected: false,
|
|
10
|
-
|
|
10
|
+
accounts: [],
|
|
11
11
|
isConnecting: false,
|
|
12
12
|
error: null,
|
|
13
|
-
thru: null
|
|
13
|
+
thru: null,
|
|
14
|
+
selectedAccount: null,
|
|
15
|
+
selectAccount: async () => void 0
|
|
14
16
|
};
|
|
15
17
|
var ThruContext = createContext(defaultContextValue);
|
|
16
18
|
function ThruProvider({ children, config }) {
|
|
17
19
|
const [sdk, setSdk] = useState(null);
|
|
18
20
|
const [thru, setThru] = useState(null);
|
|
19
21
|
const [isConnected, setIsConnected] = useState(false);
|
|
20
|
-
const [
|
|
22
|
+
const [accounts, setAccounts] = useState([]);
|
|
21
23
|
const [isConnecting, setIsConnecting] = useState(false);
|
|
22
24
|
const [error, setError] = useState(null);
|
|
25
|
+
const [selectedAccount, setSelectedAccount] = useState(null);
|
|
23
26
|
useEffect(() => {
|
|
24
27
|
const sdkInstance = new BrowserSDK(config);
|
|
25
28
|
setSdk(sdkInstance);
|
|
26
29
|
setThru(sdkInstance.getThru());
|
|
30
|
+
const updateAccountsFromSdk = () => {
|
|
31
|
+
setAccounts(sdkInstance.getAccounts());
|
|
32
|
+
};
|
|
33
|
+
const updateSelectedAccount = (account) => {
|
|
34
|
+
if (account) {
|
|
35
|
+
setSelectedAccount(account);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const fallback = sdkInstance.getSelectedAccount() ?? sdkInstance.getAccounts()[0] ?? null;
|
|
39
|
+
setSelectedAccount(fallback);
|
|
40
|
+
};
|
|
27
41
|
sdkInstance.initialize().catch((err) => {
|
|
28
42
|
console.error("Failed to initialize SDK:", err);
|
|
29
43
|
setError(err);
|
|
@@ -34,37 +48,71 @@ function ThruProvider({ children, config }) {
|
|
|
34
48
|
setError(null);
|
|
35
49
|
} else {
|
|
36
50
|
setIsConnected(true);
|
|
37
|
-
|
|
51
|
+
updateAccountsFromSdk();
|
|
38
52
|
setIsConnecting(false);
|
|
39
53
|
setError(null);
|
|
54
|
+
if (result?.accounts?.length) {
|
|
55
|
+
setSelectedAccount(result.accounts[0]);
|
|
56
|
+
} else {
|
|
57
|
+
updateSelectedAccount();
|
|
58
|
+
}
|
|
40
59
|
}
|
|
41
60
|
};
|
|
42
|
-
const
|
|
61
|
+
const resetData = () => {
|
|
43
62
|
setIsConnected(false);
|
|
44
|
-
|
|
63
|
+
setAccounts([]);
|
|
45
64
|
setIsConnecting(false);
|
|
65
|
+
setSelectedAccount(null);
|
|
66
|
+
};
|
|
67
|
+
const handleDisconnect = () => {
|
|
68
|
+
resetData();
|
|
46
69
|
};
|
|
47
70
|
const handleError = (err) => {
|
|
48
71
|
setError(err.error || new Error("Unknown error"));
|
|
49
72
|
setIsConnecting(false);
|
|
50
73
|
};
|
|
51
74
|
const handleLock = () => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
75
|
+
resetData();
|
|
76
|
+
};
|
|
77
|
+
const handleAccountChanged = (account) => {
|
|
78
|
+
updateAccountsFromSdk();
|
|
79
|
+
updateSelectedAccount(account ?? void 0);
|
|
55
80
|
};
|
|
56
81
|
sdkInstance.on("connect", handleConnect);
|
|
57
82
|
sdkInstance.on("disconnect", handleDisconnect);
|
|
58
83
|
sdkInstance.on("error", handleError);
|
|
59
84
|
sdkInstance.on("lock", handleLock);
|
|
85
|
+
sdkInstance.on("accountChanged", handleAccountChanged);
|
|
60
86
|
return () => {
|
|
61
87
|
sdkInstance.off("connect", handleConnect);
|
|
62
88
|
sdkInstance.off("disconnect", handleDisconnect);
|
|
63
89
|
sdkInstance.off("error", handleError);
|
|
64
90
|
sdkInstance.off("lock", handleLock);
|
|
91
|
+
sdkInstance.off("accountChanged", handleAccountChanged);
|
|
65
92
|
sdkInstance.destroy();
|
|
66
93
|
};
|
|
67
94
|
}, []);
|
|
95
|
+
const selectAccount = useCallback(async (account) => {
|
|
96
|
+
if (!sdk) {
|
|
97
|
+
throw new Error("BrowserSDK not initialized");
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const updated = await sdk.selectAccount(account.address);
|
|
101
|
+
setSelectedAccount(updated);
|
|
102
|
+
setAccounts((prev) => {
|
|
103
|
+
const index = prev.findIndex((acc) => acc.address === updated.address);
|
|
104
|
+
if (index >= 0) {
|
|
105
|
+
const next = [...prev];
|
|
106
|
+
next[index] = updated;
|
|
107
|
+
return next;
|
|
108
|
+
}
|
|
109
|
+
return [...prev, updated];
|
|
110
|
+
});
|
|
111
|
+
} catch (err) {
|
|
112
|
+
setError(err instanceof Error ? err : new Error("Failed to select account"));
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
}, [sdk]);
|
|
68
116
|
return /* @__PURE__ */ jsx(
|
|
69
117
|
ThruContext.Provider,
|
|
70
118
|
{
|
|
@@ -72,9 +120,11 @@ function ThruProvider({ children, config }) {
|
|
|
72
120
|
thru,
|
|
73
121
|
wallet: sdk,
|
|
74
122
|
isConnected,
|
|
75
|
-
|
|
123
|
+
accounts,
|
|
76
124
|
isConnecting,
|
|
77
|
-
error
|
|
125
|
+
error,
|
|
126
|
+
selectedAccount,
|
|
127
|
+
selectAccount
|
|
78
128
|
},
|
|
79
129
|
children
|
|
80
130
|
}
|
|
@@ -84,6 +134,26 @@ function useThru() {
|
|
|
84
134
|
const context = useContext(ThruContext);
|
|
85
135
|
return context;
|
|
86
136
|
}
|
|
137
|
+
|
|
138
|
+
// src/hooks/useAccounts.ts
|
|
139
|
+
function useAccounts(options) {
|
|
140
|
+
const { accounts, selectedAccount, isConnected, isConnecting } = useThru();
|
|
141
|
+
const externalOnSelect = options?.onAccountSelect;
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (selectedAccount) {
|
|
144
|
+
externalOnSelect?.(selectedAccount);
|
|
145
|
+
}
|
|
146
|
+
}, [externalOnSelect, selectedAccount]);
|
|
147
|
+
return useMemo(
|
|
148
|
+
() => ({
|
|
149
|
+
accounts,
|
|
150
|
+
selectedAccount,
|
|
151
|
+
isConnected,
|
|
152
|
+
isConnecting
|
|
153
|
+
}),
|
|
154
|
+
[accounts, selectedAccount, isConnected, isConnecting]
|
|
155
|
+
);
|
|
156
|
+
}
|
|
87
157
|
function waitForWallet(getWallet, timeout = 5e3, interval = 100) {
|
|
88
158
|
return new Promise((resolve, reject) => {
|
|
89
159
|
const start = Date.now();
|
|
@@ -97,7 +167,7 @@ function waitForWallet(getWallet, timeout = 5e3, interval = 100) {
|
|
|
97
167
|
});
|
|
98
168
|
}
|
|
99
169
|
function useWallet() {
|
|
100
|
-
const { wallet, isConnected,
|
|
170
|
+
const { wallet, isConnected, accounts, selectedAccount, selectAccount, isConnecting } = useThru();
|
|
101
171
|
const walletRef = useRef(wallet);
|
|
102
172
|
useEffect(() => {
|
|
103
173
|
walletRef.current = wallet;
|
|
@@ -120,13 +190,16 @@ function useWallet() {
|
|
|
120
190
|
};
|
|
121
191
|
return {
|
|
122
192
|
wallet: wallet?.thru,
|
|
123
|
-
|
|
193
|
+
accounts,
|
|
124
194
|
connect,
|
|
125
195
|
disconnect,
|
|
126
|
-
isConnected: isConnected && !!wallet
|
|
196
|
+
isConnected: isConnected && !!wallet,
|
|
197
|
+
isConnecting,
|
|
198
|
+
selectedAccount,
|
|
199
|
+
selectAccount
|
|
127
200
|
};
|
|
128
201
|
}
|
|
129
202
|
|
|
130
|
-
export { ThruProvider, useThru, useWallet };
|
|
203
|
+
export { ThruProvider, useAccounts, useThru, useWallet };
|
|
131
204
|
//# sourceMappingURL=index.js.map
|
|
132
205
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ThruContext.ts","../src/ThruProvider.tsx","../src/hooks/useThru.ts","../src/hooks/useWallet.ts"],"names":["useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import { BrowserSDK } from \"@thru/browser-sdk\";\nimport { WalletAddress } from \"@thru/chain-interfaces\";\nimport { Thru } from \"@thru/thru-sdk\";\nimport { createContext } from \"react\";\n\nexport interface ThruContextValue {\n wallet: BrowserSDK | null;\n isConnected: boolean;\n addresses: WalletAddress[];\n isConnecting: boolean;\n error: Error | null;\n thru: Thru | null;\n}\n\nconst defaultContextValue: ThruContextValue = {\n wallet: null,\n isConnected: false,\n addresses: [],\n isConnecting: false,\n error: null,\n thru: null,\n};\n\nexport const ThruContext = createContext<ThruContextValue>(defaultContextValue);\n","'use client';\n\nimport { BrowserSDK, type BrowserSDKConfig, type WalletAddress } from '@thru/browser-sdk';\nimport type { Thru } from '@thru/thru-sdk';\nimport { ReactNode, useEffect, useState } from 'react';\nimport { ThruContext } from './ThruContext';\n\nexport interface ThruProviderProps {\n children: ReactNode;\n config: BrowserSDKConfig;\n}\n\n/**\n * ThruProvider - React context provider for Thru Wallet SDK\n * Wraps the BrowserSDK and exposes state via context\n */\nexport function ThruProvider({ children, config }: ThruProviderProps) {\n const [sdk, setSdk] = useState<BrowserSDK | null>(null);\n const [thru, setThru] = useState<Thru | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [addresses, setAddresses] = useState<WalletAddress[]>([]);\n const [isConnecting, setIsConnecting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n // Create SDK instance\n const sdkInstance = new BrowserSDK(config);\n setSdk(sdkInstance);\n\n setThru(sdkInstance.getThru());\n\n // Initialize SDK (creates iframe)\n sdkInstance.initialize().catch((err) => {\n console.error('Failed to initialize SDK:', err);\n setError(err);\n });\n\n // Listen to SDK events\n const handleConnect = (result: any) => {\n // Check if this is the initial \"connecting\" status or actual connection\n if (result.status === 'connecting') {\n setIsConnecting(true);\n setError(null);\n } else {\n setIsConnected(true);\n setAddresses(sdkInstance.getAddresses());\n setIsConnecting(false);\n setError(null);\n }\n };\n\n const handleDisconnect = () => {\n setIsConnected(false);\n setAddresses([]);\n setIsConnecting(false);\n };\n\n const handleError = (err: any) => {\n setError(err.error || new Error('Unknown error'));\n setIsConnecting(false);\n };\n\n const handleLock = () => {\n setIsConnected(false);\n setAddresses([]);\n setIsConnecting(false);\n };\n\n sdkInstance.on('connect', handleConnect);\n sdkInstance.on('disconnect', handleDisconnect);\n sdkInstance.on('error', handleError);\n sdkInstance.on('lock', handleLock);\n\n // Cleanup on unmount\n return () => {\n sdkInstance.off('connect', handleConnect);\n sdkInstance.off('disconnect', handleDisconnect);\n sdkInstance.off('error', handleError);\n sdkInstance.off('lock', handleLock);\n sdkInstance.destroy();\n };\n }, []); // Empty dependency array - only create SDK once\n\n return (\n <ThruContext.Provider\n value={{\n thru,\n wallet: sdk,\n isConnected,\n addresses,\n isConnecting,\n error,\n }}\n >\n {children}\n </ThruContext.Provider>\n );\n}\n","import { useContext } from \"react\";\nimport { ThruContext } from \"../ThruContext\";\n\n/**\n * useThru - Access the Thru SDK context\n * Must be used within a ThruProvider\n */\nexport function useThru() {\n const context = useContext(ThruContext);\n return context;\n}","import { BrowserSDK, ConnectOptions } from '@thru/browser-sdk';\nimport type { ConnectResult, IThruChain } from '@thru/chain-interfaces';\nimport { useEffect, useRef } from 'react';\nimport { useThru } from './useThru';\n\nfunction waitForWallet(getWallet: () => BrowserSDK | null, timeout = 5000, interval = 100): Promise<BrowserSDK> {\n return new Promise((resolve, reject) => {\n const start = Date.now();\n const check = () => {\n const sdk = getWallet();\n if (sdk) return resolve(sdk);\n if (Date.now() - start > timeout) return reject(new Error('SDK not initialized in time'));\n setTimeout(check, interval);\n };\n check();\n });\n}\n\n/**\n * useThruChain - Hook for accessing the Thru chain API exposed by the Browser SDK.\n * Returns the chain instance (if available) and a boolean indicating readiness.\n */\nexport function useWallet() {\n const { wallet, isConnected, addresses } = useThru();\n const walletRef = useRef(wallet);\n\n useEffect(() => {\n walletRef.current = wallet;\n }, [wallet]);\n\n const disconnect = async (): Promise<void> => {\n if (!wallet) {\n throw new Error('SDK not initialized');\n }\n await wallet.disconnect();\n };\n\n const connect = async (options?: ConnectOptions): Promise<ConnectResult> => {\n try {\n const readySdk =\n walletRef.current ?? (await waitForWallet(() => walletRef.current));\n const result = await readySdk.connect(options);\n return result;\n } catch (err) {\n const error = err as Error;\n throw error;\n }\n };\n\n return {\n wallet: wallet?.thru as IThruChain | undefined,\n addresses,\n connect,\n disconnect,\n isConnected: isConnected && !!wallet,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/ThruContext.ts","../src/ThruProvider.tsx","../src/hooks/useThru.ts","../src/hooks/useAccounts.ts","../src/hooks/useWallet.ts"],"names":["useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import { BrowserSDK } from \"@thru/browser-sdk\";\nimport { WalletAccount } from \"@thru/chain-interfaces\";\nimport { Thru } from \"@thru/thru-sdk/client\";\nimport { createContext } from \"react\";\n\nexport interface ThruContextValue {\n wallet: BrowserSDK | null;\n isConnected: boolean;\n accounts: WalletAccount[];\n isConnecting: boolean;\n error: Error | null;\n thru: Thru | null;\n selectedAccount: WalletAccount | null;\n selectAccount: (account: WalletAccount) => Promise<void>;\n}\n\nconst defaultContextValue: ThruContextValue = {\n wallet: null,\n isConnected: false,\n accounts: [],\n isConnecting: false,\n error: null,\n thru: null,\n selectedAccount: null,\n selectAccount: async () => undefined,\n};\n\nexport const ThruContext = createContext<ThruContextValue>(defaultContextValue);\n","'use client';\n\nimport { BrowserSDK, type BrowserSDKConfig, type WalletAccount } from '@thru/browser-sdk';\nimport type { Thru } from '@thru/thru-sdk/client';\nimport { ReactNode, useCallback, useEffect, useState } from 'react';\nimport { ThruContext } from './ThruContext';\n\nexport interface ThruProviderProps {\n children: ReactNode;\n config: BrowserSDKConfig;\n}\n\n/**\n * ThruProvider - React context provider for Thru Wallet SDK\n * Wraps the BrowserSDK and exposes state via context\n */\nexport function ThruProvider({ children, config }: ThruProviderProps) {\n const [sdk, setSdk] = useState<BrowserSDK | null>(null);\n const [thru, setThru] = useState<Thru | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [accounts, setAccounts] = useState<WalletAccount[]>([]);\n const [isConnecting, setIsConnecting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [selectedAccount, setSelectedAccount] = useState<WalletAccount | null>(null);\n\n useEffect(() => {\n // Create SDK instance\n const sdkInstance = new BrowserSDK(config);\n setSdk(sdkInstance);\n setThru(sdkInstance.getThru());\n\n const updateAccountsFromSdk = () => {\n setAccounts(sdkInstance.getAccounts());\n };\n\n const updateSelectedAccount = (account?: WalletAccount | null) => {\n if (account) {\n setSelectedAccount(account);\n return;\n }\n const fallback = sdkInstance.getSelectedAccount() ?? sdkInstance.getAccounts()[0] ?? null;\n setSelectedAccount(fallback);\n };\n\n sdkInstance.initialize().catch((err) => {\n console.error('Failed to initialize SDK:', err);\n setError(err);\n });\n\n // Listen to SDK events\n const handleConnect = (result: any) => {\n // Check if this is the initial \"connecting\" status or actual connection\n if (result.status === 'connecting') {\n setIsConnecting(true);\n setError(null);\n } else {\n setIsConnected(true);\n updateAccountsFromSdk();\n setIsConnecting(false);\n setError(null);\n if (result?.accounts?.length) {\n setSelectedAccount(result.accounts[0]);\n } else {\n updateSelectedAccount();\n }\n }\n };\n\n const resetData = () => {\n setIsConnected(false);\n setAccounts([]);\n setIsConnecting(false);\n setSelectedAccount(null);\n };\n\n const handleDisconnect = () => {\n resetData();\n };\n\n const handleError = (err: any) => {\n setError(err.error || new Error('Unknown error'));\n setIsConnecting(false);\n };\n\n const handleLock = () => {\n resetData();\n };\n\n const handleAccountChanged = (account: WalletAccount | null | undefined) => {\n updateAccountsFromSdk();\n updateSelectedAccount(account ?? undefined);\n };\n\n sdkInstance.on('connect', handleConnect);\n sdkInstance.on('disconnect', handleDisconnect);\n sdkInstance.on('error', handleError);\n sdkInstance.on('lock', handleLock);\n sdkInstance.on('accountChanged', handleAccountChanged);\n\n // Cleanup on unmount\n return () => {\n sdkInstance.off('connect', handleConnect);\n sdkInstance.off('disconnect', handleDisconnect);\n sdkInstance.off('error', handleError);\n sdkInstance.off('lock', handleLock);\n sdkInstance.off('accountChanged', handleAccountChanged);\n sdkInstance.destroy();\n };\n }, []); // Empty dependency array - only create SDK once\n\n const selectAccount = useCallback(async (account: WalletAccount) => {\n if (!sdk) {\n throw new Error('BrowserSDK not initialized');\n }\n\n try {\n const updated = await sdk.selectAccount(account.address);\n setSelectedAccount(updated);\n setAccounts(prev => {\n const index = prev.findIndex(acc => acc.address === updated.address);\n if (index >= 0) {\n const next = [...prev];\n next[index] = updated;\n return next;\n }\n return [...prev, updated];\n });\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to select account'));\n throw err;\n }\n }, [sdk]);\n\n return (\n <ThruContext.Provider\n value={{\n thru,\n wallet: sdk,\n isConnected,\n accounts,\n isConnecting,\n error,\n selectedAccount,\n selectAccount,\n }}\n >\n {children}\n </ThruContext.Provider>\n );\n}\n","import { useContext } from \"react\";\nimport { ThruContext } from \"../ThruContext\";\n\n/**\n * useThru - Access the Thru SDK context\n * Must be used within a ThruProvider\n */\nexport function useThru() {\n const context = useContext(ThruContext);\n return context;\n}","import type { WalletAccount } from '@thru/chain-interfaces';\nimport { useEffect, useMemo } from 'react';\nimport { useThru } from './useThru';\n\nexport interface UseAccountsResult {\n accounts: WalletAccount[];\n selectedAccount: WalletAccount | null;\n isConnected: boolean;\n isConnecting: boolean;\n}\n\nexport interface UseAccountsOptions {\n onAccountSelect?: (account: WalletAccount) => void;\n}\n\n/**\n * useAccounts - Exposes connected wallet accounts and selection helpers.\n */\nexport function useAccounts(options?: UseAccountsOptions): UseAccountsResult {\n const { accounts, selectedAccount, isConnected, isConnecting } = useThru();\n const externalOnSelect = options?.onAccountSelect;\n\n useEffect(() => {\n if (selectedAccount) {\n externalOnSelect?.(selectedAccount);\n }\n }, [externalOnSelect, selectedAccount]);\n\n return useMemo(\n () => ({\n accounts,\n selectedAccount,\n isConnected,\n isConnecting,\n }),\n [accounts, selectedAccount, isConnected, isConnecting]\n );\n}\n","import { BrowserSDK, ConnectOptions } from '@thru/browser-sdk';\nimport type { ConnectResult, IThruChain } from '@thru/chain-interfaces';\nimport { useEffect, useRef } from 'react';\nimport { useThru } from './useThru';\n\nfunction waitForWallet(getWallet: () => BrowserSDK | null, timeout = 5000, interval = 100): Promise<BrowserSDK> {\n return new Promise((resolve, reject) => {\n const start = Date.now();\n const check = () => {\n const sdk = getWallet();\n if (sdk) return resolve(sdk);\n if (Date.now() - start > timeout) return reject(new Error('SDK not initialized in time'));\n setTimeout(check, interval);\n };\n check();\n });\n}\n\n/**\n * useThruChain - Hook for accessing the Thru chain API exposed by the Browser SDK.\n * Returns the chain instance (if available) and a boolean indicating readiness.\n */\nexport function useWallet() {\n const { wallet, isConnected, accounts, selectedAccount, selectAccount, isConnecting } = useThru();\n const walletRef = useRef(wallet);\n\n useEffect(() => {\n walletRef.current = wallet;\n }, [wallet]);\n\n const disconnect = async (): Promise<void> => {\n if (!wallet) {\n throw new Error('SDK not initialized');\n }\n await wallet.disconnect();\n };\n\n const connect = async (options?: ConnectOptions): Promise<ConnectResult> => {\n try {\n const readySdk =\n walletRef.current ?? (await waitForWallet(() => walletRef.current));\n const result = await readySdk.connect(options);\n return result;\n } catch (err) {\n const error = err as Error;\n throw error;\n }\n };\n\n return {\n wallet: wallet?.thru as IThruChain | undefined,\n accounts,\n connect,\n disconnect,\n isConnected: isConnected && !!wallet,\n isConnecting,\n selectedAccount,\n selectAccount,\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thru/react-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@thru/browser-sdk": "0.0.
|
|
15
|
-
"@thru/
|
|
16
|
-
"@thru/
|
|
14
|
+
"@thru/browser-sdk": "0.0.6",
|
|
15
|
+
"@thru/thru-sdk": "0.0.6",
|
|
16
|
+
"@thru/chain-interfaces": "0.0.6"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"react": "^18.0.0 || ^19.0.0",
|
package/src/ThruContext.ts
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import { BrowserSDK } from "@thru/browser-sdk";
|
|
2
|
-
import {
|
|
3
|
-
import { Thru } from "@thru/thru-sdk";
|
|
2
|
+
import { WalletAccount } from "@thru/chain-interfaces";
|
|
3
|
+
import { Thru } from "@thru/thru-sdk/client";
|
|
4
4
|
import { createContext } from "react";
|
|
5
5
|
|
|
6
6
|
export interface ThruContextValue {
|
|
7
7
|
wallet: BrowserSDK | null;
|
|
8
8
|
isConnected: boolean;
|
|
9
|
-
|
|
9
|
+
accounts: WalletAccount[];
|
|
10
10
|
isConnecting: boolean;
|
|
11
11
|
error: Error | null;
|
|
12
12
|
thru: Thru | null;
|
|
13
|
+
selectedAccount: WalletAccount | null;
|
|
14
|
+
selectAccount: (account: WalletAccount) => Promise<void>;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
const defaultContextValue: ThruContextValue = {
|
|
16
18
|
wallet: null,
|
|
17
19
|
isConnected: false,
|
|
18
|
-
|
|
20
|
+
accounts: [],
|
|
19
21
|
isConnecting: false,
|
|
20
22
|
error: null,
|
|
21
23
|
thru: null,
|
|
24
|
+
selectedAccount: null,
|
|
25
|
+
selectAccount: async () => undefined,
|
|
22
26
|
};
|
|
23
27
|
|
|
24
28
|
export const ThruContext = createContext<ThruContextValue>(defaultContextValue);
|
package/src/ThruProvider.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { BrowserSDK, type BrowserSDKConfig, type
|
|
4
|
-
import type { Thru } from '@thru/thru-sdk';
|
|
5
|
-
import { ReactNode, useEffect, useState } from 'react';
|
|
3
|
+
import { BrowserSDK, type BrowserSDKConfig, type WalletAccount } from '@thru/browser-sdk';
|
|
4
|
+
import type { Thru } from '@thru/thru-sdk/client';
|
|
5
|
+
import { ReactNode, useCallback, useEffect, useState } from 'react';
|
|
6
6
|
import { ThruContext } from './ThruContext';
|
|
7
7
|
|
|
8
8
|
export interface ThruProviderProps {
|
|
@@ -18,18 +18,30 @@ export function ThruProvider({ children, config }: ThruProviderProps) {
|
|
|
18
18
|
const [sdk, setSdk] = useState<BrowserSDK | null>(null);
|
|
19
19
|
const [thru, setThru] = useState<Thru | null>(null);
|
|
20
20
|
const [isConnected, setIsConnected] = useState(false);
|
|
21
|
-
const [
|
|
21
|
+
const [accounts, setAccounts] = useState<WalletAccount[]>([]);
|
|
22
22
|
const [isConnecting, setIsConnecting] = useState(false);
|
|
23
23
|
const [error, setError] = useState<Error | null>(null);
|
|
24
|
+
const [selectedAccount, setSelectedAccount] = useState<WalletAccount | null>(null);
|
|
24
25
|
|
|
25
26
|
useEffect(() => {
|
|
26
27
|
// Create SDK instance
|
|
27
28
|
const sdkInstance = new BrowserSDK(config);
|
|
28
29
|
setSdk(sdkInstance);
|
|
29
|
-
|
|
30
30
|
setThru(sdkInstance.getThru());
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
const updateAccountsFromSdk = () => {
|
|
33
|
+
setAccounts(sdkInstance.getAccounts());
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const updateSelectedAccount = (account?: WalletAccount | null) => {
|
|
37
|
+
if (account) {
|
|
38
|
+
setSelectedAccount(account);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const fallback = sdkInstance.getSelectedAccount() ?? sdkInstance.getAccounts()[0] ?? null;
|
|
42
|
+
setSelectedAccount(fallback);
|
|
43
|
+
};
|
|
44
|
+
|
|
33
45
|
sdkInstance.initialize().catch((err) => {
|
|
34
46
|
console.error('Failed to initialize SDK:', err);
|
|
35
47
|
setError(err);
|
|
@@ -43,16 +55,26 @@ export function ThruProvider({ children, config }: ThruProviderProps) {
|
|
|
43
55
|
setError(null);
|
|
44
56
|
} else {
|
|
45
57
|
setIsConnected(true);
|
|
46
|
-
|
|
58
|
+
updateAccountsFromSdk();
|
|
47
59
|
setIsConnecting(false);
|
|
48
60
|
setError(null);
|
|
61
|
+
if (result?.accounts?.length) {
|
|
62
|
+
setSelectedAccount(result.accounts[0]);
|
|
63
|
+
} else {
|
|
64
|
+
updateSelectedAccount();
|
|
65
|
+
}
|
|
49
66
|
}
|
|
50
67
|
};
|
|
51
68
|
|
|
52
|
-
const
|
|
69
|
+
const resetData = () => {
|
|
53
70
|
setIsConnected(false);
|
|
54
|
-
|
|
71
|
+
setAccounts([]);
|
|
55
72
|
setIsConnecting(false);
|
|
73
|
+
setSelectedAccount(null);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const handleDisconnect = () => {
|
|
77
|
+
resetData();
|
|
56
78
|
};
|
|
57
79
|
|
|
58
80
|
const handleError = (err: any) => {
|
|
@@ -61,15 +83,19 @@ export function ThruProvider({ children, config }: ThruProviderProps) {
|
|
|
61
83
|
};
|
|
62
84
|
|
|
63
85
|
const handleLock = () => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
86
|
+
resetData();
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const handleAccountChanged = (account: WalletAccount | null | undefined) => {
|
|
90
|
+
updateAccountsFromSdk();
|
|
91
|
+
updateSelectedAccount(account ?? undefined);
|
|
67
92
|
};
|
|
68
93
|
|
|
69
94
|
sdkInstance.on('connect', handleConnect);
|
|
70
95
|
sdkInstance.on('disconnect', handleDisconnect);
|
|
71
96
|
sdkInstance.on('error', handleError);
|
|
72
97
|
sdkInstance.on('lock', handleLock);
|
|
98
|
+
sdkInstance.on('accountChanged', handleAccountChanged);
|
|
73
99
|
|
|
74
100
|
// Cleanup on unmount
|
|
75
101
|
return () => {
|
|
@@ -77,19 +103,45 @@ export function ThruProvider({ children, config }: ThruProviderProps) {
|
|
|
77
103
|
sdkInstance.off('disconnect', handleDisconnect);
|
|
78
104
|
sdkInstance.off('error', handleError);
|
|
79
105
|
sdkInstance.off('lock', handleLock);
|
|
106
|
+
sdkInstance.off('accountChanged', handleAccountChanged);
|
|
80
107
|
sdkInstance.destroy();
|
|
81
108
|
};
|
|
82
109
|
}, []); // Empty dependency array - only create SDK once
|
|
83
110
|
|
|
111
|
+
const selectAccount = useCallback(async (account: WalletAccount) => {
|
|
112
|
+
if (!sdk) {
|
|
113
|
+
throw new Error('BrowserSDK not initialized');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const updated = await sdk.selectAccount(account.address);
|
|
118
|
+
setSelectedAccount(updated);
|
|
119
|
+
setAccounts(prev => {
|
|
120
|
+
const index = prev.findIndex(acc => acc.address === updated.address);
|
|
121
|
+
if (index >= 0) {
|
|
122
|
+
const next = [...prev];
|
|
123
|
+
next[index] = updated;
|
|
124
|
+
return next;
|
|
125
|
+
}
|
|
126
|
+
return [...prev, updated];
|
|
127
|
+
});
|
|
128
|
+
} catch (err) {
|
|
129
|
+
setError(err instanceof Error ? err : new Error('Failed to select account'));
|
|
130
|
+
throw err;
|
|
131
|
+
}
|
|
132
|
+
}, [sdk]);
|
|
133
|
+
|
|
84
134
|
return (
|
|
85
135
|
<ThruContext.Provider
|
|
86
136
|
value={{
|
|
87
137
|
thru,
|
|
88
138
|
wallet: sdk,
|
|
89
139
|
isConnected,
|
|
90
|
-
|
|
140
|
+
accounts,
|
|
91
141
|
isConnecting,
|
|
92
142
|
error,
|
|
143
|
+
selectedAccount,
|
|
144
|
+
selectAccount,
|
|
93
145
|
}}
|
|
94
146
|
>
|
|
95
147
|
{children}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { WalletAccount } from '@thru/chain-interfaces';
|
|
2
|
+
import { useEffect, useMemo } from 'react';
|
|
3
|
+
import { useThru } from './useThru';
|
|
4
|
+
|
|
5
|
+
export interface UseAccountsResult {
|
|
6
|
+
accounts: WalletAccount[];
|
|
7
|
+
selectedAccount: WalletAccount | null;
|
|
8
|
+
isConnected: boolean;
|
|
9
|
+
isConnecting: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface UseAccountsOptions {
|
|
13
|
+
onAccountSelect?: (account: WalletAccount) => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* useAccounts - Exposes connected wallet accounts and selection helpers.
|
|
18
|
+
*/
|
|
19
|
+
export function useAccounts(options?: UseAccountsOptions): UseAccountsResult {
|
|
20
|
+
const { accounts, selectedAccount, isConnected, isConnecting } = useThru();
|
|
21
|
+
const externalOnSelect = options?.onAccountSelect;
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (selectedAccount) {
|
|
25
|
+
externalOnSelect?.(selectedAccount);
|
|
26
|
+
}
|
|
27
|
+
}, [externalOnSelect, selectedAccount]);
|
|
28
|
+
|
|
29
|
+
return useMemo(
|
|
30
|
+
() => ({
|
|
31
|
+
accounts,
|
|
32
|
+
selectedAccount,
|
|
33
|
+
isConnected,
|
|
34
|
+
isConnecting,
|
|
35
|
+
}),
|
|
36
|
+
[accounts, selectedAccount, isConnected, isConnecting]
|
|
37
|
+
);
|
|
38
|
+
}
|
package/src/hooks/useWallet.ts
CHANGED
|
@@ -21,7 +21,7 @@ function waitForWallet(getWallet: () => BrowserSDK | null, timeout = 5000, inter
|
|
|
21
21
|
* Returns the chain instance (if available) and a boolean indicating readiness.
|
|
22
22
|
*/
|
|
23
23
|
export function useWallet() {
|
|
24
|
-
const { wallet, isConnected,
|
|
24
|
+
const { wallet, isConnected, accounts, selectedAccount, selectAccount, isConnecting } = useThru();
|
|
25
25
|
const walletRef = useRef(wallet);
|
|
26
26
|
|
|
27
27
|
useEffect(() => {
|
|
@@ -49,9 +49,12 @@ export function useWallet() {
|
|
|
49
49
|
|
|
50
50
|
return {
|
|
51
51
|
wallet: wallet?.thru as IThruChain | undefined,
|
|
52
|
-
|
|
52
|
+
accounts,
|
|
53
53
|
connect,
|
|
54
54
|
disconnect,
|
|
55
55
|
isConnected: isConnected && !!wallet,
|
|
56
|
+
isConnecting,
|
|
57
|
+
selectedAccount,
|
|
58
|
+
selectAccount,
|
|
56
59
|
};
|
|
57
60
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { ThruProvider, type ThruProviderProps } from './ThruProvider';
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
// Hooks
|
|
7
|
+
export { useAccounts, type UseAccountsOptions, type UseAccountsResult } from './hooks/useAccounts';
|
|
7
8
|
export { useThru } from './hooks/useThru';
|
|
8
9
|
export { useWallet } from './hooks/useWallet';
|
|
9
10
|
|
|
@@ -13,5 +14,5 @@ export { BrowserSDK, ErrorCode, type BrowserSDKConfig, type ConnectOptions, type
|
|
|
13
14
|
// Re-export types from chain-interfaces
|
|
14
15
|
export type {
|
|
15
16
|
ConnectResult, IThruChain, SignMessageParams,
|
|
16
|
-
SignMessageResult,
|
|
17
|
+
SignMessageResult, WalletAccount
|
|
17
18
|
} from '@thru/chain-interfaces';
|