-
Notifications
You must be signed in to change notification settings - Fork 37
/
useStandardWalletAdapters.ts
80 lines (71 loc) · 3.08 KB
/
useStandardWalletAdapters.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import type { Adapter, WalletName } from '@solana/wallet-adapter-base';
import { isWalletAdapterCompatibleWallet, StandardWalletAdapter } from '@solana/wallet-standard-wallet-adapter-base';
import { DEPRECATED_getWallets } from '@wallet-standard/app';
import type { Wallet } from '@wallet-standard/base';
import { useEffect, useMemo, useRef, useState } from 'react';
export function useStandardWalletAdapters(adapters: Adapter[]): Adapter[] {
const warnings = useConstant(() => new Set<WalletName>());
const { get, on } = useConstant(() => DEPRECATED_getWallets());
const [standardAdapters, setStandardAdapters] = useState(() => wrapWalletsWithAdapters(get()));
useEffect(() => {
const listeners = [
on('register', (...wallets) =>
setStandardAdapters((standardAdapters) => [...standardAdapters, ...wrapWalletsWithAdapters(wallets)])
),
on('unregister', (...wallets) =>
setStandardAdapters((standardAdapters) =>
standardAdapters.filter((standardAdapter) =>
wallets.some((wallet) => wallet === standardAdapter.wallet)
)
)
),
];
return () => listeners.forEach((off) => off());
}, [on]);
const prevStandardAdapters = usePrevious(standardAdapters);
useEffect(() => {
if (!prevStandardAdapters) return;
const currentAdapters = new Set(standardAdapters);
const removedAdapters = new Set(
prevStandardAdapters.filter((previousAdapter) => !currentAdapters.has(previousAdapter))
);
removedAdapters.forEach((adapter) => adapter.destroy());
}, [prevStandardAdapters, standardAdapters]);
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => () => standardAdapters.forEach((adapter) => adapter.destroy()), []);
return useMemo(
() => [
...standardAdapters,
...adapters.filter(({ name }) => {
if (standardAdapters.some((standardAdapter) => standardAdapter.name === name)) {
if (!warnings.has(name)) {
warnings.add(name);
console.warn(
`${name} was registered as a Standard Wallet. The Wallet Adapter for ${name} can be removed from your app.`
);
}
return false;
}
return true;
}),
],
[standardAdapters, adapters, warnings]
);
}
function useConstant<T>(fn: () => T): T {
const ref = useRef<{ value: T }>();
if (!ref.current) {
ref.current = { value: fn() };
}
return ref.current.value;
}
function usePrevious<T>(state: T): T | undefined {
const ref = useRef<T>();
useEffect(() => {
ref.current = state;
});
return ref.current;
}
function wrapWalletsWithAdapters(wallets: readonly Wallet[]): readonly StandardWalletAdapter[] {
return wallets.filter(isWalletAdapterCompatibleWallet).map((wallet) => new StandardWalletAdapter({ wallet }));
}