@rango-dev/widget-embedded 0.41.1-next.2 → 0.41.1-next.3
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/dist/index.js +2 -2
- package/dist/index.js.map +3 -3
- package/dist/store/middlewares/keepLastUpdated.d.ts.map +1 -1
- package/dist/store/slices/wallets.d.ts.map +1 -1
- package/dist/store/utils/wallets.d.ts +21 -2
- package/dist/store/utils/wallets.d.ts.map +1 -1
- package/dist/widget-embedded.build.json +1 -1
- package/package.json +1 -1
- package/src/store/middlewares/keepLastUpdated.ts +10 -3
- package/src/store/slices/wallets.ts +47 -75
- package/src/store/utils/wallets.ts +103 -11
package/package.json
CHANGED
|
@@ -7,13 +7,20 @@ export const keepLastUpdated: <Store, Slice extends { lastUpdatedAt: number }>(
|
|
|
7
7
|
config: StateCreator<Store, [], [], Slice>
|
|
8
8
|
) => StateCreator<Store, [], [], Slice> = (slice) => (set, get, api) => {
|
|
9
9
|
const modifedSet: typeof set = (...params) => {
|
|
10
|
+
const [partial, ...restParams] = params;
|
|
10
11
|
set((state) => {
|
|
12
|
+
// @see https://github.com/pmndrs/zustand/blob/90f8d592d4cde9aa15f236e320f17ccbc86cf0fb/src/vanilla.ts#L69-L72
|
|
13
|
+
type State = ReturnType<typeof get>;
|
|
14
|
+
const nextState =
|
|
15
|
+
typeof partial === 'function'
|
|
16
|
+
? (partial as (s: State) => State)(state)
|
|
17
|
+
: partial;
|
|
18
|
+
|
|
11
19
|
return {
|
|
12
|
-
...
|
|
20
|
+
...nextState,
|
|
13
21
|
lastUpdatedAt: +new Date(),
|
|
14
22
|
};
|
|
15
|
-
});
|
|
16
|
-
set(...params);
|
|
23
|
+
}, ...restParams);
|
|
17
24
|
};
|
|
18
25
|
return slice(modifedSet, get, api);
|
|
19
26
|
};
|
|
@@ -18,13 +18,12 @@ import { memoizedResult } from '../../utils/common';
|
|
|
18
18
|
import { isAccountAndWalletMatched } from '../../utils/wallets';
|
|
19
19
|
import { keepLastUpdated } from '../middlewares/keepLastUpdated';
|
|
20
20
|
import {
|
|
21
|
+
computeNextBalancesWithNewPrices,
|
|
22
|
+
computeNextStateAfterWalletBalanceRemoval,
|
|
21
23
|
createAssetKey,
|
|
22
|
-
createBalanceKey,
|
|
23
24
|
createBalanceStateForNewAccount,
|
|
24
25
|
extractAssetFromBalanceKey,
|
|
25
|
-
removeBalanceFromAggregatedBalance,
|
|
26
26
|
updateAggregatedBalanceStateForNewAccount,
|
|
27
|
-
updateBalancesWithNewPrices,
|
|
28
27
|
} from '../utils/wallets';
|
|
29
28
|
|
|
30
29
|
type WalletAddress = string;
|
|
@@ -353,16 +352,24 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
|
|
|
353
352
|
return;
|
|
354
353
|
}
|
|
355
354
|
|
|
356
|
-
const
|
|
355
|
+
const walletDetail = {
|
|
357
356
|
blockChain: balance.asset.blockchain,
|
|
358
357
|
balances: [balance],
|
|
359
358
|
address: walletAddress,
|
|
360
359
|
};
|
|
361
360
|
|
|
362
|
-
|
|
361
|
+
const partialCurrentState = {
|
|
362
|
+
_aggregatedBalances: get()._aggregatedBalances,
|
|
363
|
+
findToken: get().findToken,
|
|
364
|
+
};
|
|
365
|
+
computeNextBalancesWithNewPrices(
|
|
366
|
+
partialCurrentState,
|
|
367
|
+
walletDetail,
|
|
368
|
+
nextBalances
|
|
369
|
+
);
|
|
363
370
|
|
|
364
371
|
const balancesForWallet = createBalanceStateForNewAccount(
|
|
365
|
-
|
|
372
|
+
walletDetail,
|
|
366
373
|
get
|
|
367
374
|
);
|
|
368
375
|
|
|
@@ -435,73 +442,21 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
|
|
|
435
442
|
});
|
|
436
443
|
},
|
|
437
444
|
removeBalancesForWallet: (walletType, options) => {
|
|
438
|
-
|
|
439
|
-
(
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
if (connectedWallet.walletType !== walletType) {
|
|
449
|
-
walletsNeedsToBeRemoved = walletsNeedsToBeRemoved.filter((wallet) => {
|
|
450
|
-
const isAnotherWalletHasSameAddressAndChain =
|
|
451
|
-
wallet.chain === connectedWallet.chain &&
|
|
452
|
-
wallet.address === connectedWallet.address;
|
|
453
|
-
return !isAnotherWalletHasSameAddressAndChain;
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
if (!!options?.chains && options.chains.length > 0) {
|
|
459
|
-
walletsNeedsToBeRemoved = walletsNeedsToBeRemoved.filter((wallet) => {
|
|
460
|
-
return options.chains?.includes(wallet.chain);
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
if (!!options?.namespaces && options.namespaces.length > 0) {
|
|
465
|
-
walletsNeedsToBeRemoved = walletsNeedsToBeRemoved.filter((wallet) => {
|
|
466
|
-
if (wallet.namespace) {
|
|
467
|
-
return options.namespaces?.includes(wallet.namespace);
|
|
468
|
-
}
|
|
469
|
-
return false;
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
const nextBalancesState: BalanceState = {};
|
|
474
|
-
let nextAggregatedBalanceState: AggregatedBalanceState =
|
|
475
|
-
get()._aggregatedBalances;
|
|
476
|
-
const currentBalancesState = get()._balances;
|
|
477
|
-
const balanceKeys = Object.keys(currentBalancesState) as BalanceKey[];
|
|
478
|
-
|
|
479
|
-
balanceKeys.forEach((key) => {
|
|
480
|
-
const asset = extractAssetFromBalanceKey(key);
|
|
481
|
-
|
|
482
|
-
const shouldBalanceBeRemoved = !!walletsNeedsToBeRemoved.find(
|
|
483
|
-
(wallet) =>
|
|
484
|
-
createBalanceKey(wallet.address, {
|
|
485
|
-
address: asset.address,
|
|
486
|
-
blockchain: wallet.chain,
|
|
487
|
-
symbol: asset.symbol,
|
|
488
|
-
}) === key
|
|
445
|
+
const partialCurrentState = {
|
|
446
|
+
_balances: get()._balances,
|
|
447
|
+
_aggregatedBalances: get()._aggregatedBalances,
|
|
448
|
+
connectedWallets: get().connectedWallets,
|
|
449
|
+
};
|
|
450
|
+
const { _balances, _aggregatedBalances } =
|
|
451
|
+
computeNextStateAfterWalletBalanceRemoval(
|
|
452
|
+
partialCurrentState,
|
|
453
|
+
walletType,
|
|
454
|
+
options
|
|
489
455
|
);
|
|
490
456
|
|
|
491
|
-
// if a balance should be removed, we need to remove its caches in _aggregatedBalances as wel.
|
|
492
|
-
if (shouldBalanceBeRemoved) {
|
|
493
|
-
nextAggregatedBalanceState = removeBalanceFromAggregatedBalance(
|
|
494
|
-
nextAggregatedBalanceState,
|
|
495
|
-
key
|
|
496
|
-
);
|
|
497
|
-
} else {
|
|
498
|
-
nextBalancesState[key] = currentBalancesState[key];
|
|
499
|
-
}
|
|
500
|
-
});
|
|
501
|
-
|
|
502
457
|
set({
|
|
503
|
-
_balances
|
|
504
|
-
_aggregatedBalances
|
|
458
|
+
_balances,
|
|
459
|
+
_aggregatedBalances,
|
|
505
460
|
});
|
|
506
461
|
},
|
|
507
462
|
disconnectNamespaces: (walletType, requestedNamesapces) => {
|
|
@@ -644,7 +599,6 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
|
|
|
644
599
|
console.error(`Request for fetching balances failed. cause: ${e}`);
|
|
645
600
|
return;
|
|
646
601
|
}
|
|
647
|
-
|
|
648
602
|
const walletsDetails = response.wallets;
|
|
649
603
|
|
|
650
604
|
if (walletsDetails) {
|
|
@@ -672,12 +626,30 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
|
|
|
672
626
|
return;
|
|
673
627
|
}
|
|
674
628
|
|
|
675
|
-
|
|
629
|
+
const partialCurrentState = {
|
|
630
|
+
_balances: nextBalances,
|
|
631
|
+
_aggregatedBalances: nextAggregatedBalances,
|
|
632
|
+
connectedWallets: get().connectedWallets,
|
|
633
|
+
findToken: get().findToken,
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
computeNextBalancesWithNewPrices(
|
|
637
|
+
partialCurrentState,
|
|
638
|
+
wallet,
|
|
639
|
+
nextBalances
|
|
640
|
+
);
|
|
676
641
|
|
|
677
642
|
// Remove old balances for current wallet and blockchain
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
643
|
+
const { _balances, _aggregatedBalances } =
|
|
644
|
+
computeNextStateAfterWalletBalanceRemoval(
|
|
645
|
+
partialCurrentState,
|
|
646
|
+
walletType,
|
|
647
|
+
{
|
|
648
|
+
chains: [wallet.blockChain],
|
|
649
|
+
}
|
|
650
|
+
);
|
|
651
|
+
nextAggregatedBalances = _aggregatedBalances;
|
|
652
|
+
nextBalances = _balances;
|
|
681
653
|
|
|
682
654
|
/*
|
|
683
655
|
* Check if after fetching balance for an account, the account still exists.
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import type { Balance } from '../../types';
|
|
2
2
|
import type { AppStoreState } from '../app';
|
|
3
|
+
import type { FindToken } from '../slices/data';
|
|
4
|
+
import type {
|
|
5
|
+
AggregatedBalanceState,
|
|
6
|
+
AssetKey,
|
|
7
|
+
BalanceKey,
|
|
8
|
+
BalanceState,
|
|
9
|
+
ConnectedWallet,
|
|
10
|
+
} from '../slices/wallets';
|
|
11
|
+
import type { Namespace } from '@rango-dev/wallets-core/namespaces/common';
|
|
3
12
|
import type { Asset, WalletDetail } from 'rango-types';
|
|
4
13
|
|
|
5
14
|
import BigNumber from 'bignumber.js';
|
|
6
15
|
|
|
7
16
|
import { ZERO } from '../../constants/numbers';
|
|
8
17
|
import { BALANCE_SEPARATOR } from '../../constants/wallets';
|
|
9
|
-
import {
|
|
10
|
-
type AggregatedBalanceState,
|
|
11
|
-
type AssetKey,
|
|
12
|
-
type BalanceKey,
|
|
13
|
-
type BalanceState,
|
|
14
|
-
} from '../slices/wallets';
|
|
15
18
|
|
|
16
19
|
/**
|
|
17
20
|
* Note: We need to use `symbol` as well since native coins and cosmos blockchains don't have `address`
|
|
@@ -44,16 +47,19 @@ export function extractAssetFromBalanceKey(key: BalanceKey): Asset {
|
|
|
44
47
|
};
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
export function
|
|
50
|
+
export function computeNextBalancesWithNewPrices(
|
|
51
|
+
paritalCurrentState: {
|
|
52
|
+
findToken: FindToken;
|
|
53
|
+
_aggregatedBalances: AggregatedBalanceState;
|
|
54
|
+
},
|
|
48
55
|
wallet: Omit<WalletDetail, 'failed' | 'explorerUrl'>,
|
|
49
|
-
balanceState: BalanceState
|
|
50
|
-
store: () => AppStoreState
|
|
56
|
+
balanceState: BalanceState
|
|
51
57
|
): BalanceState {
|
|
52
58
|
wallet.balances?.forEach((balance) => {
|
|
53
59
|
const usdPrice =
|
|
54
|
-
balance.price ??
|
|
60
|
+
balance.price ?? paritalCurrentState.findToken(balance.asset)?.usdPrice;
|
|
55
61
|
const balancesToUpdate =
|
|
56
|
-
|
|
62
|
+
paritalCurrentState._aggregatedBalances[createAssetKey(balance.asset)];
|
|
57
63
|
|
|
58
64
|
balancesToUpdate?.forEach((balanceKey) => {
|
|
59
65
|
if (balanceState[balanceKey]) {
|
|
@@ -139,3 +145,89 @@ export function removeBalanceFromAggregatedBalance(
|
|
|
139
145
|
|
|
140
146
|
return aggregatedBalances;
|
|
141
147
|
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* We made a util to remvoe balances to be able batch with other state updates.
|
|
151
|
+
*/
|
|
152
|
+
export function computeNextStateAfterWalletBalanceRemoval(
|
|
153
|
+
paritalCurrentState: {
|
|
154
|
+
_balances: BalanceState;
|
|
155
|
+
_aggregatedBalances: AggregatedBalanceState;
|
|
156
|
+
connectedWallets: ConnectedWallet[];
|
|
157
|
+
},
|
|
158
|
+
walletType: string,
|
|
159
|
+
options?: {
|
|
160
|
+
chains?: string[];
|
|
161
|
+
namespaces?: Namespace[];
|
|
162
|
+
}
|
|
163
|
+
) {
|
|
164
|
+
let walletsNeedsToBeRemoved = paritalCurrentState.connectedWallets.filter(
|
|
165
|
+
(connectedWallet) => connectedWallet.walletType === walletType
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
/*
|
|
169
|
+
* We only need to delete balances where there is no connected wallets with same chain and address for that balance.
|
|
170
|
+
* Consider both Metamask and Solana having support for `0xblahblahblahblah` for Ethereum.
|
|
171
|
+
* If Phantom is disconnecting, we should keep the balance since Metamask has access to same address yet.
|
|
172
|
+
* So we only delete balance when there is no connected wallet that has access to that specific chain and address.
|
|
173
|
+
*/
|
|
174
|
+
paritalCurrentState.connectedWallets.forEach((connectedWallet) => {
|
|
175
|
+
if (connectedWallet.walletType !== walletType) {
|
|
176
|
+
walletsNeedsToBeRemoved = walletsNeedsToBeRemoved.filter((wallet) => {
|
|
177
|
+
const isAnotherWalletHasSameAddressAndChain =
|
|
178
|
+
wallet.chain === connectedWallet.chain &&
|
|
179
|
+
wallet.address === connectedWallet.address;
|
|
180
|
+
return !isAnotherWalletHasSameAddressAndChain;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
if (!!options?.chains && options.chains.length > 0) {
|
|
186
|
+
walletsNeedsToBeRemoved = walletsNeedsToBeRemoved.filter((wallet) => {
|
|
187
|
+
return options.chains?.includes(wallet.chain);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (!!options?.namespaces && options.namespaces.length > 0) {
|
|
192
|
+
walletsNeedsToBeRemoved = walletsNeedsToBeRemoved.filter((wallet) => {
|
|
193
|
+
if (wallet.namespace) {
|
|
194
|
+
return options.namespaces?.includes(wallet.namespace);
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const nextBalancesState: BalanceState = {};
|
|
201
|
+
let nextAggregatedBalanceState: AggregatedBalanceState =
|
|
202
|
+
paritalCurrentState._aggregatedBalances;
|
|
203
|
+
const currentBalancesState = paritalCurrentState._balances;
|
|
204
|
+
const balanceKeys = Object.keys(currentBalancesState) as BalanceKey[];
|
|
205
|
+
|
|
206
|
+
balanceKeys.forEach((key) => {
|
|
207
|
+
const asset = extractAssetFromBalanceKey(key);
|
|
208
|
+
|
|
209
|
+
const shouldBalanceBeRemoved = !!walletsNeedsToBeRemoved.find(
|
|
210
|
+
(wallet) =>
|
|
211
|
+
createBalanceKey(wallet.address, {
|
|
212
|
+
address: asset.address,
|
|
213
|
+
blockchain: wallet.chain,
|
|
214
|
+
symbol: asset.symbol,
|
|
215
|
+
}) === key
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
// if a balance should be removed, we need to remove its caches in _aggregatedBalances as wel.
|
|
219
|
+
if (shouldBalanceBeRemoved) {
|
|
220
|
+
nextAggregatedBalanceState = removeBalanceFromAggregatedBalance(
|
|
221
|
+
nextAggregatedBalanceState,
|
|
222
|
+
key
|
|
223
|
+
);
|
|
224
|
+
} else {
|
|
225
|
+
nextBalancesState[key] = currentBalancesState[key];
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
_balances: nextBalancesState,
|
|
231
|
+
_aggregatedBalances: nextAggregatedBalanceState,
|
|
232
|
+
};
|
|
233
|
+
}
|