@coin-voyage/crypto 2.2.3-beta.0 → 2.2.3
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/evm/create-default-evm-config.js +1 -1
- package/dist/hooks/use-account.js +19 -21
- package/dist/hooks/use-installed-wallets.js +37 -43
- package/dist/hooks/use-last-connector.d.ts +8 -2
- package/dist/hooks/use-last-connector.js +20 -9
- package/dist/hooks/use-universal-connect.js +4 -5
- package/package.json +2 -2
|
@@ -35,7 +35,7 @@ export function createDefaultEVMConfig(props) {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
if (isWalletInstalled("app.phantom.ethereum")) {
|
|
38
|
-
connectors.push(extendConnector(injected({ target: "phantom" }), "phantom", "Phantom"));
|
|
38
|
+
connectors.push(extendConnector(injected({ target: "phantom" }), "app.phantom", "Phantom"));
|
|
39
39
|
}
|
|
40
40
|
if (!isWalletInstalled("coinbase")) {
|
|
41
41
|
const coinbase = createCoinbaseConnector(props?.coinbase ?? {
|
|
@@ -7,6 +7,7 @@ import { useCallback, useRef, useSyncExternalStore } from "react";
|
|
|
7
7
|
import { useAccount as useAccountInternal } from "wagmi";
|
|
8
8
|
import { getConnector } from "../lib/utils/connector";
|
|
9
9
|
import { extendsWalletAdapter } from "../solana/utils";
|
|
10
|
+
import { useLastConnector } from "./use-last-connector";
|
|
10
11
|
const defaultAccount = {
|
|
11
12
|
chainType: ChainType.EVM,
|
|
12
13
|
isConnected: false,
|
|
@@ -110,11 +111,12 @@ const buildUtxoAccount = (btcAccount) => {
|
|
|
110
111
|
* @bigmi/react for Bitcoin, and @mysten/dapp-kit for Sui) and normalizes their responses into a unified Account type.
|
|
111
112
|
*/
|
|
112
113
|
export const useAccount = (args) => {
|
|
114
|
+
const { lastConnector } = useLastConnector();
|
|
115
|
+
const wagmiAccount = useAccountInternal();
|
|
116
|
+
const { wallet } = useWallet();
|
|
117
|
+
const suiWallet = useCurrentWallet();
|
|
118
|
+
const suiAccount = useCurrentAccount();
|
|
113
119
|
const btcConfig = useBigmiConfig();
|
|
114
|
-
// Use @bigmi/client primitives directly instead of @bigmi/react's useAccount
|
|
115
|
-
// to fix "getServerSnapshot should be cached" error. The upstream hook passes
|
|
116
|
-
// an uncached getServerSnapshot to useSyncExternalStore, causing infinite loops
|
|
117
|
-
// during SSR/hydration in Next.js.
|
|
118
120
|
const btcSnapshotCache = useRef(getBtcAccount(btcConfig));
|
|
119
121
|
const btcSubscribe = useCallback((onChange) => watchBtcAccount(btcConfig, {
|
|
120
122
|
onChange: () => {
|
|
@@ -124,33 +126,29 @@ export const useAccount = (args) => {
|
|
|
124
126
|
}), [btcConfig]);
|
|
125
127
|
const btcGetSnapshot = useCallback(() => btcSnapshotCache.current, []);
|
|
126
128
|
const btcAccount = useSyncExternalStore(btcSubscribe, btcGetSnapshot, btcGetSnapshot);
|
|
127
|
-
const wagmiAccount = useAccountInternal();
|
|
128
|
-
const { wallet } = useWallet();
|
|
129
|
-
const suiWallet = useCurrentWallet();
|
|
130
|
-
const suiAccount = useCurrentAccount();
|
|
131
129
|
const lastConnectedAccount = args?.selectedWallet
|
|
132
|
-
? getConnector(args?.selectedWallet.connectors, args?.chainType)
|
|
130
|
+
? getConnector(args?.selectedWallet.connectors, args.chainType ?? lastConnector?.chainType)
|
|
133
131
|
: undefined;
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
132
|
+
const accounts = [
|
|
133
|
+
buildEvmAccount(wagmiAccount),
|
|
134
|
+
buildSolanaAccount(wallet),
|
|
135
|
+
buildSuiAccount(suiWallet, suiAccount),
|
|
136
|
+
buildUtxoAccount(btcAccount),
|
|
137
|
+
];
|
|
139
138
|
const connectedAccounts = accounts.filter((account) => account.isConnected);
|
|
140
139
|
const selectedChainTypeAccount = args?.chainType
|
|
141
|
-
? connectedAccounts.find((account) => account.chainType === args
|
|
140
|
+
? connectedAccounts.find((account) => account.chainType === args.chainType)
|
|
142
141
|
: undefined;
|
|
143
142
|
// If lastConnectedAccount exists, attempt to find a connected account with a matching connector ID or name.
|
|
144
143
|
// If no matching account is found, fallback to the first connected account.
|
|
145
144
|
// If lastConnectedAccount is not present, simply select the first connected account.
|
|
146
145
|
const selectedAccount = lastConnectedAccount
|
|
147
146
|
? connectedAccounts.find((account) => {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
: connectedAccounts[0];
|
|
147
|
+
return (account.chainType === args?.chainType &&
|
|
148
|
+
(account.connector?.id === lastConnectedAccount?.id ||
|
|
149
|
+
account.connector?.name === lastConnectedAccount?.name));
|
|
150
|
+
}) || connectedAccounts.find((account) => account.chainType === args?.chainType)
|
|
151
|
+
: connectedAccounts.find((account) => account.chainType === args?.chainType) || connectedAccounts[0];
|
|
154
152
|
return {
|
|
155
153
|
account: selectedChainTypeAccount || selectedAccount || defaultAccount,
|
|
156
154
|
accounts: connectedAccounts,
|
|
@@ -9,6 +9,18 @@ import { getConnectorIcon } from "../lib/utils/get-connector-icon";
|
|
|
9
9
|
import { getWalletPriority } from "../lib/utils/get-wallet-priority";
|
|
10
10
|
import { isWalletInstalled } from "../lib/utils/is-wallet-installed";
|
|
11
11
|
import { extendsWalletAdapter } from "../solana/utils";
|
|
12
|
+
// canonical wallet ID for multi-chain wallets
|
|
13
|
+
const getCanonicalWalletId = (idOrName) => {
|
|
14
|
+
const lower = idOrName.toLowerCase();
|
|
15
|
+
// Explicit multi-chain wallet mapping
|
|
16
|
+
if (lower.includes("phantom"))
|
|
17
|
+
return "app.phantom";
|
|
18
|
+
if (lower.includes("rainbow"))
|
|
19
|
+
return "me.rainbow";
|
|
20
|
+
if (lower.includes("metamask"))
|
|
21
|
+
return "io.metamask";
|
|
22
|
+
return lower.split(" ")[0];
|
|
23
|
+
};
|
|
12
24
|
export const useInstalledWallets = (filterChainType) => {
|
|
13
25
|
const bigmiConfig = useBigmiConfig?.() ?? null;
|
|
14
26
|
const wagmiConfig = useContext(WagmiContext) ?? null;
|
|
@@ -17,7 +29,7 @@ export const useInstalledWallets = (filterChainType) => {
|
|
|
17
29
|
return useMemo(() => {
|
|
18
30
|
const shouldInclude = (chainType) => !filterChainType || filterChainType === chainType;
|
|
19
31
|
const installedUTXO = shouldInclude(ChainType.UTXO)
|
|
20
|
-
?
|
|
32
|
+
? bigmiConfig?.connectors.filter((c) => isWalletInstalled(c.id)) ?? []
|
|
21
33
|
: [];
|
|
22
34
|
const installedEVM = shouldInclude(ChainType.EVM)
|
|
23
35
|
? Array.from(wagmiConfig?.connectors ?? []).filter((c) => isWalletInstalled(c.id))
|
|
@@ -26,55 +38,38 @@ export const useInstalledWallets = (filterChainType) => {
|
|
|
26
38
|
? solanaWallets.filter((w) => [WalletReadyState.Installed, WalletReadyState.Loadable].includes(w.adapter.readyState))
|
|
27
39
|
: [];
|
|
28
40
|
const installedSui = shouldInclude(ChainType.SUI) && suiWallets ? suiWallets : [];
|
|
29
|
-
return combineWalletLists(installedUTXO, installedEVM, installedSol, installedSui);
|
|
41
|
+
return combineWalletLists(installedUTXO, installedEVM, installedSol, installedSui, filterChainType);
|
|
30
42
|
}, [bigmiConfig?.connectors, wagmiConfig?.connectors, solanaWallets, suiWallets, filterChainType]);
|
|
31
43
|
};
|
|
32
|
-
const combineWalletLists = (utxoConnectorList, evmConnectorList, solanaWalletList, suiWalletList) => {
|
|
33
|
-
const
|
|
44
|
+
const combineWalletLists = (utxoConnectorList, evmConnectorList, solanaWalletList, suiWalletList, filterChainType) => {
|
|
45
|
+
const walletMap = new Map();
|
|
46
|
+
const addConnector = (rawId, displayName, icon, connector) => {
|
|
47
|
+
const walletId = getCanonicalWalletId(rawId);
|
|
48
|
+
if (filterChainType && connector.chainType !== filterChainType)
|
|
49
|
+
return;
|
|
50
|
+
const existing = walletMap.get(walletId);
|
|
51
|
+
if (existing) {
|
|
52
|
+
existing.connectors.push(connector);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
walletMap.set(walletId, { id: walletId, name: displayName, icon, connectors: [connector] });
|
|
56
|
+
}
|
|
57
|
+
};
|
|
34
58
|
utxoConnectorList.forEach((utxo) => {
|
|
35
|
-
|
|
36
|
-
id: utxo.id,
|
|
37
|
-
name: utxo.name,
|
|
38
|
-
icon: getConnectorIcon(utxo),
|
|
39
|
-
connector: { connector: utxo, chainType: ChainType.UTXO },
|
|
40
|
-
});
|
|
59
|
+
addConnector(utxo.id, utxo.name, getConnectorIcon(utxo), { connector: utxo, chainType: ChainType.UTXO });
|
|
41
60
|
});
|
|
42
61
|
evmConnectorList.forEach((evm) => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
name: evm?.displayName || evm?.name,
|
|
46
|
-
icon: getConnectorIcon(evm),
|
|
47
|
-
connector: { connector: evm, chainType: ChainType.EVM },
|
|
48
|
-
});
|
|
62
|
+
const name = evm?.displayName || evm?.name;
|
|
63
|
+
addConnector(evm.id, name, getConnectorIcon(evm), { connector: evm, chainType: ChainType.EVM });
|
|
49
64
|
});
|
|
50
65
|
solanaWalletList.forEach((svm) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
icon: svm.adapter.icon,
|
|
55
|
-
connector: {
|
|
56
|
-
connector: extendsWalletAdapter(svm.adapter, svm.adapter.name),
|
|
57
|
-
chainType: ChainType.SOL,
|
|
58
|
-
},
|
|
66
|
+
addConnector(svm.adapter.name, svm.adapter.name, svm.adapter.icon, {
|
|
67
|
+
connector: extendsWalletAdapter(svm.adapter, svm.adapter.name),
|
|
68
|
+
chainType: ChainType.SOL,
|
|
59
69
|
});
|
|
60
70
|
});
|
|
61
71
|
suiWalletList.forEach((moveVM) => {
|
|
62
|
-
|
|
63
|
-
id: moveVM.name,
|
|
64
|
-
name: moveVM.name,
|
|
65
|
-
icon: moveVM.icon,
|
|
66
|
-
connector: { connector: moveVM, chainType: ChainType.SUI },
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
const walletMap = new Map();
|
|
70
|
-
allConnectors.forEach(({ id, name, icon, connector }) => {
|
|
71
|
-
const existing = walletMap.get(id);
|
|
72
|
-
if (existing) {
|
|
73
|
-
existing.connectors.push(connector);
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
walletMap.set(id, { id, name, icon, connectors: [connector] });
|
|
77
|
-
}
|
|
72
|
+
addConnector(moveVM.name, moveVM.name, moveVM.icon, { connector: moveVM, chainType: ChainType.SUI });
|
|
78
73
|
});
|
|
79
74
|
const combinedWallets = Array.from(walletMap.values());
|
|
80
75
|
combinedWallets.sort(walletComparator);
|
|
@@ -83,8 +78,7 @@ const combineWalletLists = (utxoConnectorList, evmConnectorList, solanaWalletLis
|
|
|
83
78
|
const walletComparator = (a, b) => {
|
|
84
79
|
const priorityA = getWalletPriority(a.id);
|
|
85
80
|
const priorityB = getWalletPriority(b.id);
|
|
86
|
-
if (priorityA !== priorityB)
|
|
81
|
+
if (priorityA !== priorityB)
|
|
87
82
|
return priorityA - priorityB;
|
|
88
|
-
|
|
89
|
-
return a.id?.localeCompare(b.id);
|
|
83
|
+
return a.id.localeCompare(b.id);
|
|
90
84
|
};
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
import type { ChainType } from "@coin-voyage/shared/types";
|
|
2
|
+
import type { WalletConnector } from "../types/wallet-connector";
|
|
1
3
|
export declare const useLastConnector: () => {
|
|
2
|
-
lastConnectorId: string |
|
|
3
|
-
|
|
4
|
+
lastConnectorId: string | undefined;
|
|
5
|
+
lastConnector: {
|
|
6
|
+
id: string;
|
|
7
|
+
chainType: ChainType;
|
|
8
|
+
} | null;
|
|
9
|
+
updateLastConnectorId: (connector: WalletConnector, chainType: ChainType) => void;
|
|
4
10
|
};
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { getValue, setValue } from "@coin-voyage/shared/common";
|
|
2
|
-
import { useState } from "react";
|
|
2
|
+
import { useCallback, useState } from "react";
|
|
3
|
+
import { getConnectorId } from "../lib/utils/connector";
|
|
3
4
|
export const useLastConnector = () => {
|
|
4
|
-
const [
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return id ?? "";
|
|
5
|
+
const [lastConnectorIdWithChain, setLastConnectorIdWithChain] = useState(() => {
|
|
6
|
+
const stored = getValue("@coin-voyage/recentConnectorId");
|
|
7
|
+
return stored ?? null;
|
|
8
8
|
});
|
|
9
|
-
const updateLastConnectorId = (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const updateLastConnectorId = useCallback((connector, chainType) => {
|
|
10
|
+
const idWithChain = `${getConnectorId(connector)}-${chainType}`;
|
|
11
|
+
setValue("@coin-voyage/recentConnectorId", idWithChain);
|
|
12
|
+
setLastConnectorIdWithChain(idWithChain);
|
|
13
|
+
}, []);
|
|
14
|
+
// Parse into ID + chainType for easy access
|
|
15
|
+
const lastConnector = lastConnectorIdWithChain
|
|
16
|
+
? (() => {
|
|
17
|
+
const split = lastConnectorIdWithChain.split("-");
|
|
18
|
+
const id = split[0];
|
|
19
|
+
const chainType = split[1];
|
|
20
|
+
return { id, chainType };
|
|
21
|
+
})()
|
|
22
|
+
: null;
|
|
23
|
+
return { lastConnectorId: lastConnector?.id, lastConnector, updateLastConnectorId };
|
|
13
24
|
};
|
|
@@ -4,7 +4,6 @@ import { useConnectWallet } from "@mysten/dapp-kit";
|
|
|
4
4
|
import { useWallet } from "@solana/wallet-adapter-react";
|
|
5
5
|
import { useCallback } from "react";
|
|
6
6
|
import { useConfig as useWagmiConfig, useConnect as useWagmiConnect } from "wagmi";
|
|
7
|
-
import { getConnectorId } from "../lib/utils/connector";
|
|
8
7
|
import { useLastConnector } from "./use-last-connector";
|
|
9
8
|
export const useUniversalConnect = (props) => {
|
|
10
9
|
const utxoConfig = useBigmiConfig();
|
|
@@ -19,7 +18,7 @@ export const useUniversalConnect = (props) => {
|
|
|
19
18
|
...props,
|
|
20
19
|
onSuccess(data, variables) {
|
|
21
20
|
const connector = variables.connector || variables.connector;
|
|
22
|
-
updateLastConnectorId(
|
|
21
|
+
updateLastConnectorId(connector, ChainType.EVM);
|
|
23
22
|
onSuccess?.(data, {
|
|
24
23
|
chainId: variables?.chainId,
|
|
25
24
|
connector,
|
|
@@ -34,7 +33,7 @@ export const useUniversalConnect = (props) => {
|
|
|
34
33
|
...props,
|
|
35
34
|
onSuccess(data, variables) {
|
|
36
35
|
const connector = variables.connector;
|
|
37
|
-
updateLastConnectorId(
|
|
36
|
+
updateLastConnectorId(connector, ChainType.UTXO);
|
|
38
37
|
onSuccess?.(data, {
|
|
39
38
|
chainId: ChainId.BTC,
|
|
40
39
|
connector,
|
|
@@ -83,7 +82,7 @@ export const useUniversalConnect = (props) => {
|
|
|
83
82
|
walletAdapter.connect().catch(handleError);
|
|
84
83
|
});
|
|
85
84
|
}
|
|
86
|
-
updateLastConnectorId(
|
|
85
|
+
updateLastConnectorId(connector, ChainType.SOL);
|
|
87
86
|
onSuccess?.(undefined, { connector: walletAdapter });
|
|
88
87
|
break;
|
|
89
88
|
}
|
|
@@ -93,7 +92,7 @@ export const useUniversalConnect = (props) => {
|
|
|
93
92
|
}, {
|
|
94
93
|
onError,
|
|
95
94
|
onSuccess: async (data) => {
|
|
96
|
-
updateLastConnectorId(
|
|
95
|
+
updateLastConnectorId(connector, ChainType.SUI);
|
|
97
96
|
onSuccess?.(data, { connector });
|
|
98
97
|
},
|
|
99
98
|
onSettled: onSettled,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coin-voyage/crypto",
|
|
3
3
|
"description": "Crypto utilities for Coin Voyage",
|
|
4
|
-
"version": "2.2.3
|
|
4
|
+
"version": "2.2.3",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"author": "Lars <lars@coinvoyage.io>",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@solana/wallet-adapter-walletconnect": "0.1.21",
|
|
51
51
|
"@solana/wallet-adapter-base": "0.9.27",
|
|
52
52
|
"@solana/wallet-adapter-coinbase": "0.1.23",
|
|
53
|
-
"@coin-voyage/shared": "2.2.5
|
|
53
|
+
"@coin-voyage/shared": "2.2.5"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/elliptic": "6.4.18"
|