@rango-dev/wallets-react 0.0.0-experimental-936229e8-20251208
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/CHANGELOG.md +265 -0
- package/dist/helpers/index.d.ts +2 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +2 -0
- package/dist/helpers/index.js.map +7 -0
- package/dist/hub/autoConnect.d.ts +11 -0
- package/dist/hub/autoConnect.d.ts.map +1 -0
- package/dist/hub/constants.d.ts +3 -0
- package/dist/hub/constants.d.ts.map +1 -0
- package/dist/hub/helpers.d.ts +33 -0
- package/dist/hub/helpers.d.ts.map +1 -0
- package/dist/hub/lastConnectedWallets.d.ts +22 -0
- package/dist/hub/lastConnectedWallets.d.ts.map +1 -0
- package/dist/hub/mod.d.ts +3 -0
- package/dist/hub/mod.d.ts.map +1 -0
- package/dist/hub/types.d.ts +4 -0
- package/dist/hub/types.d.ts.map +1 -0
- package/dist/hub/useHubAdapter.d.ts +11 -0
- package/dist/hub/useHubAdapter.d.ts.map +1 -0
- package/dist/hub/useHubRefs.d.ts +7 -0
- package/dist/hub/useHubRefs.d.ts.map +1 -0
- package/dist/hub/utils.d.ts +52 -0
- package/dist/hub/utils.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +7 -0
- package/dist/legacy/autoConnect.d.ts +8 -0
- package/dist/legacy/autoConnect.d.ts.map +1 -0
- package/dist/legacy/context.d.ts +3 -0
- package/dist/legacy/context.d.ts.map +1 -0
- package/dist/legacy/helpers.d.ts +23 -0
- package/dist/legacy/helpers.d.ts.map +1 -0
- package/dist/legacy/hooks.d.ts +10 -0
- package/dist/legacy/hooks.d.ts.map +1 -0
- package/dist/legacy/mod.d.ts +5 -0
- package/dist/legacy/mod.d.ts.map +1 -0
- package/dist/legacy/types.d.ts +143 -0
- package/dist/legacy/types.d.ts.map +1 -0
- package/dist/legacy/useAutoConnect.d.ts +8 -0
- package/dist/legacy/useAutoConnect.d.ts.map +1 -0
- package/dist/legacy/useLegacyProviders.d.ts +7 -0
- package/dist/legacy/useLegacyProviders.d.ts.map +1 -0
- package/dist/legacy/utils.d.ts +3 -0
- package/dist/legacy/utils.d.ts.map +1 -0
- package/dist/provider.d.ts +5 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/test-utils/env.d.ts +7 -0
- package/dist/test-utils/env.d.ts.map +1 -0
- package/dist/test-utils/fixtures.d.ts +14 -0
- package/dist/test-utils/fixtures.d.ts.map +1 -0
- package/dist/useProviders.d.ts +4 -0
- package/dist/useProviders.d.ts.map +1 -0
- package/dist/wallets-react.build.json +1 -0
- package/helpers/package.json +8 -0
- package/package.json +50 -0
- package/readme.md +3 -0
- package/src/helpers/index.ts +1 -0
- package/src/hub/autoConnect.ts +276 -0
- package/src/hub/constants.ts +2 -0
- package/src/hub/helpers.ts +179 -0
- package/src/hub/lastConnectedWallets.ts +166 -0
- package/src/hub/mod.ts +6 -0
- package/src/hub/types.ts +12 -0
- package/src/hub/useHubAdapter.ts +516 -0
- package/src/hub/useHubRefs.ts +50 -0
- package/src/hub/utils.ts +393 -0
- package/src/index.ts +4 -0
- package/src/legacy/autoConnect.ts +66 -0
- package/src/legacy/context.ts +39 -0
- package/src/legacy/helpers.ts +183 -0
- package/src/legacy/hooks.ts +54 -0
- package/src/legacy/mod.ts +13 -0
- package/src/legacy/types.ts +195 -0
- package/src/legacy/useAutoConnect.ts +23 -0
- package/src/legacy/useLegacyProviders.ts +241 -0
- package/src/legacy/utils.ts +7 -0
- package/src/provider.tsx +18 -0
- package/src/test-utils/env.ts +10 -0
- package/src/test-utils/fixtures.ts +238 -0
- package/src/useProviders.ts +120 -0
package/src/hub/utils.ts
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import type { AllProxiedNamespaces } from './types.js';
|
|
2
|
+
import type { Hub, Provider, ProxiedNamespace } from '@rango-dev/wallets-core';
|
|
3
|
+
import type {
|
|
4
|
+
LegacyNamespaceInputForConnect,
|
|
5
|
+
LegacyProviderInterface,
|
|
6
|
+
LegacyEventHandler as WalletEventHandler,
|
|
7
|
+
} from '@rango-dev/wallets-core/legacy';
|
|
8
|
+
import type { CosmosActions } from '@rango-dev/wallets-core/namespaces/cosmos';
|
|
9
|
+
import type { EvmActions } from '@rango-dev/wallets-core/namespaces/evm';
|
|
10
|
+
import type { SolanaActions } from '@rango-dev/wallets-core/namespaces/solana';
|
|
11
|
+
import type { SuiActions } from '@rango-dev/wallets-core/namespaces/sui';
|
|
12
|
+
import type { UtxoActions } from '@rango-dev/wallets-core/namespaces/utxo';
|
|
13
|
+
import type { Event } from '@rango-dev/wallets-core/store';
|
|
14
|
+
|
|
15
|
+
import { LegacyEvents as Events } from '@rango-dev/wallets-core/legacy';
|
|
16
|
+
import { type VersionedProviders } from '@rango-dev/wallets-core/utils';
|
|
17
|
+
import { pickVersion } from '@rango-dev/wallets-core/utils';
|
|
18
|
+
import {
|
|
19
|
+
type AddEthereumChainParameter,
|
|
20
|
+
convertEvmBlockchainMetaToEvmChainInfo,
|
|
21
|
+
type WalletType,
|
|
22
|
+
} from '@rango-dev/wallets-shared';
|
|
23
|
+
import { type BlockchainMeta, isEvmBlockchain } from 'rango-types';
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
type ConnectResult,
|
|
27
|
+
HUB_LAST_CONNECTED_WALLETS,
|
|
28
|
+
type ProviderProps,
|
|
29
|
+
} from '../legacy/mod.js';
|
|
30
|
+
|
|
31
|
+
import {
|
|
32
|
+
fromAccountIdToLegacyAddressFormat,
|
|
33
|
+
isConnectResultEvm,
|
|
34
|
+
isConnectResultSolana,
|
|
35
|
+
} from './helpers.js';
|
|
36
|
+
import { LastConnectedWalletsFromStorage } from './lastConnectedWallets.js';
|
|
37
|
+
|
|
38
|
+
/* Gets a list of hub and legacy providers and returns a tuple which separates them. */
|
|
39
|
+
export function separateLegacyAndHubProviders(
|
|
40
|
+
providers: VersionedProviders[]
|
|
41
|
+
): [LegacyProviderInterface[], Provider[]] {
|
|
42
|
+
const LEGACY_VERSION = '0.0.0';
|
|
43
|
+
const HUB_VERSION = '1.0.0';
|
|
44
|
+
|
|
45
|
+
const legacyProviders: LegacyProviderInterface[] = [];
|
|
46
|
+
const hubProviders: Provider[] = [];
|
|
47
|
+
|
|
48
|
+
providers.forEach((provider) => {
|
|
49
|
+
try {
|
|
50
|
+
const target = pickVersion(provider, HUB_VERSION);
|
|
51
|
+
hubProviders.push(target[1]);
|
|
52
|
+
} catch {
|
|
53
|
+
const target = pickVersion(provider, LEGACY_VERSION);
|
|
54
|
+
legacyProviders.push(target[1]);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return [legacyProviders, hubProviders];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function findProviderByType(
|
|
62
|
+
providers: Provider[],
|
|
63
|
+
type: string
|
|
64
|
+
): Provider | undefined {
|
|
65
|
+
return providers.find((provider) => provider.id === type);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* We will call this function on hub's `subscribe`.
|
|
70
|
+
* it will check states and will emit legacy events for backward compatibility.
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(
|
|
74
|
+
HUB_LAST_CONNECTED_WALLETS
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
export function getSupportedChainsFromProvider(
|
|
78
|
+
provider: Provider,
|
|
79
|
+
allBlockChains: ProviderProps['allBlockChains']
|
|
80
|
+
) {
|
|
81
|
+
const namespacesProperty = provider
|
|
82
|
+
.info()
|
|
83
|
+
?.metadata.properties?.find((property) => property.name === 'namespaces');
|
|
84
|
+
|
|
85
|
+
const supportedChains =
|
|
86
|
+
namespacesProperty?.value.data.flatMap((namespace) =>
|
|
87
|
+
namespace.getSupportedChains(allBlockChains || [])
|
|
88
|
+
) || [];
|
|
89
|
+
|
|
90
|
+
return supportedChains;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function mapHubEventsToLegacy(
|
|
94
|
+
hub: Hub,
|
|
95
|
+
event: Event,
|
|
96
|
+
onUpdateState: WalletEventHandler,
|
|
97
|
+
metadata: {
|
|
98
|
+
allBlockChains: ProviderProps['allBlockChains'];
|
|
99
|
+
lastConnectAttemptParams: {
|
|
100
|
+
[type: WalletType]: LegacyNamespaceInputForConnect[];
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
): void {
|
|
104
|
+
const provider = hub.get(event.provider);
|
|
105
|
+
if (!provider) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
"Currently all the events have assigned to a provider. The event doesn't include one.",
|
|
108
|
+
{
|
|
109
|
+
cause: event,
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// @ts-expect-error for those events that doesn't have namespace, it will be undefinded
|
|
115
|
+
const namespaceId: string | undefined = event.namespace;
|
|
116
|
+
|
|
117
|
+
const namespace = namespaceId
|
|
118
|
+
? provider.findByNamespace(namespaceId)
|
|
119
|
+
: undefined;
|
|
120
|
+
let accounts: string[] | null = null;
|
|
121
|
+
let network: string | null = null;
|
|
122
|
+
let derivationPath: string | undefined;
|
|
123
|
+
|
|
124
|
+
if (namespace) {
|
|
125
|
+
const [getNamespaceState] = namespace.state();
|
|
126
|
+
accounts = getNamespaceState().accounts;
|
|
127
|
+
network = getNamespaceState().network;
|
|
128
|
+
|
|
129
|
+
if (metadata.lastConnectAttemptParams[event.provider]) {
|
|
130
|
+
derivationPath = metadata.lastConnectAttemptParams[event.provider].find(
|
|
131
|
+
(namespace) => namespace.namespace === namespaceId
|
|
132
|
+
)?.derivationPath;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const [getProviderState] = provider.state();
|
|
137
|
+
const coreState = {
|
|
138
|
+
connected: getProviderState().connected,
|
|
139
|
+
connecting: getProviderState().connecting,
|
|
140
|
+
installed: getProviderState().installed,
|
|
141
|
+
accounts,
|
|
142
|
+
network,
|
|
143
|
+
reachable: true,
|
|
144
|
+
derivationPath,
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const eventInfo = {
|
|
148
|
+
supportedBlockchains: getSupportedChainsFromProvider(
|
|
149
|
+
provider,
|
|
150
|
+
metadata.allBlockChains
|
|
151
|
+
),
|
|
152
|
+
isContractWallet: false,
|
|
153
|
+
isHub: true,
|
|
154
|
+
namespace: namespaceId,
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
switch (event.type) {
|
|
158
|
+
case 'provider_detected':
|
|
159
|
+
onUpdateState(
|
|
160
|
+
event.provider,
|
|
161
|
+
Events.INSTALLED,
|
|
162
|
+
true,
|
|
163
|
+
coreState,
|
|
164
|
+
eventInfo
|
|
165
|
+
);
|
|
166
|
+
break;
|
|
167
|
+
case 'provider_connecting':
|
|
168
|
+
onUpdateState(
|
|
169
|
+
event.provider,
|
|
170
|
+
Events.CONNECTING,
|
|
171
|
+
event.value,
|
|
172
|
+
coreState,
|
|
173
|
+
eventInfo
|
|
174
|
+
);
|
|
175
|
+
break;
|
|
176
|
+
case 'provider_connected':
|
|
177
|
+
onUpdateState(
|
|
178
|
+
event.provider,
|
|
179
|
+
Events.CONNECTED,
|
|
180
|
+
true,
|
|
181
|
+
coreState,
|
|
182
|
+
eventInfo
|
|
183
|
+
);
|
|
184
|
+
break;
|
|
185
|
+
case 'provider_disconnected':
|
|
186
|
+
onUpdateState(
|
|
187
|
+
event.provider,
|
|
188
|
+
Events.PROVIDER_DISCONNECTED,
|
|
189
|
+
event.provider,
|
|
190
|
+
coreState,
|
|
191
|
+
eventInfo
|
|
192
|
+
);
|
|
193
|
+
onUpdateState(
|
|
194
|
+
event.provider,
|
|
195
|
+
Events.CONNECTED,
|
|
196
|
+
false,
|
|
197
|
+
coreState,
|
|
198
|
+
eventInfo
|
|
199
|
+
);
|
|
200
|
+
onUpdateState(
|
|
201
|
+
event.provider,
|
|
202
|
+
Events.ACCOUNTS,
|
|
203
|
+
null,
|
|
204
|
+
coreState,
|
|
205
|
+
eventInfo
|
|
206
|
+
);
|
|
207
|
+
break;
|
|
208
|
+
case 'namespace_disconnected':
|
|
209
|
+
lastConnectedWalletsFromStorage.removeNamespacesFromWallet(
|
|
210
|
+
event.provider,
|
|
211
|
+
[event.namespace]
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
onUpdateState(
|
|
215
|
+
event.provider,
|
|
216
|
+
Events.NAMESPACE_DISCONNECTED,
|
|
217
|
+
event.namespace,
|
|
218
|
+
coreState,
|
|
219
|
+
{
|
|
220
|
+
...eventInfo,
|
|
221
|
+
namespace: event.namespace,
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
// onUpdateState(event.provider, Events.ACCOUNTS, null, coreState, eventInfo);
|
|
225
|
+
break;
|
|
226
|
+
case 'namespace_connected':
|
|
227
|
+
case 'namespace_account_switched':
|
|
228
|
+
{
|
|
229
|
+
if (event.type === 'namespace_account_switched') {
|
|
230
|
+
onUpdateState(
|
|
231
|
+
event.provider,
|
|
232
|
+
Events.NAMESPACE_DISCONNECTED,
|
|
233
|
+
event.namespace,
|
|
234
|
+
coreState,
|
|
235
|
+
eventInfo
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const formattedAddresses = event.accounts.map((accounts) =>
|
|
240
|
+
fromAccountIdToLegacyAddressFormat(
|
|
241
|
+
accounts,
|
|
242
|
+
metadata.allBlockChains || []
|
|
243
|
+
)
|
|
244
|
+
);
|
|
245
|
+
onUpdateState(
|
|
246
|
+
event.provider,
|
|
247
|
+
Events.ACCOUNTS,
|
|
248
|
+
formattedAddresses,
|
|
249
|
+
coreState,
|
|
250
|
+
{
|
|
251
|
+
...eventInfo,
|
|
252
|
+
namespace: event.namespace,
|
|
253
|
+
}
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
break;
|
|
257
|
+
case 'namespace_network_switched':
|
|
258
|
+
onUpdateState(event.provider, Events.NETWORK, event.network, coreState, {
|
|
259
|
+
...eventInfo,
|
|
260
|
+
namespace: event.namespace,
|
|
261
|
+
});
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function getAllLegacyProviders(
|
|
267
|
+
allProviders: VersionedProviders[]
|
|
268
|
+
): LegacyProviderInterface[] {
|
|
269
|
+
const LEGACY_VERSION = '0.0.0';
|
|
270
|
+
|
|
271
|
+
const legacyProviders: LegacyProviderInterface[] = [];
|
|
272
|
+
|
|
273
|
+
allProviders.forEach((provider) => {
|
|
274
|
+
const target = pickVersion(provider, LEGACY_VERSION);
|
|
275
|
+
legacyProviders.push(target[1]);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
return legacyProviders;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* In legacy mode, for those who have switch network functionality (like evm), we are using an enum for network names
|
|
283
|
+
* this enum only has meaning for us, and when we are going to connect an instance (e.g. window.ethereum) we should pass chain id.
|
|
284
|
+
*/
|
|
285
|
+
export function convertNamespaceNetworkToEvmChainId(
|
|
286
|
+
namespace: LegacyNamespaceInputForConnect,
|
|
287
|
+
meta: BlockchainMeta[]
|
|
288
|
+
) {
|
|
289
|
+
if (!namespace.network) {
|
|
290
|
+
return undefined;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const evmBlockchainsList = meta.filter(isEvmBlockchain);
|
|
294
|
+
const evmChains = convertEvmBlockchainMetaToEvmChainInfo(evmBlockchainsList);
|
|
295
|
+
|
|
296
|
+
return evmChains[namespace.network];
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* We are passing an string for chain id (e.g. ETH, POLYGON), but wallet's instances (e.g. window.ethereum) needs chainId (e.g. 0x1).
|
|
301
|
+
* This function will help us to map these strings to proper hex ids.
|
|
302
|
+
*
|
|
303
|
+
* If you need same functionality for other blockchain types (e.g. Cosmos), You can make a separate function and add it here.
|
|
304
|
+
*/
|
|
305
|
+
export function tryConvertNamespaceNetworkToChainInfo(
|
|
306
|
+
namespace: LegacyNamespaceInputForConnect,
|
|
307
|
+
meta: BlockchainMeta[]
|
|
308
|
+
): string | AddEthereumChainParameter | undefined {
|
|
309
|
+
// `undefined` means it's not evm or we couldn't find it in meta.
|
|
310
|
+
const evmChain = convertNamespaceNetworkToEvmChainId(namespace, meta);
|
|
311
|
+
const network = evmChain || namespace.network;
|
|
312
|
+
|
|
313
|
+
return network;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export function transformHubResultToLegacyResult(
|
|
317
|
+
res: Awaited<ReturnType<AllProxiedNamespaces['connect']>>
|
|
318
|
+
): ConnectResult {
|
|
319
|
+
if (isConnectResultEvm(res)) {
|
|
320
|
+
return {
|
|
321
|
+
accounts: res.accounts,
|
|
322
|
+
network: res.network,
|
|
323
|
+
provider: undefined,
|
|
324
|
+
};
|
|
325
|
+
} else if (isConnectResultSolana(res)) {
|
|
326
|
+
return {
|
|
327
|
+
accounts: res,
|
|
328
|
+
network: null,
|
|
329
|
+
provider: undefined,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
accounts: [res],
|
|
335
|
+
network: null,
|
|
336
|
+
provider: undefined,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Synchronizes providers in the hub with the configuration providers.
|
|
342
|
+
* - Registers and initializes any configuration providers not yet in the hub
|
|
343
|
+
* - Removes providers from the hub that aren't in the configuration
|
|
344
|
+
*/
|
|
345
|
+
export function synchronizeHubWithConfigProviders(
|
|
346
|
+
hub: Hub,
|
|
347
|
+
configurationProviders: Provider[]
|
|
348
|
+
) {
|
|
349
|
+
const registeredProviders = hub.getAll();
|
|
350
|
+
|
|
351
|
+
// Register and initialize providers that exist in config but not in hub
|
|
352
|
+
const providersToRegister = configurationProviders.filter(
|
|
353
|
+
(configProvider) => !registeredProviders.get(configProvider.id)
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
providersToRegister.forEach((providerToRegister) => {
|
|
357
|
+
hub.add(providerToRegister.id, providerToRegister);
|
|
358
|
+
providerToRegister.init();
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// Remove providers that exist in hub but not in config
|
|
362
|
+
registeredProviders.forEach((registeredProvider) => {
|
|
363
|
+
const isProviderInConfig = configurationProviders.some(
|
|
364
|
+
(configProvider) => configProvider.id === registeredProvider.id
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
if (!isProviderInConfig) {
|
|
368
|
+
hub.remove(registeredProvider.id);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export function isSolanaNamespace(
|
|
374
|
+
ns: ProxiedNamespace<
|
|
375
|
+
EvmActions | SolanaActions | CosmosActions | SuiActions | UtxoActions
|
|
376
|
+
>
|
|
377
|
+
): ns is ProxiedNamespace<SolanaActions> & { namespaceId: 'Solana' } {
|
|
378
|
+
return ns.namespaceId === 'Solana';
|
|
379
|
+
}
|
|
380
|
+
export function isEvmNamespace(
|
|
381
|
+
ns: ProxiedNamespace<
|
|
382
|
+
EvmActions | SolanaActions | CosmosActions | SuiActions | UtxoActions
|
|
383
|
+
>
|
|
384
|
+
): ns is ProxiedNamespace<EvmActions> & { namespaceId: 'EVM' } {
|
|
385
|
+
return ns.namespaceId === 'EVM';
|
|
386
|
+
}
|
|
387
|
+
export function isCosmosNamespace(
|
|
388
|
+
ns: ProxiedNamespace<
|
|
389
|
+
EvmActions | SolanaActions | CosmosActions | SuiActions | UtxoActions
|
|
390
|
+
>
|
|
391
|
+
): ns is ProxiedNamespace<CosmosActions> & { namespaceId: 'Cosmos' } {
|
|
392
|
+
return ns.namespaceId === 'Cosmos';
|
|
393
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { WalletActions, WalletProviders } from './types.js';
|
|
2
|
+
import type { LegacyWallet as Wallet } from '@rango-dev/wallets-core/legacy';
|
|
3
|
+
import type { WalletConfig, WalletType } from '@rango-dev/wallets-shared';
|
|
4
|
+
|
|
5
|
+
import { LastConnectedWalletsFromStorage } from '../hub/lastConnectedWallets.js';
|
|
6
|
+
|
|
7
|
+
import { LEGACY_LAST_CONNECTED_WALLETS } from './mod.js';
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
*If a wallet has multiple providers and one of them can be eagerly connected,
|
|
11
|
+
*then the whole wallet will support it at that point and we try to connect to that wallet as usual in eagerConnect method.
|
|
12
|
+
*/
|
|
13
|
+
export async function autoConnect(
|
|
14
|
+
wallets: WalletProviders,
|
|
15
|
+
getWalletInstance: (wallet: {
|
|
16
|
+
actions: WalletActions;
|
|
17
|
+
config: WalletConfig;
|
|
18
|
+
}) => Wallet<any>
|
|
19
|
+
) {
|
|
20
|
+
const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(
|
|
21
|
+
LEGACY_LAST_CONNECTED_WALLETS
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const lastConnectedWallets = lastConnectedWalletsFromStorage.list();
|
|
25
|
+
const walletIds = Object.keys(lastConnectedWallets);
|
|
26
|
+
|
|
27
|
+
if (walletIds.length) {
|
|
28
|
+
const eagerConnectQueue: {
|
|
29
|
+
walletType: WalletType;
|
|
30
|
+
eagerConnect: () => Promise<any>;
|
|
31
|
+
}[] = [];
|
|
32
|
+
|
|
33
|
+
walletIds.forEach((walletType) => {
|
|
34
|
+
const wallet = wallets.get(walletType);
|
|
35
|
+
|
|
36
|
+
if (!!wallet) {
|
|
37
|
+
const walletInstance = getWalletInstance(wallet);
|
|
38
|
+
eagerConnectQueue.push({
|
|
39
|
+
walletType,
|
|
40
|
+
eagerConnect: walletInstance.eagerConnect.bind(walletInstance),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const result = await Promise.allSettled(
|
|
46
|
+
eagerConnectQueue.map(async ({ eagerConnect }) => eagerConnect())
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const walletsToRemoveFromPersistance: WalletType[] = [];
|
|
50
|
+
result.forEach((settleResult, index) => {
|
|
51
|
+
const { status } = settleResult;
|
|
52
|
+
|
|
53
|
+
if (status === 'rejected') {
|
|
54
|
+
walletsToRemoveFromPersistance.push(
|
|
55
|
+
eagerConnectQueue[index].walletType
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (walletsToRemoveFromPersistance.length) {
|
|
61
|
+
lastConnectedWalletsFromStorage.removeWallets(
|
|
62
|
+
walletsToRemoveFromPersistance
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ProviderContext } from './types.js';
|
|
2
|
+
|
|
3
|
+
import { createContext } from 'react';
|
|
4
|
+
|
|
5
|
+
const defaultErrorMessage = "Context hasn't been initialized yet.";
|
|
6
|
+
const defaultContext: ProviderContext = {
|
|
7
|
+
async connect() {
|
|
8
|
+
throw new Error(defaultErrorMessage);
|
|
9
|
+
},
|
|
10
|
+
async disconnect() {
|
|
11
|
+
throw new Error(defaultErrorMessage);
|
|
12
|
+
},
|
|
13
|
+
async disconnectAll() {
|
|
14
|
+
throw new Error(defaultErrorMessage);
|
|
15
|
+
},
|
|
16
|
+
async suggestAndConnect() {
|
|
17
|
+
throw new Error(defaultErrorMessage);
|
|
18
|
+
},
|
|
19
|
+
state() {
|
|
20
|
+
throw new Error(defaultErrorMessage);
|
|
21
|
+
},
|
|
22
|
+
canSwitchNetworkTo() {
|
|
23
|
+
throw new Error(defaultErrorMessage);
|
|
24
|
+
},
|
|
25
|
+
providers() {
|
|
26
|
+
throw new Error(defaultErrorMessage);
|
|
27
|
+
},
|
|
28
|
+
getWalletInfo() {
|
|
29
|
+
throw new Error(defaultErrorMessage);
|
|
30
|
+
},
|
|
31
|
+
getSigners() {
|
|
32
|
+
throw new Error(defaultErrorMessage);
|
|
33
|
+
},
|
|
34
|
+
hubProvider() {
|
|
35
|
+
throw new Error(defaultErrorMessage);
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const WalletContext = createContext<ProviderContext>(defaultContext);
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ProviderInterface,
|
|
3
|
+
State,
|
|
4
|
+
WalletActions,
|
|
5
|
+
WalletProviders,
|
|
6
|
+
} from './types.js';
|
|
7
|
+
import type {
|
|
8
|
+
LegacyOptions as Options,
|
|
9
|
+
LegacyEventHandler as WalletEventHandler,
|
|
10
|
+
LegacyState as WalletState,
|
|
11
|
+
} from '@rango-dev/wallets-core/legacy';
|
|
12
|
+
import type { WalletType } from '@rango-dev/wallets-shared';
|
|
13
|
+
|
|
14
|
+
import { Persistor } from '@rango-dev/wallets-core/legacy';
|
|
15
|
+
|
|
16
|
+
import { LEGACY_LAST_CONNECTED_WALLETS } from '../hub/constants.js';
|
|
17
|
+
import { LastConnectedWalletsFromStorage } from '../hub/lastConnectedWallets.js';
|
|
18
|
+
|
|
19
|
+
export function choose(wallets: any[], type: WalletType): any | null {
|
|
20
|
+
return wallets.find((wallet) => wallet.type === type) || null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const defaultWalletState: WalletState = {
|
|
24
|
+
connected: false,
|
|
25
|
+
connecting: false,
|
|
26
|
+
reachable: false,
|
|
27
|
+
installed: false,
|
|
28
|
+
accounts: null,
|
|
29
|
+
network: null,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export function stateReducer(state: State, action: any) {
|
|
33
|
+
if (action.type === 'new_state') {
|
|
34
|
+
// TODO fix problem and remove ts-ignore
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
36
|
+
// @ts-ignore
|
|
37
|
+
const target_wallet = state[action.wallet];
|
|
38
|
+
if (!target_wallet) {
|
|
39
|
+
return {
|
|
40
|
+
...state,
|
|
41
|
+
[action.wallet]: {
|
|
42
|
+
...defaultWalletState,
|
|
43
|
+
[action.name]: action.value,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
...state,
|
|
50
|
+
[action.wallet]: {
|
|
51
|
+
...target_wallet,
|
|
52
|
+
[action.name]: action.value,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return state;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function connectedWallets(providersState: State): WalletType[] {
|
|
61
|
+
return Object.entries(providersState)
|
|
62
|
+
.filter(([, wallet_state]) => {
|
|
63
|
+
return wallet_state?.connected;
|
|
64
|
+
})
|
|
65
|
+
.map(([type]) => {
|
|
66
|
+
return type;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function availableWallets(providersState: State): WalletType[] {
|
|
71
|
+
return Object.entries(providersState).map(([type]) => {
|
|
72
|
+
return type;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function checkWalletProviders(
|
|
77
|
+
list: ProviderInterface[]
|
|
78
|
+
): WalletProviders {
|
|
79
|
+
const wallets: WalletProviders = new Map();
|
|
80
|
+
|
|
81
|
+
list.forEach((provider) => {
|
|
82
|
+
const { config, ...actions } = provider;
|
|
83
|
+
wallets.set(config.type, {
|
|
84
|
+
actions,
|
|
85
|
+
config,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return wallets;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* eslint-disable @typescript-eslint/ban-types */
|
|
93
|
+
export function isAsync(fn: Function) {
|
|
94
|
+
return fn?.constructor?.name === 'AsyncFunction';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function needsCheckInstallation(options: Options) {
|
|
98
|
+
const { checkInstallation = true } = options.config;
|
|
99
|
+
return checkInstallation;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export async function tryPersistWallet({
|
|
103
|
+
type,
|
|
104
|
+
walletActions,
|
|
105
|
+
getState,
|
|
106
|
+
}: {
|
|
107
|
+
type: WalletType;
|
|
108
|
+
walletActions: WalletActions;
|
|
109
|
+
getState: (walletType: WalletType) => WalletState;
|
|
110
|
+
}) {
|
|
111
|
+
if (walletActions.canEagerConnect) {
|
|
112
|
+
const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(
|
|
113
|
+
LEGACY_LAST_CONNECTED_WALLETS
|
|
114
|
+
);
|
|
115
|
+
const lastConnectedWallets = lastConnectedWalletsFromStorage.list();
|
|
116
|
+
const walletAlreadyPersisted = !!lastConnectedWallets[type];
|
|
117
|
+
|
|
118
|
+
/*
|
|
119
|
+
*If on the last attempt we are unable to eagerly connect to any wallet and the user connects any wallet manualy,
|
|
120
|
+
*persistance will be outdated and will need to be removed.
|
|
121
|
+
*/
|
|
122
|
+
if (walletAlreadyPersisted && !getState(type).connected) {
|
|
123
|
+
clearPersistance();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!walletAlreadyPersisted) {
|
|
127
|
+
lastConnectedWalletsFromStorage.addWallet(type, []);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function tryRemoveWalletFromPersistance({
|
|
133
|
+
type,
|
|
134
|
+
walletActions,
|
|
135
|
+
}: {
|
|
136
|
+
type: WalletType;
|
|
137
|
+
walletActions: WalletActions;
|
|
138
|
+
}) {
|
|
139
|
+
if (walletActions.canEagerConnect) {
|
|
140
|
+
const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(
|
|
141
|
+
LEGACY_LAST_CONNECTED_WALLETS
|
|
142
|
+
);
|
|
143
|
+
lastConnectedWalletsFromStorage.removeWallets([type]);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function clearPersistance() {
|
|
148
|
+
const persistor = new Persistor<string[]>();
|
|
149
|
+
const wallets = persistor.getItem(LEGACY_LAST_CONNECTED_WALLETS);
|
|
150
|
+
if (wallets) {
|
|
151
|
+
persistor.removeItem(LEGACY_LAST_CONNECTED_WALLETS);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/*
|
|
156
|
+
*Our event handler includes an internal state updater, and a notifier
|
|
157
|
+
*for the outside listener.
|
|
158
|
+
*On creating first wallet refrence, and on chaning `props.onUpdateState`
|
|
159
|
+
*we are using this function.
|
|
160
|
+
*/
|
|
161
|
+
export function makeEventHandler(
|
|
162
|
+
dispatcher: any,
|
|
163
|
+
onUpdateState?: WalletEventHandler
|
|
164
|
+
) {
|
|
165
|
+
const handler: WalletEventHandler = (
|
|
166
|
+
type,
|
|
167
|
+
name,
|
|
168
|
+
value,
|
|
169
|
+
coreState,
|
|
170
|
+
supportedChains
|
|
171
|
+
) => {
|
|
172
|
+
const action = { type: 'new_state', wallet: type, name, value };
|
|
173
|
+
// Update state
|
|
174
|
+
dispatcher(action);
|
|
175
|
+
|
|
176
|
+
// Giving the event to the outside listener
|
|
177
|
+
if (onUpdateState) {
|
|
178
|
+
onUpdateState(type, name, value, coreState, supportedChains);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
return handler;
|
|
183
|
+
}
|