-
Notifications
You must be signed in to change notification settings - Fork 589
/
connectorsForWallets.ts
185 lines (162 loc) Β· 5.81 KB
/
connectorsForWallets.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import { Connector } from 'wagmi';
import { WalletConnectConnector } from 'wagmi/connectors/walletConnect';
import { isHexString } from '../utils/colors';
import { isMobile } from '../utils/isMobile';
import { omitUndefinedValues } from '../utils/omitUndefinedValues';
import { Wallet, WalletInstance, WalletList } from './Wallet';
interface WalletListItem extends Wallet {
index: number;
groupIndex: number;
groupName: string;
}
/*
Build your own list of wallets for the RainbowKit modal
with their necessary connectors. This way you have full
control over which wallets to display, and in which order.
Returns a `connectors` fn to pass directly to Wagmi's `createConfig`.
*/
export function connectorsForWallets(walletList: WalletList): () => Connector[];
/*
Assemble a list of low-level connectors for use with the
`WalletButton` and `RainbowButton` components in custom implementations.
*/
export function connectorsForWallets(wallets: Wallet[]): Connector[];
/*
Overload implementation for `connectorsForWallets`.
1. Returns a `connectors` function that will then return a Connectors array
2. Returns a prepared Connectors array stuffed with dummy WalletList data
*/
export function connectorsForWallets(walletList: any): any {
if ('groupName' in walletList[0]) {
return _connectorsForWallets(walletList);
}
return _connectorsForWallets([
{
groupName: '',
wallets: walletList as Wallet[],
},
])();
}
const _connectorsForWallets = (walletList: WalletList): (() => Connector[]) => {
return () => {
let index = -1;
const connectors: Connector[] = [];
const visibleWallets: WalletListItem[] = [];
const potentiallyHiddenWallets: WalletListItem[] = [];
const walletInstances: WalletInstance[] = [];
// First collect all list items in the correct order, but keep
// track of which ones have a `hidden` function so we can
// evaluate them after all the visible wallet instances have
// been created. This is because the potentially hidden wallets
// need access to the list of resolved wallet instances so that
// they can decide whether or not they should be hidden,
// e.g. the "Injected Wallet" option hides itself if another
// injected wallet is available.
// biome-ignore lint/complexity/noForEach: TODO
walletList.forEach(({ groupName, wallets }, groupIndex) => {
// biome-ignore lint/complexity/noForEach: TODO
wallets.forEach((wallet) => {
index++;
// guard against non-hex values for `iconAccent`
if (wallet?.iconAccent && !isHexString(wallet?.iconAccent)) {
throw new Error(
`Property \`iconAccent\` is not a hex value for wallet: ${wallet.name}`,
);
}
const walletListItem = {
...wallet,
groupIndex,
groupName,
index,
};
if (typeof wallet.hidden === 'function') {
potentiallyHiddenWallets.push(walletListItem);
} else {
visibleWallets.push(walletListItem);
}
});
});
// We process the known visible wallets first so that the potentially
// hidden wallets have access to the complete list of resolved wallets
const walletListItems: WalletListItem[] = [
...visibleWallets,
...potentiallyHiddenWallets,
];
// biome-ignore lint/complexity/noForEach: TODO
walletListItems.forEach(
({
createConnector,
groupIndex,
groupName,
hidden,
index,
...walletMeta
}) => {
if (typeof hidden === 'function') {
// Run the function to check if the wallet needs to be hidden
const isHidden = hidden({
wallets: [
// Note: We only expose a subset of fields
// publicly to reduce API surface area
...walletInstances.map(({ connector, id, installed, name }) => ({
connector,
id,
installed,
name,
})),
],
});
// If wallet is hidden, bail out and proceed to the next list item
if (isHidden) {
return;
}
}
const { connector, ...connectionMethods } = omitUndefinedValues(
createConnector(),
);
let walletConnectModalConnector: Connector | undefined;
if (
walletMeta.id === 'walletConnect' &&
connectionMethods.qrCode &&
!isMobile()
) {
const { chains, options } = connector;
walletConnectModalConnector = new WalletConnectConnector({
chains,
options: {
...options,
showQrModal: true,
},
});
connectors.push(walletConnectModalConnector);
}
const walletInstance: WalletInstance = {
connector,
groupIndex,
groupName,
index,
walletConnectModalConnector,
...walletMeta,
...connectionMethods,
};
// We maintain an array of all wallet instances
// so they can be passed to the `hidden` function
// used by generic fallback wallets
walletInstances.push(walletInstance);
if (!connectors.includes(connector)) {
connectors.push(connector);
// Reset private wallet list the first time we see
// a connector to avoid duplicates after HMR,
// otherwise we'll keep pushing wallets into
// the old list. This is happening because we're
// re-using the WalletConnectConnector instance
// so the wallet list already exists after HMR.
connector._wallets = [];
}
// Add wallet to connector's list of associated wallets
connector._wallets.push(walletInstance);
},
);
return connectors;
};
};