@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.
Files changed (81) hide show
  1. package/CHANGELOG.md +265 -0
  2. package/dist/helpers/index.d.ts +2 -0
  3. package/dist/helpers/index.d.ts.map +1 -0
  4. package/dist/helpers/index.js +2 -0
  5. package/dist/helpers/index.js.map +7 -0
  6. package/dist/hub/autoConnect.d.ts +11 -0
  7. package/dist/hub/autoConnect.d.ts.map +1 -0
  8. package/dist/hub/constants.d.ts +3 -0
  9. package/dist/hub/constants.d.ts.map +1 -0
  10. package/dist/hub/helpers.d.ts +33 -0
  11. package/dist/hub/helpers.d.ts.map +1 -0
  12. package/dist/hub/lastConnectedWallets.d.ts +22 -0
  13. package/dist/hub/lastConnectedWallets.d.ts.map +1 -0
  14. package/dist/hub/mod.d.ts +3 -0
  15. package/dist/hub/mod.d.ts.map +1 -0
  16. package/dist/hub/types.d.ts +4 -0
  17. package/dist/hub/types.d.ts.map +1 -0
  18. package/dist/hub/useHubAdapter.d.ts +11 -0
  19. package/dist/hub/useHubAdapter.d.ts.map +1 -0
  20. package/dist/hub/useHubRefs.d.ts +7 -0
  21. package/dist/hub/useHubRefs.d.ts.map +1 -0
  22. package/dist/hub/utils.d.ts +52 -0
  23. package/dist/hub/utils.d.ts.map +1 -0
  24. package/dist/index.d.ts +5 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +2 -0
  27. package/dist/index.js.map +7 -0
  28. package/dist/legacy/autoConnect.d.ts +8 -0
  29. package/dist/legacy/autoConnect.d.ts.map +1 -0
  30. package/dist/legacy/context.d.ts +3 -0
  31. package/dist/legacy/context.d.ts.map +1 -0
  32. package/dist/legacy/helpers.d.ts +23 -0
  33. package/dist/legacy/helpers.d.ts.map +1 -0
  34. package/dist/legacy/hooks.d.ts +10 -0
  35. package/dist/legacy/hooks.d.ts.map +1 -0
  36. package/dist/legacy/mod.d.ts +5 -0
  37. package/dist/legacy/mod.d.ts.map +1 -0
  38. package/dist/legacy/types.d.ts +143 -0
  39. package/dist/legacy/types.d.ts.map +1 -0
  40. package/dist/legacy/useAutoConnect.d.ts +8 -0
  41. package/dist/legacy/useAutoConnect.d.ts.map +1 -0
  42. package/dist/legacy/useLegacyProviders.d.ts +7 -0
  43. package/dist/legacy/useLegacyProviders.d.ts.map +1 -0
  44. package/dist/legacy/utils.d.ts +3 -0
  45. package/dist/legacy/utils.d.ts.map +1 -0
  46. package/dist/provider.d.ts +5 -0
  47. package/dist/provider.d.ts.map +1 -0
  48. package/dist/test-utils/env.d.ts +7 -0
  49. package/dist/test-utils/env.d.ts.map +1 -0
  50. package/dist/test-utils/fixtures.d.ts +14 -0
  51. package/dist/test-utils/fixtures.d.ts.map +1 -0
  52. package/dist/useProviders.d.ts +4 -0
  53. package/dist/useProviders.d.ts.map +1 -0
  54. package/dist/wallets-react.build.json +1 -0
  55. package/helpers/package.json +8 -0
  56. package/package.json +50 -0
  57. package/readme.md +3 -0
  58. package/src/helpers/index.ts +1 -0
  59. package/src/hub/autoConnect.ts +276 -0
  60. package/src/hub/constants.ts +2 -0
  61. package/src/hub/helpers.ts +179 -0
  62. package/src/hub/lastConnectedWallets.ts +166 -0
  63. package/src/hub/mod.ts +6 -0
  64. package/src/hub/types.ts +12 -0
  65. package/src/hub/useHubAdapter.ts +516 -0
  66. package/src/hub/useHubRefs.ts +50 -0
  67. package/src/hub/utils.ts +393 -0
  68. package/src/index.ts +4 -0
  69. package/src/legacy/autoConnect.ts +66 -0
  70. package/src/legacy/context.ts +39 -0
  71. package/src/legacy/helpers.ts +183 -0
  72. package/src/legacy/hooks.ts +54 -0
  73. package/src/legacy/mod.ts +13 -0
  74. package/src/legacy/types.ts +195 -0
  75. package/src/legacy/useAutoConnect.ts +23 -0
  76. package/src/legacy/useLegacyProviders.ts +241 -0
  77. package/src/legacy/utils.ts +7 -0
  78. package/src/provider.tsx +18 -0
  79. package/src/test-utils/env.ts +10 -0
  80. package/src/test-utils/fixtures.ts +238 -0
  81. package/src/useProviders.ts +120 -0
@@ -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,4 @@
1
+ export * from './legacy/helpers.js';
2
+ export { default as Provider } from './provider.js';
3
+ export { useWallets } from './legacy/hooks.js';
4
+ export * from './legacy/types.js';
@@ -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
+ }