@rango-dev/wallets-react 0.27.0 → 0.27.1-next.0
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 +4 -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 +19 -0
- package/dist/hub/helpers.d.ts.map +1 -0
- package/dist/hub/lastConnectedWallets.d.ts +21 -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 +10 -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 +32 -0
- package/dist/hub/utils.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +4 -4
- package/dist/legacy/autoConnect.d.ts +8 -0
- package/dist/legacy/autoConnect.d.ts.map +1 -0
- package/dist/legacy/helpers.d.ts +2 -6
- package/dist/legacy/helpers.d.ts.map +1 -1
- package/dist/legacy/mod.d.ts +5 -0
- package/dist/legacy/mod.d.ts.map +1 -0
- package/dist/legacy/types.d.ts +13 -4
- package/dist/legacy/types.d.ts.map +1 -1
- package/dist/legacy/useAutoConnect.d.ts +5 -4
- package/dist/legacy/useAutoConnect.d.ts.map +1 -1
- package/dist/legacy/useLegacyProviders.d.ts +5 -1
- package/dist/legacy/useLegacyProviders.d.ts.map +1 -1
- package/dist/legacy/utils.d.ts +3 -0
- package/dist/legacy/utils.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 -1
- package/package.json +14 -6
- package/src/hub/autoConnect.ts +186 -0
- package/src/hub/constants.ts +2 -0
- package/src/hub/helpers.ts +67 -0
- package/src/hub/lastConnectedWallets.ts +124 -0
- package/src/hub/mod.ts +2 -0
- package/src/hub/types.ts +12 -0
- package/src/hub/useHubAdapter.ts +353 -0
- package/src/hub/useHubRefs.ts +53 -0
- package/src/hub/utils.ts +322 -0
- package/src/index.ts +1 -0
- package/src/legacy/autoConnect.ts +78 -0
- package/src/legacy/helpers.ts +17 -92
- package/src/legacy/mod.ts +13 -0
- package/src/legacy/types.ts +16 -6
- package/src/legacy/useAutoConnect.ts +8 -16
- package/src/legacy/useLegacyProviders.ts +23 -6
- package/src/legacy/utils.ts +7 -0
- package/src/provider.tsx +3 -3
- package/src/test-utils/env.ts +10 -0
- package/src/test-utils/fixtures.ts +238 -0
- package/src/useProviders.ts +120 -0
- package/dist/legacy/constants.d.ts +0 -2
- package/dist/legacy/constants.d.ts.map +0 -1
- package/src/legacy/constants.ts +0 -1
package/src/hub/utils.ts
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import type { AllProxiedNamespaces } from './types.js';
|
|
2
|
+
import type { ConnectResult, ProviderProps } from '../legacy/mod.js';
|
|
3
|
+
import type { Hub, Provider, State } from '@rango-dev/wallets-core';
|
|
4
|
+
import type {
|
|
5
|
+
LegacyNamespaceInputForConnect,
|
|
6
|
+
LegacyProviderInterface,
|
|
7
|
+
LegacyEventHandler as WalletEventHandler,
|
|
8
|
+
} from '@rango-dev/wallets-core/legacy';
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
guessProviderStateSelector,
|
|
12
|
+
namespaceStateSelector,
|
|
13
|
+
} from '@rango-dev/wallets-core';
|
|
14
|
+
import { LegacyEvents as Events } from '@rango-dev/wallets-core/legacy';
|
|
15
|
+
import {
|
|
16
|
+
generateStoreId,
|
|
17
|
+
type VersionedProviders,
|
|
18
|
+
} from '@rango-dev/wallets-core/utils';
|
|
19
|
+
import { pickVersion } from '@rango-dev/wallets-core/utils';
|
|
20
|
+
import {
|
|
21
|
+
type AddEthereumChainParameter,
|
|
22
|
+
convertEvmBlockchainMetaToEvmChainInfo,
|
|
23
|
+
} from '@rango-dev/wallets-shared';
|
|
24
|
+
import { type BlockchainMeta, isEvmBlockchain } from 'rango-types';
|
|
25
|
+
|
|
26
|
+
import {
|
|
27
|
+
fromAccountIdToLegacyAddressFormat,
|
|
28
|
+
isConnectResultEvm,
|
|
29
|
+
isConnectResultSolana,
|
|
30
|
+
} from './helpers.js';
|
|
31
|
+
|
|
32
|
+
/* Gets a list of hub and legacy providers and returns a tuple which separates them. */
|
|
33
|
+
export function separateLegacyAndHubProviders(
|
|
34
|
+
providers: VersionedProviders[],
|
|
35
|
+
options?: { isExperimentalEnabled?: boolean }
|
|
36
|
+
): [LegacyProviderInterface[], Provider[]] {
|
|
37
|
+
const LEGACY_VERSION = '0.0.0';
|
|
38
|
+
const HUB_VERSION = '1.0.0';
|
|
39
|
+
const { isExperimentalEnabled = false } = options || {};
|
|
40
|
+
|
|
41
|
+
if (isExperimentalEnabled) {
|
|
42
|
+
const legacyProviders: LegacyProviderInterface[] = [];
|
|
43
|
+
const hubProviders: Provider[] = [];
|
|
44
|
+
|
|
45
|
+
providers.forEach((provider) => {
|
|
46
|
+
try {
|
|
47
|
+
const target = pickVersion(provider, HUB_VERSION);
|
|
48
|
+
hubProviders.push(target[1]);
|
|
49
|
+
} catch {
|
|
50
|
+
const target = pickVersion(provider, LEGACY_VERSION);
|
|
51
|
+
legacyProviders.push(target[1]);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return [legacyProviders, hubProviders];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const legacyProviders = providers.map(
|
|
59
|
+
(provider) => pickVersion(provider, LEGACY_VERSION)[1]
|
|
60
|
+
);
|
|
61
|
+
return [legacyProviders, []];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function findProviderByType(
|
|
65
|
+
providers: Provider[],
|
|
66
|
+
type: string
|
|
67
|
+
): Provider | undefined {
|
|
68
|
+
return providers.find((provider) => provider.id === type);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* We will call this function on hub's `subscribe`.
|
|
73
|
+
* it will check states and will emit legacy events for backward compatibility.
|
|
74
|
+
*/
|
|
75
|
+
export function checkHubStateAndTriggerEvents(
|
|
76
|
+
hub: Hub,
|
|
77
|
+
currentState: State,
|
|
78
|
+
previousState: State,
|
|
79
|
+
onUpdateState: WalletEventHandler,
|
|
80
|
+
allProviders: VersionedProviders[],
|
|
81
|
+
allBlockChains: ProviderProps['allBlockChains']
|
|
82
|
+
): void {
|
|
83
|
+
hub.getAll().forEach((provider, providerId) => {
|
|
84
|
+
const currentProviderState = guessProviderStateSelector(
|
|
85
|
+
currentState,
|
|
86
|
+
providerId
|
|
87
|
+
);
|
|
88
|
+
const previousProviderState = guessProviderStateSelector(
|
|
89
|
+
previousState,
|
|
90
|
+
providerId
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
let accounts: string[] | null = [];
|
|
94
|
+
/*
|
|
95
|
+
* We don't rely `accounts` to make sure we will trigger proper event on this case:
|
|
96
|
+
* previous value: [0x...]
|
|
97
|
+
* current value: []
|
|
98
|
+
*/
|
|
99
|
+
let hasAccountChanged = false;
|
|
100
|
+
let hasNetworkChanged = false;
|
|
101
|
+
let hasProviderDisconnected = false;
|
|
102
|
+
// It will pick the last network from namespaces.
|
|
103
|
+
let maybeNetwork = null;
|
|
104
|
+
provider.getAll().forEach((namespace) => {
|
|
105
|
+
const storeId = generateStoreId(providerId, namespace.namespaceId);
|
|
106
|
+
const currentNamespaceState = namespaceStateSelector(
|
|
107
|
+
currentState,
|
|
108
|
+
storeId
|
|
109
|
+
);
|
|
110
|
+
const previousNamespaceState = namespaceStateSelector(
|
|
111
|
+
previousState,
|
|
112
|
+
storeId
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
if (currentNamespaceState.network !== null) {
|
|
116
|
+
maybeNetwork = currentNamespaceState.network;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Check for network
|
|
120
|
+
if (currentNamespaceState.network !== previousNamespaceState.network) {
|
|
121
|
+
hasNetworkChanged = true;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// TODO: `accounts` has been frozen, we should check and find where object.freeze() is calling.
|
|
125
|
+
|
|
126
|
+
// Check for accounts
|
|
127
|
+
if (
|
|
128
|
+
previousNamespaceState.accounts?.slice().sort().toString() !==
|
|
129
|
+
currentNamespaceState.accounts?.slice().sort().toString()
|
|
130
|
+
) {
|
|
131
|
+
if (currentNamespaceState.accounts) {
|
|
132
|
+
const formattedAddresses = currentNamespaceState.accounts.map(
|
|
133
|
+
fromAccountIdToLegacyAddressFormat
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
if (accounts) {
|
|
137
|
+
accounts = [...accounts, ...formattedAddresses];
|
|
138
|
+
} else {
|
|
139
|
+
accounts = [...formattedAddresses];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
hasAccountChanged = true;
|
|
143
|
+
} else {
|
|
144
|
+
accounts = null;
|
|
145
|
+
hasProviderDisconnected = true;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
let legacyProvider;
|
|
151
|
+
try {
|
|
152
|
+
legacyProvider = getLegacyProvider(allProviders, providerId);
|
|
153
|
+
} catch (e) {
|
|
154
|
+
console.warn(
|
|
155
|
+
'Having legacy provider is required for including some information like supported chain. ',
|
|
156
|
+
e
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const coreState = {
|
|
161
|
+
connected: currentProviderState.connected,
|
|
162
|
+
connecting: currentProviderState.connecting,
|
|
163
|
+
installed: currentProviderState.installed,
|
|
164
|
+
accounts: accounts,
|
|
165
|
+
network: maybeNetwork,
|
|
166
|
+
reachable: true,
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const eventInfo = {
|
|
170
|
+
supportedBlockchains:
|
|
171
|
+
legacyProvider?.getWalletInfo(allBlockChains || []).supportedChains ||
|
|
172
|
+
[],
|
|
173
|
+
isContractWallet: false,
|
|
174
|
+
isHub: true,
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
if (previousProviderState.installed !== currentProviderState.installed) {
|
|
178
|
+
onUpdateState(
|
|
179
|
+
providerId,
|
|
180
|
+
Events.INSTALLED,
|
|
181
|
+
currentProviderState.installed,
|
|
182
|
+
coreState,
|
|
183
|
+
eventInfo
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
if (previousProviderState.connecting !== currentProviderState.connecting) {
|
|
187
|
+
onUpdateState(
|
|
188
|
+
providerId,
|
|
189
|
+
Events.CONNECTING,
|
|
190
|
+
currentProviderState.connecting,
|
|
191
|
+
coreState,
|
|
192
|
+
eventInfo
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
if (previousProviderState.connected !== currentProviderState.connected) {
|
|
196
|
+
onUpdateState(
|
|
197
|
+
providerId,
|
|
198
|
+
Events.CONNECTED,
|
|
199
|
+
currentProviderState.connected,
|
|
200
|
+
coreState,
|
|
201
|
+
eventInfo
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
if (hasAccountChanged) {
|
|
205
|
+
onUpdateState(
|
|
206
|
+
providerId,
|
|
207
|
+
Events.ACCOUNTS,
|
|
208
|
+
accounts,
|
|
209
|
+
coreState,
|
|
210
|
+
eventInfo
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
if (hasProviderDisconnected) {
|
|
214
|
+
onUpdateState(providerId, Events.ACCOUNTS, null, coreState, eventInfo);
|
|
215
|
+
}
|
|
216
|
+
if (hasNetworkChanged) {
|
|
217
|
+
onUpdateState(
|
|
218
|
+
providerId,
|
|
219
|
+
Events.NETWORK,
|
|
220
|
+
maybeNetwork,
|
|
221
|
+
coreState,
|
|
222
|
+
eventInfo
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function getLegacyProvider(
|
|
229
|
+
allProviders: VersionedProviders[],
|
|
230
|
+
type: string
|
|
231
|
+
): LegacyProviderInterface {
|
|
232
|
+
const [legacy] = separateLegacyAndHubProviders(allProviders);
|
|
233
|
+
const provider = legacy.find((legacyProvider) => {
|
|
234
|
+
return legacyProvider.config.type === type;
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
if (!provider) {
|
|
238
|
+
console.warn(
|
|
239
|
+
`You have a provider that doesn't have legacy provider. It causes some problems since we need some legacy functionality. Provider Id: ${type}`
|
|
240
|
+
);
|
|
241
|
+
throw new Error(
|
|
242
|
+
`You need to have legacy implementation to use some methods. Provider Id: ${type}`
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return provider;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* In legacy mode, for those who have switch network functionality (like evm), we are using an enum for network names
|
|
251
|
+
* 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.
|
|
252
|
+
*/
|
|
253
|
+
export function convertNamespaceNetworkToEvmChainId(
|
|
254
|
+
namespace: LegacyNamespaceInputForConnect,
|
|
255
|
+
meta: BlockchainMeta[]
|
|
256
|
+
) {
|
|
257
|
+
if (!namespace.network) {
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const evmBlockchainsList = meta.filter(isEvmBlockchain);
|
|
262
|
+
const evmChains = convertEvmBlockchainMetaToEvmChainInfo(evmBlockchainsList);
|
|
263
|
+
|
|
264
|
+
return evmChains[namespace.network];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* 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).
|
|
269
|
+
* This function will help us to map these strings to proper hex ids.
|
|
270
|
+
*
|
|
271
|
+
* If you need same functionality for other blockchain types (e.g. Cosmos), You can make a separate function and add it here.
|
|
272
|
+
*/
|
|
273
|
+
export function tryConvertNamespaceNetworkToChainInfo(
|
|
274
|
+
namespace: LegacyNamespaceInputForConnect,
|
|
275
|
+
meta: BlockchainMeta[]
|
|
276
|
+
): string | AddEthereumChainParameter | undefined {
|
|
277
|
+
// `undefined` means it's not evm or we couldn't find it in meta.
|
|
278
|
+
const evmChain = convertNamespaceNetworkToEvmChainId(namespace, meta);
|
|
279
|
+
const network = evmChain || namespace.network;
|
|
280
|
+
|
|
281
|
+
return network;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function transformHubResultToLegacyResult(
|
|
285
|
+
res: Awaited<ReturnType<AllProxiedNamespaces['connect']>>
|
|
286
|
+
): ConnectResult {
|
|
287
|
+
if (isConnectResultEvm(res)) {
|
|
288
|
+
return {
|
|
289
|
+
accounts: res.accounts,
|
|
290
|
+
network: res.network,
|
|
291
|
+
provider: undefined,
|
|
292
|
+
};
|
|
293
|
+
} else if (isConnectResultSolana(res)) {
|
|
294
|
+
return {
|
|
295
|
+
accounts: res,
|
|
296
|
+
network: null,
|
|
297
|
+
provider: undefined,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return {
|
|
302
|
+
accounts: [res],
|
|
303
|
+
network: null,
|
|
304
|
+
provider: undefined,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export function checkProviderListsEquality(
|
|
309
|
+
providerList1: Provider[],
|
|
310
|
+
providerList2: Provider[]
|
|
311
|
+
) {
|
|
312
|
+
const providerIds1 = providerList1
|
|
313
|
+
.map((provider) => provider.id)
|
|
314
|
+
.sort()
|
|
315
|
+
.toString();
|
|
316
|
+
const providerIds2 = providerList2
|
|
317
|
+
.map((provider) => provider.id)
|
|
318
|
+
.sort()
|
|
319
|
+
.toString();
|
|
320
|
+
|
|
321
|
+
return providerIds1 === providerIds2;
|
|
322
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,78 @@
|
|
|
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 canRestoreAnyConnection = !!result.find(
|
|
50
|
+
({ status }) => status === 'fulfilled'
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
*After successfully connecting to at least one wallet,
|
|
55
|
+
*we will removing the other wallets from persistence.
|
|
56
|
+
*If we are unable to connect to any wallet,
|
|
57
|
+
*the persistence will not be removed and the eager connection will be retried with another page load.
|
|
58
|
+
*/
|
|
59
|
+
if (canRestoreAnyConnection) {
|
|
60
|
+
const walletsToRemoveFromPersistance: WalletType[] = [];
|
|
61
|
+
result.forEach((settleResult, index) => {
|
|
62
|
+
const { status } = settleResult;
|
|
63
|
+
|
|
64
|
+
if (status === 'rejected') {
|
|
65
|
+
walletsToRemoveFromPersistance.push(
|
|
66
|
+
eagerConnectQueue[index].walletType
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
if (walletsToRemoveFromPersistance.length) {
|
|
72
|
+
lastConnectedWalletsFromStorage.removeWallets(
|
|
73
|
+
walletsToRemoveFromPersistance
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
package/src/legacy/helpers.ts
CHANGED
|
@@ -6,15 +6,15 @@ import type {
|
|
|
6
6
|
} from './types.js';
|
|
7
7
|
import type {
|
|
8
8
|
LegacyOptions as Options,
|
|
9
|
-
LegacyWallet as Wallet,
|
|
10
9
|
LegacyEventHandler as WalletEventHandler,
|
|
11
10
|
LegacyState as WalletState,
|
|
12
11
|
} from '@rango-dev/wallets-core/legacy';
|
|
13
|
-
import type {
|
|
12
|
+
import type { WalletType } from '@rango-dev/wallets-shared';
|
|
14
13
|
|
|
15
14
|
import { Persistor } from '@rango-dev/wallets-core/legacy';
|
|
16
15
|
|
|
17
|
-
import {
|
|
16
|
+
import { LEGACY_LAST_CONNECTED_WALLETS } from '../hub/constants.js';
|
|
17
|
+
import { LastConnectedWalletsFromStorage } from '../hub/lastConnectedWallets.js';
|
|
18
18
|
|
|
19
19
|
export function choose(wallets: any[], type: WalletType): any | null {
|
|
20
20
|
return wallets.find((wallet) => wallet.type === type) || null;
|
|
@@ -109,26 +109,22 @@ export async function tryPersistWallet({
|
|
|
109
109
|
getState: (walletType: WalletType) => WalletState;
|
|
110
110
|
}) {
|
|
111
111
|
if (walletActions.canEagerConnect) {
|
|
112
|
-
const
|
|
113
|
-
|
|
112
|
+
const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(
|
|
113
|
+
LEGACY_LAST_CONNECTED_WALLETS
|
|
114
|
+
);
|
|
115
|
+
const lastConnectedWallets = lastConnectedWalletsFromStorage.list();
|
|
116
|
+
const walletAlreadyPersisted = !!lastConnectedWallets[type];
|
|
114
117
|
|
|
115
118
|
/*
|
|
116
119
|
*If on the last attempt we are unable to eagerly connect to any wallet and the user connects any wallet manualy,
|
|
117
120
|
*persistance will be outdated and will need to be removed.
|
|
118
121
|
*/
|
|
119
|
-
|
|
120
|
-
(walletType) => !getState(walletType).connected
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
if (shouldClearPersistance) {
|
|
122
|
+
if (walletAlreadyPersisted && !getState(type).connected) {
|
|
124
123
|
clearPersistance();
|
|
125
124
|
}
|
|
126
125
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
persistor.setItem(LAST_CONNECTED_WALLETS, wallets.concat(type));
|
|
130
|
-
} else {
|
|
131
|
-
persistor.setItem(LAST_CONNECTED_WALLETS, [type]);
|
|
126
|
+
if (!walletAlreadyPersisted) {
|
|
127
|
+
lastConnectedWalletsFromStorage.addWallet(type, []);
|
|
132
128
|
}
|
|
133
129
|
}
|
|
134
130
|
}
|
|
@@ -141,92 +137,21 @@ export function tryRemoveWalletFromPersistance({
|
|
|
141
137
|
walletActions: WalletActions;
|
|
142
138
|
}) {
|
|
143
139
|
if (walletActions.canEagerConnect) {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
LAST_CONNECTED_WALLETS,
|
|
149
|
-
wallets.filter((wallet) => wallet !== type)
|
|
150
|
-
);
|
|
151
|
-
}
|
|
140
|
+
const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(
|
|
141
|
+
LEGACY_LAST_CONNECTED_WALLETS
|
|
142
|
+
);
|
|
143
|
+
lastConnectedWalletsFromStorage.removeWallets([type]);
|
|
152
144
|
}
|
|
153
145
|
}
|
|
154
146
|
|
|
155
147
|
export function clearPersistance() {
|
|
156
148
|
const persistor = new Persistor<string[]>();
|
|
157
|
-
const wallets = persistor.getItem(
|
|
149
|
+
const wallets = persistor.getItem(LEGACY_LAST_CONNECTED_WALLETS);
|
|
158
150
|
if (wallets) {
|
|
159
|
-
persistor.removeItem(
|
|
151
|
+
persistor.removeItem(LEGACY_LAST_CONNECTED_WALLETS);
|
|
160
152
|
}
|
|
161
153
|
}
|
|
162
154
|
|
|
163
|
-
/*
|
|
164
|
-
*If a wallet has multiple providers and one of them can be eagerly connected,
|
|
165
|
-
*then the whole wallet will support it at that point and we try to connect to that wallet as usual in eagerConnect method.
|
|
166
|
-
*/
|
|
167
|
-
export async function autoConnect(
|
|
168
|
-
wallets: WalletProviders,
|
|
169
|
-
getWalletInstance: (wallet: {
|
|
170
|
-
actions: WalletActions;
|
|
171
|
-
config: WalletConfig;
|
|
172
|
-
}) => Wallet<any>
|
|
173
|
-
) {
|
|
174
|
-
const persistor = new Persistor<string[]>();
|
|
175
|
-
const lastConnectedWallets = persistor.getItem(LAST_CONNECTED_WALLETS);
|
|
176
|
-
if (lastConnectedWallets && lastConnectedWallets.length) {
|
|
177
|
-
const connect_promises: {
|
|
178
|
-
walletType: WalletType;
|
|
179
|
-
eagerConnect: () => Promise<any>;
|
|
180
|
-
}[] = [];
|
|
181
|
-
lastConnectedWallets.forEach((walletType) => {
|
|
182
|
-
const wallet = wallets.get(walletType);
|
|
183
|
-
|
|
184
|
-
if (!!wallet) {
|
|
185
|
-
const walletInstance = getWalletInstance(wallet);
|
|
186
|
-
connect_promises.push({
|
|
187
|
-
walletType,
|
|
188
|
-
eagerConnect: walletInstance.eagerConnect.bind(walletInstance),
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
const result = await Promise.allSettled(
|
|
194
|
-
connect_promises.map(async ({ eagerConnect }) => eagerConnect())
|
|
195
|
-
);
|
|
196
|
-
|
|
197
|
-
const canRestoreAnyConnection = !!result.find(
|
|
198
|
-
({ status }) => status === 'fulfilled'
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
/*
|
|
202
|
-
*After successfully connecting to at least one wallet,
|
|
203
|
-
*we will removing the other wallets from persistence.
|
|
204
|
-
*If we are unable to connect to any wallet,
|
|
205
|
-
*the persistence will not be removed and the eager connection will be retried with another page load.
|
|
206
|
-
*/
|
|
207
|
-
if (canRestoreAnyConnection) {
|
|
208
|
-
const walletsToRemoveFromPersistance: WalletType[] = [];
|
|
209
|
-
result.forEach((settleResult, index) => {
|
|
210
|
-
const { status } = settleResult;
|
|
211
|
-
|
|
212
|
-
if (status === 'rejected') {
|
|
213
|
-
walletsToRemoveFromPersistance.push(
|
|
214
|
-
connect_promises[index].walletType
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
if (walletsToRemoveFromPersistance.length) {
|
|
220
|
-
persistor.setItem(
|
|
221
|
-
LAST_CONNECTED_WALLETS,
|
|
222
|
-
lastConnectedWallets.filter(
|
|
223
|
-
(walletType) => !walletsToRemoveFromPersistance.includes(walletType)
|
|
224
|
-
)
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
155
|
/*
|
|
231
156
|
*Our event handler includes an internal state updater, and a notifier
|
|
232
157
|
*for the outside listener.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
ProviderProps,
|
|
3
|
+
ProviderContext,
|
|
4
|
+
ConnectResult,
|
|
5
|
+
ExtendedWalletInfo,
|
|
6
|
+
} from './types.js';
|
|
7
|
+
export {
|
|
8
|
+
LEGACY_LAST_CONNECTED_WALLETS,
|
|
9
|
+
HUB_LAST_CONNECTED_WALLETS,
|
|
10
|
+
} from '../hub/constants.js';
|
|
11
|
+
|
|
12
|
+
export { WalletContext } from './context.js';
|
|
13
|
+
export { useLegacyProviders } from './useLegacyProviders.js';
|
package/src/legacy/types.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { ProviderInfo, VersionedProviders } from '@rango-dev/wallets-core';
|
|
1
2
|
import type {
|
|
2
|
-
|
|
3
|
+
LegacyNamespaceInputForConnect,
|
|
4
|
+
LegacyProviderInterface,
|
|
3
5
|
LegacyNetwork as Network,
|
|
4
6
|
LegacyEventHandler as WalletEventHandler,
|
|
5
7
|
LegacyWalletInfo as WalletInfo,
|
|
@@ -21,12 +23,16 @@ export type ConnectResult = {
|
|
|
21
23
|
|
|
22
24
|
export type Providers = { [type in WalletType]?: any };
|
|
23
25
|
|
|
26
|
+
export type ExtendedWalletInfo = WalletInfo & {
|
|
27
|
+
properties?: ProviderInfo['properties'];
|
|
28
|
+
isHub?: boolean;
|
|
29
|
+
};
|
|
30
|
+
|
|
24
31
|
export type ProviderContext = {
|
|
25
32
|
connect(
|
|
26
33
|
type: WalletType,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
): Promise<ConnectResult>;
|
|
34
|
+
namespaces?: LegacyNamespaceInputForConnect[]
|
|
35
|
+
): Promise<ConnectResult[]>;
|
|
30
36
|
disconnect(type: WalletType): Promise<void>;
|
|
31
37
|
disconnectAll(): Promise<PromiseSettledResult<any>[]>;
|
|
32
38
|
state(type: WalletType): WalletState;
|
|
@@ -40,7 +46,7 @@ export type ProviderContext = {
|
|
|
40
46
|
*/
|
|
41
47
|
providers(): Providers;
|
|
42
48
|
getSigners(type: WalletType): Promise<SignerFactory>;
|
|
43
|
-
getWalletInfo(type: WalletType):
|
|
49
|
+
getWalletInfo(type: WalletType): ExtendedWalletInfo;
|
|
44
50
|
suggestAndConnect(type: WalletType, network: Network): Promise<ConnectResult>;
|
|
45
51
|
};
|
|
46
52
|
|
|
@@ -48,7 +54,11 @@ export type ProviderProps = PropsWithChildren<{
|
|
|
48
54
|
onUpdateState?: WalletEventHandler;
|
|
49
55
|
allBlockChains?: BlockchainMeta[];
|
|
50
56
|
autoConnect?: boolean;
|
|
51
|
-
providers:
|
|
57
|
+
providers: VersionedProviders[];
|
|
58
|
+
configs?: {
|
|
59
|
+
isExperimentalEnabled?: boolean;
|
|
60
|
+
wallets?: (WalletType | LegacyProviderInterface)[];
|
|
61
|
+
};
|
|
52
62
|
}>;
|
|
53
63
|
|
|
54
64
|
export enum Events {
|
|
@@ -1,31 +1,23 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ProviderProps, WalletProviders } from './types.js';
|
|
1
|
+
import type { ProviderProps } from './types.js';
|
|
3
2
|
|
|
4
3
|
import { useEffect, useRef } from 'react';
|
|
5
4
|
|
|
6
|
-
import {
|
|
5
|
+
import { shouldTryAutoConnect } from './utils.js';
|
|
7
6
|
|
|
8
7
|
export function useAutoConnect(
|
|
9
8
|
props: Pick<ProviderProps, 'allBlockChains' | 'autoConnect'> & {
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
/**
|
|
10
|
+
* A function to run autoConnect on instances
|
|
11
|
+
*/
|
|
12
|
+
autoConnectHandler: () => void;
|
|
12
13
|
}
|
|
13
14
|
) {
|
|
14
15
|
const autoConnectInitiated = useRef(false);
|
|
15
16
|
|
|
16
|
-
// Running auto connect on instances
|
|
17
17
|
useEffect(() => {
|
|
18
|
-
|
|
19
|
-
props.allBlockChains &&
|
|
20
|
-
props.allBlockChains.length &&
|
|
21
|
-
props.autoConnect &&
|
|
22
|
-
!autoConnectInitiated.current;
|
|
23
|
-
|
|
24
|
-
if (shouldTryAutoConnect) {
|
|
18
|
+
if (shouldTryAutoConnect(props) && !autoConnectInitiated.current) {
|
|
25
19
|
autoConnectInitiated.current = true;
|
|
26
|
-
|
|
27
|
-
await autoConnect(props.wallets, props.getWalletInstanceFromLegacy);
|
|
28
|
-
})();
|
|
20
|
+
props.autoConnectHandler();
|
|
29
21
|
}
|
|
30
22
|
}, [props.autoConnect, props.allBlockChains]);
|
|
31
23
|
}
|