@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.
@@ -1,3 +1,5 @@
1
1
  export * from './useWalletManager';
2
2
  export * from './useChain';
3
3
  export * from './useChainWallet';
4
+ export * from './useSigningClient';
5
+ export * from './useAsync';
@@ -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
+ }
@@ -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
+ };
@@ -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 existedChainWalletStatesMap = new Map(get().chainWalletState.map(cws => [cws.walletName + cws.chainName, cws]));
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
- if (!existedChainWalletStatesMap.has(wallet.info.name + chain.chainName)) {
44
- set(draft => {
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
- const account = await walletManager.getAccount(walletName, chainName);
184
- get().updateChainWalletState(walletName, chainName, { account });
185
- return account;
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
- const rpcEndpoint = await walletManager.getRpcEndpoint(walletName, chainName);
189
- return rpcEndpoint;
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
+ }
@@ -1 +1,2 @@
1
1
  export * from './wallet';
2
+ export * from './dedupeAsync';
package/hooks/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export * from './useWalletManager';
2
2
  export * from './useChain';
3
3
  export * from './useChainWallet';
4
+ export * from './useSigningClient';
5
+ export * from './useAsync';
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;
@@ -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,5 @@
1
+ export declare const useSigningClient: (chainName: string, walletName: string) => {
2
+ signingClient: import("@interchainjs/cosmos/signing-client").SigningClient;
3
+ error: Error;
4
+ isLoading: boolean;
5
+ };
@@ -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.2.221",
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.2.221",
37
+ "@interchain-kit/core": "0.3.0",
38
38
  "@interchain-ui/react": "1.26.1",
39
- "@interchainjs/cosmos": "1.10.1",
40
- "@interchainjs/cosmos-types": "1.10.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.10.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
- "gitHead": "8858e1325a57cd4082cb9658fb480952d1a0eec9"
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 existedChainWalletStatesMap = new Map(get().chainWalletState.map(cws => [cws.walletName + cws.chainName, cws]));
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
- if (!existedChainWalletStatesMap.has(wallet.info.name + chain.chainName)) {
47
- set(draft => {
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
- const account = await walletManager.getAccount(walletName, chainName);
187
- get().updateChainWalletState(walletName, chainName, { account });
188
- return account;
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
- const rpcEndpoint = await walletManager.getRpcEndpoint(walletName, chainName);
192
- return rpcEndpoint;
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
@@ -1 +1,2 @@
1
1
  export * from './wallet';
2
+ export * from './dedupeAsync';
package/utils/index.js CHANGED
@@ -15,3 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./wallet"), exports);
18
+ __exportStar(require("./dedupeAsync"), exports);