@interchain-kit/react 0.2.221 → 0.3.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/esm/hooks/index.js +2 -0
- package/esm/hooks/useAsync.js +117 -0
- package/esm/hooks/useChain.js +6 -1
- package/esm/hooks/useChainWallet.js +6 -1
- package/esm/hooks/useSigningClient.js +21 -0
- package/esm/store/store.js +37 -12
- package/esm/utils/dedupeAsync.js +18 -0
- package/esm/utils/index.js +1 -0
- package/hooks/index.d.ts +2 -0
- package/hooks/index.js +2 -0
- package/hooks/useAsync.d.ts +32 -0
- package/hooks/useAsync.js +121 -0
- package/hooks/useChain.js +6 -1
- package/hooks/useChainWallet.js +6 -1
- package/hooks/useSigningClient.d.ts +5 -0
- package/hooks/useSigningClient.js +25 -0
- package/package.json +12 -10
- package/store/store.js +37 -12
- package/types/chain.d.ts +4 -1
- package/utils/dedupeAsync.d.ts +7 -0
- package/utils/dedupeAsync.js +21 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
package/esm/hooks/index.js
CHANGED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { useState, useEffect, useRef } from 'react';
|
|
2
|
+
export const cache = new Map();
|
|
3
|
+
export const activeRequests = new Map();
|
|
4
|
+
export function useAsync({ queryKey, queryFn, enabled = true, disableCache = false, }) {
|
|
5
|
+
const [state, setState] = useState({
|
|
6
|
+
data: null,
|
|
7
|
+
isLoading: false,
|
|
8
|
+
error: null,
|
|
9
|
+
});
|
|
10
|
+
const mountedRef = useRef(false);
|
|
11
|
+
const queryFnRef = useRef(queryFn);
|
|
12
|
+
const cacheKey = Array.isArray(queryKey)
|
|
13
|
+
? JSON.stringify(queryKey)
|
|
14
|
+
: queryKey;
|
|
15
|
+
// Always update the current function
|
|
16
|
+
queryFnRef.current = queryFn;
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
mountedRef.current = true;
|
|
19
|
+
return () => {
|
|
20
|
+
mountedRef.current = false;
|
|
21
|
+
};
|
|
22
|
+
}, []);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (!enabled)
|
|
25
|
+
return;
|
|
26
|
+
if (!disableCache && cache.has(cacheKey)) {
|
|
27
|
+
setState(prev => ({
|
|
28
|
+
...prev,
|
|
29
|
+
data: cache.get(cacheKey),
|
|
30
|
+
isLoading: false,
|
|
31
|
+
error: null,
|
|
32
|
+
}));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (activeRequests.has(cacheKey)) {
|
|
36
|
+
activeRequests.get(cacheKey).then((data) => {
|
|
37
|
+
if (mountedRef.current) {
|
|
38
|
+
setState({
|
|
39
|
+
data,
|
|
40
|
+
isLoading: false,
|
|
41
|
+
error: null,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}, (error) => {
|
|
45
|
+
if (mountedRef.current) {
|
|
46
|
+
setState({
|
|
47
|
+
data: null,
|
|
48
|
+
isLoading: false,
|
|
49
|
+
error,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
setState(prev => ({ ...prev, isLoading: true, error: null }));
|
|
56
|
+
const requestPromise = queryFnRef.current()
|
|
57
|
+
.then((data) => {
|
|
58
|
+
if (!disableCache) {
|
|
59
|
+
cache.set(cacheKey, data);
|
|
60
|
+
}
|
|
61
|
+
if (mountedRef.current) {
|
|
62
|
+
setState({
|
|
63
|
+
data,
|
|
64
|
+
isLoading: false,
|
|
65
|
+
error: null,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return data;
|
|
69
|
+
})
|
|
70
|
+
.catch((error) => {
|
|
71
|
+
if (mountedRef.current) {
|
|
72
|
+
setState({
|
|
73
|
+
data: null,
|
|
74
|
+
isLoading: false,
|
|
75
|
+
error,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
.finally(() => {
|
|
80
|
+
activeRequests.delete(cacheKey);
|
|
81
|
+
});
|
|
82
|
+
activeRequests.set(cacheKey, requestPromise);
|
|
83
|
+
}, [cacheKey, enabled, disableCache]);
|
|
84
|
+
const refetch = async () => {
|
|
85
|
+
try {
|
|
86
|
+
setState(prev => ({ ...prev, isLoading: true, error: null }));
|
|
87
|
+
const data = await queryFnRef.current();
|
|
88
|
+
if (!disableCache) {
|
|
89
|
+
cache.set(cacheKey, data);
|
|
90
|
+
}
|
|
91
|
+
if (mountedRef.current) {
|
|
92
|
+
setState({
|
|
93
|
+
data,
|
|
94
|
+
isLoading: false,
|
|
95
|
+
error: null,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return data;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (mountedRef.current) {
|
|
102
|
+
setState({
|
|
103
|
+
data: null,
|
|
104
|
+
isLoading: false,
|
|
105
|
+
error: error,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
data: state.data,
|
|
113
|
+
isLoading: state.isLoading,
|
|
114
|
+
error: state.error,
|
|
115
|
+
refetch,
|
|
116
|
+
};
|
|
117
|
+
}
|
package/esm/hooks/useChain.js
CHANGED
|
@@ -2,6 +2,7 @@ import { useWalletModal } from "../modal";
|
|
|
2
2
|
import { useWalletManager } from './useWalletManager';
|
|
3
3
|
import { ChainNameNotExist } from '@interchain-kit/core';
|
|
4
4
|
import { ChainWallet } from '../store/chain-wallet';
|
|
5
|
+
import { useSigningClient } from './useSigningClient';
|
|
5
6
|
export const useChain = (chainName) => {
|
|
6
7
|
const { assetLists, currentWalletName, disconnect, setCurrentChainName, getChainByName, getWalletByName, getChainWalletState, getChainLogoUrl, connect, getSigningClient, getRpcEndpoint, getAccount } = useWalletManager();
|
|
7
8
|
const chain = getChainByName(chainName);
|
|
@@ -12,6 +13,7 @@ export const useChain = (chainName) => {
|
|
|
12
13
|
const wallet = getWalletByName(currentWalletName);
|
|
13
14
|
const chainWalletStateToShow = getChainWalletState(currentWalletName, chainName);
|
|
14
15
|
const { open, close } = useWalletModal();
|
|
16
|
+
const { signingClient, isLoading: isSigningClientLoading, error: signingClientError } = useSigningClient(chainName, currentWalletName);
|
|
15
17
|
return {
|
|
16
18
|
//for migration cosmos kit
|
|
17
19
|
connect: () => {
|
|
@@ -34,7 +36,10 @@ export const useChain = (chainName) => {
|
|
|
34
36
|
assetList,
|
|
35
37
|
address: chainWalletStateToShow?.account?.address,
|
|
36
38
|
wallet: new ChainWallet(wallet, () => connect(currentWalletName, chainName), () => disconnect(currentWalletName, chainName), () => getAccount(currentWalletName, chainName)),
|
|
37
|
-
rpcEndpoint: chainWalletStateToShow?.rpcEndpoint,
|
|
38
39
|
getSigningClient: () => getSigningClient(currentWalletName, chainName),
|
|
40
|
+
signingClient,
|
|
41
|
+
isSigningClientLoading,
|
|
42
|
+
signingClientError,
|
|
43
|
+
rpcEndpoint: chainWalletStateToShow?.rpcEndpoint,
|
|
39
44
|
};
|
|
40
45
|
};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { useWalletManager } from "./useWalletManager";
|
|
2
2
|
import { ChainWallet } from "../store/chain-wallet";
|
|
3
|
+
import { useSigningClient } from "./useSigningClient";
|
|
3
4
|
export const useChainWallet = (chainName, walletName) => {
|
|
4
5
|
const { assetLists, disconnect, setCurrentChainName, setCurrentWalletName, getChainByName, getWalletByName, getChainWalletState, getChainLogoUrl, connect, getSigningClient, getRpcEndpoint, getAccount } = useWalletManager();
|
|
5
6
|
const chain = getChainByName(chainName);
|
|
6
7
|
const wallet = getWalletByName(walletName);
|
|
7
8
|
const assetList = assetLists.find(a => a.chainName === chainName);
|
|
8
9
|
const chainWalletStateToShow = getChainWalletState(walletName, chainName);
|
|
10
|
+
const { signingClient, isLoading: isSigningClientLoading, error: signingClientError } = useSigningClient(chainName, walletName);
|
|
9
11
|
return {
|
|
10
12
|
//for migration cosmos kit
|
|
11
13
|
connect: async () => {
|
|
@@ -24,7 +26,10 @@ export const useChainWallet = (chainName, walletName) => {
|
|
|
24
26
|
assetList,
|
|
25
27
|
address: chainWalletStateToShow?.account?.address,
|
|
26
28
|
wallet: wallet ? new ChainWallet(wallet, () => connect(walletName, chainName), () => disconnect(walletName, chainName), () => getAccount(walletName, chainName)) : null,
|
|
27
|
-
rpcEndpoint: chainWalletStateToShow?.rpcEndpoint,
|
|
28
29
|
getSigningClient: () => getSigningClient(walletName, chainName),
|
|
30
|
+
signingClient,
|
|
31
|
+
isSigningClientLoading,
|
|
32
|
+
signingClientError,
|
|
33
|
+
rpcEndpoint: chainWalletStateToShow?.rpcEndpoint,
|
|
29
34
|
};
|
|
30
35
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useWalletManager } from "./useWalletManager";
|
|
2
|
+
import { useAsync } from "./useAsync";
|
|
3
|
+
import { WalletState } from "@interchain-kit/core";
|
|
4
|
+
export const useSigningClient = (chainName, walletName) => {
|
|
5
|
+
const { getSigningClient, getChainWalletState, getRpcEndpoint } = useWalletManager();
|
|
6
|
+
const chainWalletState = getChainWalletState(walletName, chainName);
|
|
7
|
+
const { data, isLoading, error } = useAsync({
|
|
8
|
+
queryKey: `signing-client-${chainName}-${walletName}`,
|
|
9
|
+
queryFn: async () => {
|
|
10
|
+
await getRpcEndpoint(walletName, chainName);
|
|
11
|
+
return getSigningClient(walletName, chainName);
|
|
12
|
+
},
|
|
13
|
+
enabled: chainWalletState?.walletState === WalletState.Connected,
|
|
14
|
+
disableCache: true,
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
signingClient: data,
|
|
18
|
+
error,
|
|
19
|
+
isLoading,
|
|
20
|
+
};
|
|
21
|
+
};
|
package/esm/store/store.js
CHANGED
|
@@ -2,6 +2,7 @@ import { clientNotExistError, WalletState } from "@interchain-kit/core";
|
|
|
2
2
|
import { createStore } from "zustand";
|
|
3
3
|
import { immer } from "zustand/middleware/immer";
|
|
4
4
|
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
5
|
+
import { dedupeAsync } from '../utils';
|
|
5
6
|
const immerSyncUp = (newWalletManager) => {
|
|
6
7
|
return (draft) => {
|
|
7
8
|
draft.chains = newWalletManager.chains;
|
|
@@ -37,11 +38,17 @@ export const createInterchainStore = (walletManager) => {
|
|
|
37
38
|
});
|
|
38
39
|
},
|
|
39
40
|
init: async () => {
|
|
40
|
-
const
|
|
41
|
+
const oldChainWalletStatesMap = new Map(get().chainWalletState.map(cws => [cws.walletName + cws.chainName, cws]));
|
|
42
|
+
set(draft => {
|
|
43
|
+
draft.chainWalletState = [];
|
|
44
|
+
});
|
|
41
45
|
wallets.forEach(wallet => {
|
|
42
46
|
chains.forEach(chain => {
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
set(draft => {
|
|
48
|
+
if (oldChainWalletStatesMap.has(wallet.info.name + chain.chainName)) {
|
|
49
|
+
draft.chainWalletState.push(oldChainWalletStatesMap.get(wallet.info.name + chain.chainName));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
45
52
|
draft.chainWalletState.push({
|
|
46
53
|
chainName: chain.chainName,
|
|
47
54
|
walletName: wallet.info.name,
|
|
@@ -50,8 +57,8 @@ export const createInterchainStore = (walletManager) => {
|
|
|
50
57
|
errorMessage: "",
|
|
51
58
|
account: undefined
|
|
52
59
|
});
|
|
53
|
-
}
|
|
54
|
-
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
55
62
|
});
|
|
56
63
|
});
|
|
57
64
|
const NotExistWallets = [];
|
|
@@ -138,6 +145,9 @@ export const createInterchainStore = (walletManager) => {
|
|
|
138
145
|
}
|
|
139
146
|
});
|
|
140
147
|
});
|
|
148
|
+
draft.chainWalletState = draft.chainWalletState.map(cws => {
|
|
149
|
+
return { ...cws, rpcEndpoint: newEndpointOptions?.endpoints?.[cws.chainName]?.rpc?.[0] || cws.rpcEndpoint };
|
|
150
|
+
});
|
|
141
151
|
});
|
|
142
152
|
},
|
|
143
153
|
connect: async (walletName, chainName) => {
|
|
@@ -180,13 +190,23 @@ export const createInterchainStore = (walletManager) => {
|
|
|
180
190
|
}
|
|
181
191
|
},
|
|
182
192
|
getAccount: async (walletName, chainName) => {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
193
|
+
try {
|
|
194
|
+
const account = await walletManager.getAccount(walletName, chainName);
|
|
195
|
+
get().updateChainWalletState(walletName, chainName, { account });
|
|
196
|
+
return account;
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
console.log(error);
|
|
200
|
+
}
|
|
186
201
|
},
|
|
187
202
|
getRpcEndpoint: async (walletName, chainName) => {
|
|
188
|
-
|
|
189
|
-
|
|
203
|
+
return dedupeAsync(`${chainName}-rpcEndpoint`, async () => {
|
|
204
|
+
const rpcEndpoint = await walletManager.getRpcEndpoint(walletName, chainName);
|
|
205
|
+
get().wallets.map(wallet => {
|
|
206
|
+
get().updateChainWalletState(wallet.info.name, chainName, { rpcEndpoint });
|
|
207
|
+
});
|
|
208
|
+
return rpcEndpoint;
|
|
209
|
+
});
|
|
190
210
|
},
|
|
191
211
|
getChainLogoUrl(chainName) {
|
|
192
212
|
return walletManager.getChainLogoUrl(chainName);
|
|
@@ -216,7 +236,7 @@ export const createInterchainStore = (walletManager) => {
|
|
|
216
236
|
getWalletByName(walletName) {
|
|
217
237
|
return walletManager.getWalletByName(walletName);
|
|
218
238
|
},
|
|
219
|
-
getSigningClient(walletName, chainName) {
|
|
239
|
+
async getSigningClient(walletName, chainName) {
|
|
220
240
|
return walletManager.getSigningClient(walletName, chainName);
|
|
221
241
|
},
|
|
222
242
|
getEnv() {
|
|
@@ -226,7 +246,12 @@ export const createInterchainStore = (walletManager) => {
|
|
|
226
246
|
name: 'interchain-kit-store',
|
|
227
247
|
storage: createJSONStorage(() => localStorage),
|
|
228
248
|
partialize: state => ({
|
|
229
|
-
chainWalletState: state.chainWalletState
|
|
249
|
+
chainWalletState: state.chainWalletState.map(cws => ({
|
|
250
|
+
chainName: cws.chainName,
|
|
251
|
+
walletName: cws.walletName,
|
|
252
|
+
account: cws.account,
|
|
253
|
+
walletState: cws.walletState,
|
|
254
|
+
})),
|
|
230
255
|
currentWalletName: state.currentWalletName,
|
|
231
256
|
currentChainName: state.currentChainName
|
|
232
257
|
}),
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const pendingRequests = new Map();
|
|
2
|
+
/**
|
|
3
|
+
* Deduplicate async calls to avoid multiple identical requests.
|
|
4
|
+
* @param key - A unique key representing the request.
|
|
5
|
+
* @param asyncFn - A function that returns a Promise.
|
|
6
|
+
* @returns A Promise resolving to the result of the async function.
|
|
7
|
+
*/
|
|
8
|
+
export async function dedupeAsync(key, asyncFn) {
|
|
9
|
+
if (pendingRequests.has(key)) {
|
|
10
|
+
return pendingRequests.get(key);
|
|
11
|
+
}
|
|
12
|
+
const promise = asyncFn()
|
|
13
|
+
.finally(() => {
|
|
14
|
+
pendingRequests.delete(key);
|
|
15
|
+
});
|
|
16
|
+
pendingRequests.set(key, promise);
|
|
17
|
+
return promise;
|
|
18
|
+
}
|
package/esm/utils/index.js
CHANGED
package/hooks/index.d.ts
CHANGED
package/hooks/index.js
CHANGED
|
@@ -17,3 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./useWalletManager"), exports);
|
|
18
18
|
__exportStar(require("./useChain"), exports);
|
|
19
19
|
__exportStar(require("./useChainWallet"), exports);
|
|
20
|
+
__exportStar(require("./useSigningClient"), exports);
|
|
21
|
+
__exportStar(require("./useAsync"), exports);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare const cache: Map<string, any>;
|
|
2
|
+
export declare const activeRequests: Map<string, Promise<any>>;
|
|
3
|
+
type UseAsyncRequestOptions<T> = {
|
|
4
|
+
/**
|
|
5
|
+
* Unique key for the query
|
|
6
|
+
*/
|
|
7
|
+
queryKey: string | any[];
|
|
8
|
+
/**
|
|
9
|
+
* Query function that returns a promise
|
|
10
|
+
* Note: For best performance, use a stable function reference
|
|
11
|
+
* (defined outside component or wrapped in useCallback)
|
|
12
|
+
* But not required - the hook will work without it
|
|
13
|
+
*/
|
|
14
|
+
queryFn: () => Promise<T>;
|
|
15
|
+
/**
|
|
16
|
+
* Whether the query should execute
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Whether to disable caching
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
disableCache?: boolean;
|
|
25
|
+
};
|
|
26
|
+
export declare function useAsync<T>({ queryKey, queryFn, enabled, disableCache, }: UseAsyncRequestOptions<T>): {
|
|
27
|
+
data: T;
|
|
28
|
+
isLoading: boolean;
|
|
29
|
+
error: Error;
|
|
30
|
+
refetch: () => Promise<T>;
|
|
31
|
+
};
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.activeRequests = exports.cache = void 0;
|
|
4
|
+
exports.useAsync = useAsync;
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
exports.cache = new Map();
|
|
7
|
+
exports.activeRequests = new Map();
|
|
8
|
+
function useAsync({ queryKey, queryFn, enabled = true, disableCache = false, }) {
|
|
9
|
+
const [state, setState] = (0, react_1.useState)({
|
|
10
|
+
data: null,
|
|
11
|
+
isLoading: false,
|
|
12
|
+
error: null,
|
|
13
|
+
});
|
|
14
|
+
const mountedRef = (0, react_1.useRef)(false);
|
|
15
|
+
const queryFnRef = (0, react_1.useRef)(queryFn);
|
|
16
|
+
const cacheKey = Array.isArray(queryKey)
|
|
17
|
+
? JSON.stringify(queryKey)
|
|
18
|
+
: queryKey;
|
|
19
|
+
// Always update the current function
|
|
20
|
+
queryFnRef.current = queryFn;
|
|
21
|
+
(0, react_1.useEffect)(() => {
|
|
22
|
+
mountedRef.current = true;
|
|
23
|
+
return () => {
|
|
24
|
+
mountedRef.current = false;
|
|
25
|
+
};
|
|
26
|
+
}, []);
|
|
27
|
+
(0, react_1.useEffect)(() => {
|
|
28
|
+
if (!enabled)
|
|
29
|
+
return;
|
|
30
|
+
if (!disableCache && exports.cache.has(cacheKey)) {
|
|
31
|
+
setState(prev => ({
|
|
32
|
+
...prev,
|
|
33
|
+
data: exports.cache.get(cacheKey),
|
|
34
|
+
isLoading: false,
|
|
35
|
+
error: null,
|
|
36
|
+
}));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (exports.activeRequests.has(cacheKey)) {
|
|
40
|
+
exports.activeRequests.get(cacheKey).then((data) => {
|
|
41
|
+
if (mountedRef.current) {
|
|
42
|
+
setState({
|
|
43
|
+
data,
|
|
44
|
+
isLoading: false,
|
|
45
|
+
error: null,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}, (error) => {
|
|
49
|
+
if (mountedRef.current) {
|
|
50
|
+
setState({
|
|
51
|
+
data: null,
|
|
52
|
+
isLoading: false,
|
|
53
|
+
error,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
setState(prev => ({ ...prev, isLoading: true, error: null }));
|
|
60
|
+
const requestPromise = queryFnRef.current()
|
|
61
|
+
.then((data) => {
|
|
62
|
+
if (!disableCache) {
|
|
63
|
+
exports.cache.set(cacheKey, data);
|
|
64
|
+
}
|
|
65
|
+
if (mountedRef.current) {
|
|
66
|
+
setState({
|
|
67
|
+
data,
|
|
68
|
+
isLoading: false,
|
|
69
|
+
error: null,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return data;
|
|
73
|
+
})
|
|
74
|
+
.catch((error) => {
|
|
75
|
+
if (mountedRef.current) {
|
|
76
|
+
setState({
|
|
77
|
+
data: null,
|
|
78
|
+
isLoading: false,
|
|
79
|
+
error,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
.finally(() => {
|
|
84
|
+
exports.activeRequests.delete(cacheKey);
|
|
85
|
+
});
|
|
86
|
+
exports.activeRequests.set(cacheKey, requestPromise);
|
|
87
|
+
}, [cacheKey, enabled, disableCache]);
|
|
88
|
+
const refetch = async () => {
|
|
89
|
+
try {
|
|
90
|
+
setState(prev => ({ ...prev, isLoading: true, error: null }));
|
|
91
|
+
const data = await queryFnRef.current();
|
|
92
|
+
if (!disableCache) {
|
|
93
|
+
exports.cache.set(cacheKey, data);
|
|
94
|
+
}
|
|
95
|
+
if (mountedRef.current) {
|
|
96
|
+
setState({
|
|
97
|
+
data,
|
|
98
|
+
isLoading: false,
|
|
99
|
+
error: null,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return data;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
if (mountedRef.current) {
|
|
106
|
+
setState({
|
|
107
|
+
data: null,
|
|
108
|
+
isLoading: false,
|
|
109
|
+
error: error,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
return {
|
|
116
|
+
data: state.data,
|
|
117
|
+
isLoading: state.isLoading,
|
|
118
|
+
error: state.error,
|
|
119
|
+
refetch,
|
|
120
|
+
};
|
|
121
|
+
}
|
package/hooks/useChain.js
CHANGED
|
@@ -5,6 +5,7 @@ const modal_1 = require("../modal");
|
|
|
5
5
|
const useWalletManager_1 = require("./useWalletManager");
|
|
6
6
|
const core_1 = require("@interchain-kit/core");
|
|
7
7
|
const chain_wallet_1 = require("../store/chain-wallet");
|
|
8
|
+
const useSigningClient_1 = require("./useSigningClient");
|
|
8
9
|
const useChain = (chainName) => {
|
|
9
10
|
const { assetLists, currentWalletName, disconnect, setCurrentChainName, getChainByName, getWalletByName, getChainWalletState, getChainLogoUrl, connect, getSigningClient, getRpcEndpoint, getAccount } = (0, useWalletManager_1.useWalletManager)();
|
|
10
11
|
const chain = getChainByName(chainName);
|
|
@@ -15,6 +16,7 @@ const useChain = (chainName) => {
|
|
|
15
16
|
const wallet = getWalletByName(currentWalletName);
|
|
16
17
|
const chainWalletStateToShow = getChainWalletState(currentWalletName, chainName);
|
|
17
18
|
const { open, close } = (0, modal_1.useWalletModal)();
|
|
19
|
+
const { signingClient, isLoading: isSigningClientLoading, error: signingClientError } = (0, useSigningClient_1.useSigningClient)(chainName, currentWalletName);
|
|
18
20
|
return {
|
|
19
21
|
//for migration cosmos kit
|
|
20
22
|
connect: () => {
|
|
@@ -37,8 +39,11 @@ const useChain = (chainName) => {
|
|
|
37
39
|
assetList,
|
|
38
40
|
address: chainWalletStateToShow?.account?.address,
|
|
39
41
|
wallet: new chain_wallet_1.ChainWallet(wallet, () => connect(currentWalletName, chainName), () => disconnect(currentWalletName, chainName), () => getAccount(currentWalletName, chainName)),
|
|
40
|
-
rpcEndpoint: chainWalletStateToShow?.rpcEndpoint,
|
|
41
42
|
getSigningClient: () => getSigningClient(currentWalletName, chainName),
|
|
43
|
+
signingClient,
|
|
44
|
+
isSigningClientLoading,
|
|
45
|
+
signingClientError,
|
|
46
|
+
rpcEndpoint: chainWalletStateToShow?.rpcEndpoint,
|
|
42
47
|
};
|
|
43
48
|
};
|
|
44
49
|
exports.useChain = useChain;
|
package/hooks/useChainWallet.js
CHANGED
|
@@ -3,12 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.useChainWallet = void 0;
|
|
4
4
|
const useWalletManager_1 = require("./useWalletManager");
|
|
5
5
|
const chain_wallet_1 = require("../store/chain-wallet");
|
|
6
|
+
const useSigningClient_1 = require("./useSigningClient");
|
|
6
7
|
const useChainWallet = (chainName, walletName) => {
|
|
7
8
|
const { assetLists, disconnect, setCurrentChainName, setCurrentWalletName, getChainByName, getWalletByName, getChainWalletState, getChainLogoUrl, connect, getSigningClient, getRpcEndpoint, getAccount } = (0, useWalletManager_1.useWalletManager)();
|
|
8
9
|
const chain = getChainByName(chainName);
|
|
9
10
|
const wallet = getWalletByName(walletName);
|
|
10
11
|
const assetList = assetLists.find(a => a.chainName === chainName);
|
|
11
12
|
const chainWalletStateToShow = getChainWalletState(walletName, chainName);
|
|
13
|
+
const { signingClient, isLoading: isSigningClientLoading, error: signingClientError } = (0, useSigningClient_1.useSigningClient)(chainName, walletName);
|
|
12
14
|
return {
|
|
13
15
|
//for migration cosmos kit
|
|
14
16
|
connect: async () => {
|
|
@@ -27,8 +29,11 @@ const useChainWallet = (chainName, walletName) => {
|
|
|
27
29
|
assetList,
|
|
28
30
|
address: chainWalletStateToShow?.account?.address,
|
|
29
31
|
wallet: wallet ? new chain_wallet_1.ChainWallet(wallet, () => connect(walletName, chainName), () => disconnect(walletName, chainName), () => getAccount(walletName, chainName)) : null,
|
|
30
|
-
rpcEndpoint: chainWalletStateToShow?.rpcEndpoint,
|
|
31
32
|
getSigningClient: () => getSigningClient(walletName, chainName),
|
|
33
|
+
signingClient,
|
|
34
|
+
isSigningClientLoading,
|
|
35
|
+
signingClientError,
|
|
36
|
+
rpcEndpoint: chainWalletStateToShow?.rpcEndpoint,
|
|
32
37
|
};
|
|
33
38
|
};
|
|
34
39
|
exports.useChainWallet = useChainWallet;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useSigningClient = void 0;
|
|
4
|
+
const useWalletManager_1 = require("./useWalletManager");
|
|
5
|
+
const useAsync_1 = require("./useAsync");
|
|
6
|
+
const core_1 = require("@interchain-kit/core");
|
|
7
|
+
const useSigningClient = (chainName, walletName) => {
|
|
8
|
+
const { getSigningClient, getChainWalletState, getRpcEndpoint } = (0, useWalletManager_1.useWalletManager)();
|
|
9
|
+
const chainWalletState = getChainWalletState(walletName, chainName);
|
|
10
|
+
const { data, isLoading, error } = (0, useAsync_1.useAsync)({
|
|
11
|
+
queryKey: `signing-client-${chainName}-${walletName}`,
|
|
12
|
+
queryFn: async () => {
|
|
13
|
+
await getRpcEndpoint(walletName, chainName);
|
|
14
|
+
return getSigningClient(walletName, chainName);
|
|
15
|
+
},
|
|
16
|
+
enabled: chainWalletState?.walletState === core_1.WalletState.Connected,
|
|
17
|
+
disableCache: true,
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
signingClient: data,
|
|
21
|
+
error,
|
|
22
|
+
isLoading,
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
exports.useSigningClient = useSigningClient;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interchain-kit/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"author": "Hyperweb <developers@hyperweb.io>",
|
|
5
5
|
"description": "interchain-kit wallet connector react package",
|
|
6
6
|
"main": "index.js",
|
|
@@ -34,17 +34,13 @@
|
|
|
34
34
|
"keywords": [],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@chain-registry/v2-types": "^0.53.40",
|
|
37
|
-
"@interchain-kit/core": "0.
|
|
37
|
+
"@interchain-kit/core": "0.3.0",
|
|
38
38
|
"@interchain-ui/react": "1.26.1",
|
|
39
|
-
"@interchainjs/cosmos": "1.
|
|
40
|
-
"@interchainjs/cosmos-types": "1.
|
|
39
|
+
"@interchainjs/cosmos": "1.11.2",
|
|
40
|
+
"@interchainjs/cosmos-types": "1.11.2",
|
|
41
41
|
"@react-icons/all-files": "^4.1.0",
|
|
42
|
-
"@types/react": "^18.3.3",
|
|
43
|
-
"@types/react-dom": "^18.3.0",
|
|
44
42
|
"@walletconnect/types": "^2.17.3",
|
|
45
|
-
"interchainjs": "1.
|
|
46
|
-
"react": "^18.3.1",
|
|
47
|
-
"react-dom": "^18.3.1",
|
|
43
|
+
"interchainjs": "1.11.2",
|
|
48
44
|
"zustand": "^5.0.3"
|
|
49
45
|
},
|
|
50
46
|
"devDependencies": {
|
|
@@ -61,5 +57,11 @@
|
|
|
61
57
|
"jest-environment-jsdom": "^29.7.0",
|
|
62
58
|
"ts-jest": "^29.3.0"
|
|
63
59
|
},
|
|
64
|
-
"
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"@types/react": "^19.0.0",
|
|
62
|
+
"@types/react-dom": "^19.0.0",
|
|
63
|
+
"react": "^19.0.0",
|
|
64
|
+
"react-dom": "^19.0.0"
|
|
65
|
+
},
|
|
66
|
+
"gitHead": "2fa62ae0dbeb2833b55d59c0cfe8446d1c7a7b06"
|
|
65
67
|
}
|
package/store/store.js
CHANGED
|
@@ -5,6 +5,7 @@ const core_1 = require("@interchain-kit/core");
|
|
|
5
5
|
const zustand_1 = require("zustand");
|
|
6
6
|
const immer_1 = require("zustand/middleware/immer");
|
|
7
7
|
const middleware_1 = require("zustand/middleware");
|
|
8
|
+
const utils_1 = require("../utils");
|
|
8
9
|
const immerSyncUp = (newWalletManager) => {
|
|
9
10
|
return (draft) => {
|
|
10
11
|
draft.chains = newWalletManager.chains;
|
|
@@ -40,11 +41,17 @@ const createInterchainStore = (walletManager) => {
|
|
|
40
41
|
});
|
|
41
42
|
},
|
|
42
43
|
init: async () => {
|
|
43
|
-
const
|
|
44
|
+
const oldChainWalletStatesMap = new Map(get().chainWalletState.map(cws => [cws.walletName + cws.chainName, cws]));
|
|
45
|
+
set(draft => {
|
|
46
|
+
draft.chainWalletState = [];
|
|
47
|
+
});
|
|
44
48
|
wallets.forEach(wallet => {
|
|
45
49
|
chains.forEach(chain => {
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
set(draft => {
|
|
51
|
+
if (oldChainWalletStatesMap.has(wallet.info.name + chain.chainName)) {
|
|
52
|
+
draft.chainWalletState.push(oldChainWalletStatesMap.get(wallet.info.name + chain.chainName));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
48
55
|
draft.chainWalletState.push({
|
|
49
56
|
chainName: chain.chainName,
|
|
50
57
|
walletName: wallet.info.name,
|
|
@@ -53,8 +60,8 @@ const createInterchainStore = (walletManager) => {
|
|
|
53
60
|
errorMessage: "",
|
|
54
61
|
account: undefined
|
|
55
62
|
});
|
|
56
|
-
}
|
|
57
|
-
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
58
65
|
});
|
|
59
66
|
});
|
|
60
67
|
const NotExistWallets = [];
|
|
@@ -141,6 +148,9 @@ const createInterchainStore = (walletManager) => {
|
|
|
141
148
|
}
|
|
142
149
|
});
|
|
143
150
|
});
|
|
151
|
+
draft.chainWalletState = draft.chainWalletState.map(cws => {
|
|
152
|
+
return { ...cws, rpcEndpoint: newEndpointOptions?.endpoints?.[cws.chainName]?.rpc?.[0] || cws.rpcEndpoint };
|
|
153
|
+
});
|
|
144
154
|
});
|
|
145
155
|
},
|
|
146
156
|
connect: async (walletName, chainName) => {
|
|
@@ -183,13 +193,23 @@ const createInterchainStore = (walletManager) => {
|
|
|
183
193
|
}
|
|
184
194
|
},
|
|
185
195
|
getAccount: async (walletName, chainName) => {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
196
|
+
try {
|
|
197
|
+
const account = await walletManager.getAccount(walletName, chainName);
|
|
198
|
+
get().updateChainWalletState(walletName, chainName, { account });
|
|
199
|
+
return account;
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
console.log(error);
|
|
203
|
+
}
|
|
189
204
|
},
|
|
190
205
|
getRpcEndpoint: async (walletName, chainName) => {
|
|
191
|
-
|
|
192
|
-
|
|
206
|
+
return (0, utils_1.dedupeAsync)(`${chainName}-rpcEndpoint`, async () => {
|
|
207
|
+
const rpcEndpoint = await walletManager.getRpcEndpoint(walletName, chainName);
|
|
208
|
+
get().wallets.map(wallet => {
|
|
209
|
+
get().updateChainWalletState(wallet.info.name, chainName, { rpcEndpoint });
|
|
210
|
+
});
|
|
211
|
+
return rpcEndpoint;
|
|
212
|
+
});
|
|
193
213
|
},
|
|
194
214
|
getChainLogoUrl(chainName) {
|
|
195
215
|
return walletManager.getChainLogoUrl(chainName);
|
|
@@ -219,7 +239,7 @@ const createInterchainStore = (walletManager) => {
|
|
|
219
239
|
getWalletByName(walletName) {
|
|
220
240
|
return walletManager.getWalletByName(walletName);
|
|
221
241
|
},
|
|
222
|
-
getSigningClient(walletName, chainName) {
|
|
242
|
+
async getSigningClient(walletName, chainName) {
|
|
223
243
|
return walletManager.getSigningClient(walletName, chainName);
|
|
224
244
|
},
|
|
225
245
|
getEnv() {
|
|
@@ -229,7 +249,12 @@ const createInterchainStore = (walletManager) => {
|
|
|
229
249
|
name: 'interchain-kit-store',
|
|
230
250
|
storage: (0, middleware_1.createJSONStorage)(() => localStorage),
|
|
231
251
|
partialize: state => ({
|
|
232
|
-
chainWalletState: state.chainWalletState
|
|
252
|
+
chainWalletState: state.chainWalletState.map(cws => ({
|
|
253
|
+
chainName: cws.chainName,
|
|
254
|
+
walletName: cws.walletName,
|
|
255
|
+
account: cws.account,
|
|
256
|
+
walletState: cws.walletState,
|
|
257
|
+
})),
|
|
233
258
|
currentWalletName: state.currentWalletName,
|
|
234
259
|
currentChainName: state.currentChainName
|
|
235
260
|
}),
|
package/types/chain.d.ts
CHANGED
|
@@ -19,8 +19,11 @@ export type UseChainReturnType = {
|
|
|
19
19
|
assetList: AssetList;
|
|
20
20
|
address: string;
|
|
21
21
|
wallet: ChainWallet<BaseWallet>;
|
|
22
|
-
rpcEndpoint: string | HttpEndpoint;
|
|
22
|
+
rpcEndpoint: string | HttpEndpoint | unknown;
|
|
23
23
|
getSigningClient: () => Promise<SigningClient>;
|
|
24
|
+
signingClient: SigningClient | null;
|
|
25
|
+
isSigningClientLoading: boolean;
|
|
26
|
+
signingClientError: Error | unknown | null;
|
|
24
27
|
} & CosmosKitUseChainReturnType;
|
|
25
28
|
export type UseChainWalletReturnType = Omit<UseChainReturnType, 'openView' | 'closeView'>;
|
|
26
29
|
export type UseInterchainClientReturnType = {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deduplicate async calls to avoid multiple identical requests.
|
|
3
|
+
* @param key - A unique key representing the request.
|
|
4
|
+
* @param asyncFn - A function that returns a Promise.
|
|
5
|
+
* @returns A Promise resolving to the result of the async function.
|
|
6
|
+
*/
|
|
7
|
+
export declare function dedupeAsync<T>(key: string, asyncFn: () => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dedupeAsync = dedupeAsync;
|
|
4
|
+
const pendingRequests = new Map();
|
|
5
|
+
/**
|
|
6
|
+
* Deduplicate async calls to avoid multiple identical requests.
|
|
7
|
+
* @param key - A unique key representing the request.
|
|
8
|
+
* @param asyncFn - A function that returns a Promise.
|
|
9
|
+
* @returns A Promise resolving to the result of the async function.
|
|
10
|
+
*/
|
|
11
|
+
async function dedupeAsync(key, asyncFn) {
|
|
12
|
+
if (pendingRequests.has(key)) {
|
|
13
|
+
return pendingRequests.get(key);
|
|
14
|
+
}
|
|
15
|
+
const promise = asyncFn()
|
|
16
|
+
.finally(() => {
|
|
17
|
+
pendingRequests.delete(key);
|
|
18
|
+
});
|
|
19
|
+
pendingRequests.set(key, promise);
|
|
20
|
+
return promise;
|
|
21
|
+
}
|
package/utils/index.d.ts
CHANGED
package/utils/index.js
CHANGED