@talismn/balances-react 0.0.0-pr642-20230322025617 → 0.0.0-pr644-20230322035559
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 +10 -7
- package/dist/declarations/src/hooks/index.d.ts +1 -0
- package/dist/declarations/src/hooks/useBalancesStatus.d.ts +19 -0
- package/dist/talismn-balances-react.cjs.dev.js +83 -28
- package/dist/talismn-balances-react.cjs.prod.js +83 -28
- package/dist/talismn-balances-react.esm.js +79 -26
- package/package.json +8 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @talismn/balances-react
|
|
2
2
|
|
|
3
|
-
## 0.0.0-
|
|
3
|
+
## 0.0.0-pr644-20230322035559
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
@@ -8,18 +8,21 @@
|
|
|
8
8
|
|
|
9
9
|
### Patch Changes
|
|
10
10
|
|
|
11
|
+
- 3068bd6: feat: stale balances and exponential rpc backoff
|
|
11
12
|
- 6643a4e: fix: tokenRates in @talismn/balances-react
|
|
12
13
|
- 6643a4e: fix: ported useDbCache related perf fixes to @talismn/balances-react
|
|
14
|
+
- Updated dependencies [3068bd6]
|
|
13
15
|
- Updated dependencies [6643a4e]
|
|
14
16
|
- Updated dependencies [79f6ccf]
|
|
15
17
|
- Updated dependencies [6643a4e]
|
|
16
18
|
- Updated dependencies [c24dc1f]
|
|
17
|
-
- @talismn/
|
|
18
|
-
- @talismn/
|
|
19
|
-
- @talismn/
|
|
20
|
-
- @talismn/
|
|
21
|
-
- @talismn/
|
|
22
|
-
- @talismn/
|
|
19
|
+
- @talismn/chain-connector@0.0.0-pr644-20230322035559
|
|
20
|
+
- @talismn/connection-meta@0.0.0-pr644-20230322035559
|
|
21
|
+
- @talismn/balances@0.0.0-pr644-20230322035559
|
|
22
|
+
- @talismn/token-rates@0.0.0-pr644-20230322035559
|
|
23
|
+
- @talismn/chaindata-provider-extension@0.0.0-pr644-20230322035559
|
|
24
|
+
- @talismn/chaindata-provider@0.0.0-pr644-20230322035559
|
|
25
|
+
- @talismn/chain-connector-evm@0.0.0-pr644-20230322035559
|
|
23
26
|
|
|
24
27
|
## 0.3.3
|
|
25
28
|
|
|
@@ -2,6 +2,7 @@ export * from "./useAllAddresses";
|
|
|
2
2
|
export * from "./useBalanceModules";
|
|
3
3
|
export * from "./useBalances";
|
|
4
4
|
export * from "./useBalancesHydrate";
|
|
5
|
+
export * from "./useBalancesStatus";
|
|
5
6
|
export * from "./useChainConnectors";
|
|
6
7
|
export * from "./useChaindata";
|
|
7
8
|
export * from "./useChains";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Balances } from "@talismn/balances";
|
|
2
|
+
export type BalancesStatus = {
|
|
3
|
+
status: "live";
|
|
4
|
+
} | {
|
|
5
|
+
status: "fetching";
|
|
6
|
+
} | {
|
|
7
|
+
status: "stale";
|
|
8
|
+
staleChains: string[];
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Given a collection of `Balances`, this hook returns a `BalancesStatus` summary for the collection.
|
|
12
|
+
*
|
|
13
|
+
* @param balances The collection of balances to get the status from.
|
|
14
|
+
* @param isLoadingLocks Because the wallet currently fetches locks outside of the balances api, this param can be used to indicate that the locks are still loading, even if the `Balances` collection is not.
|
|
15
|
+
* @returns An instance of `BalancesStatus` which represents the status of the balances collection.
|
|
16
|
+
|
|
17
|
+
*/
|
|
18
|
+
export declare const useBalancesStatus: (balances: Balances, isLoadingLocks?: boolean) => BalancesStatus;
|
|
19
|
+
export declare const getStaleChains: (balances: Balances) => string[];
|
|
@@ -6,6 +6,7 @@ var react = require('react');
|
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
7
|
var chainConnector = require('@talismn/chain-connector');
|
|
8
8
|
var chainConnectorEvm = require('@talismn/chain-connector-evm');
|
|
9
|
+
var connectionMeta = require('@talismn/connection-meta');
|
|
9
10
|
var chaindataProviderExtension = require('@talismn/chaindata-provider-extension');
|
|
10
11
|
var balances = require('@talismn/balances');
|
|
11
12
|
var tokenRates = require('@talismn/token-rates');
|
|
@@ -73,7 +74,7 @@ function useChainConnectorsProvider(options) {
|
|
|
73
74
|
const chaindata = useChaindata();
|
|
74
75
|
|
|
75
76
|
// substrate connector
|
|
76
|
-
const substrate = react.useMemo(() => new chainConnector.ChainConnector(chaindata), [chaindata]);
|
|
77
|
+
const substrate = react.useMemo(() => new chainConnector.ChainConnector(chaindata, connectionMeta.connectionMetaDb), [chaindata]);
|
|
77
78
|
|
|
78
79
|
// evm connector
|
|
79
80
|
const evm = react.useMemo(() => new chainConnectorEvm.ChainConnectorEvm(chaindata, {
|
|
@@ -199,7 +200,7 @@ const [DbCacheProvider, useDbCache] = provideContext(useDbCacheProvider);
|
|
|
199
200
|
|
|
200
201
|
var packageJson = {
|
|
201
202
|
name: "@talismn/balances-react",
|
|
202
|
-
version: "0.0.0-
|
|
203
|
+
version: "0.0.0-pr644-20230322035559",
|
|
203
204
|
author: "Talisman",
|
|
204
205
|
homepage: "https://talisman.xyz",
|
|
205
206
|
license: "UNLICENSED",
|
|
@@ -230,6 +231,7 @@ var packageJson = {
|
|
|
230
231
|
"@talismn/chain-connector-evm": "workspace:^",
|
|
231
232
|
"@talismn/chaindata-provider": "workspace:^",
|
|
232
233
|
"@talismn/chaindata-provider-extension": "workspace:^",
|
|
234
|
+
"@talismn/connection-meta": "workspace:^",
|
|
233
235
|
"@talismn/token-rates": "workspace:^",
|
|
234
236
|
anylogger: "^1.0.11",
|
|
235
237
|
"blueimp-md5": "2.19.0",
|
|
@@ -313,20 +315,6 @@ const useSharedSubscription = (key, subscribe) => {
|
|
|
313
315
|
}, [key, subscribe]);
|
|
314
316
|
};
|
|
315
317
|
|
|
316
|
-
function useTokens(withTestnets) {
|
|
317
|
-
// keep db data up to date
|
|
318
|
-
useDbCacheSubscription("tokens");
|
|
319
|
-
const {
|
|
320
|
-
tokensWithTestnetsMap,
|
|
321
|
-
tokensWithoutTestnetsMap
|
|
322
|
-
} = useDbCache();
|
|
323
|
-
return withTestnets ? tokensWithTestnetsMap : tokensWithoutTestnetsMap;
|
|
324
|
-
}
|
|
325
|
-
function useToken(tokenId, withTestnets) {
|
|
326
|
-
const tokens = useTokens(withTestnets);
|
|
327
|
-
return tokenId ? tokens[tokenId] : undefined;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
318
|
/**
|
|
331
319
|
* Creates a subscription function that can be used to subscribe to a multicast observable created from an upstream source.
|
|
332
320
|
*
|
|
@@ -404,7 +392,7 @@ function useDbCacheTokenRatesSubscription() {
|
|
|
404
392
|
const {
|
|
405
393
|
withTestnets
|
|
406
394
|
} = useWithTestnets();
|
|
407
|
-
const tokens = useTokens(withTestnets);
|
|
395
|
+
const tokens = useTokens$1(withTestnets);
|
|
408
396
|
const subscriptionKey = react.useMemo(
|
|
409
397
|
// not super sexy but we need key to change based on this stuff
|
|
410
398
|
() => {
|
|
@@ -431,7 +419,7 @@ function useDbCacheBalancesSubscription() {
|
|
|
431
419
|
const chaindataProvider = useChaindata();
|
|
432
420
|
const chainConnectors = useChainConnectors();
|
|
433
421
|
const [allAddresses] = useAllAddresses();
|
|
434
|
-
const tokens = useTokens(withTestnets);
|
|
422
|
+
const tokens = useTokens$1(withTestnets);
|
|
435
423
|
const subscriptionKey = react.useMemo(
|
|
436
424
|
// not super sexy but we need key to change based on this stuff
|
|
437
425
|
() => {
|
|
@@ -442,10 +430,19 @@ function useDbCacheBalancesSubscription() {
|
|
|
442
430
|
}, [allAddresses, balanceModules, chainConnectors, chaindataProvider, tokens]);
|
|
443
431
|
const subscription = react.useCallback(() => {
|
|
444
432
|
if (!Object.values(tokens ?? {}).length || !allAddresses.length) return () => {};
|
|
445
|
-
return subscribeBalances(tokens ?? {}, allAddresses,
|
|
446
|
-
}, [allAddresses, balanceModules,
|
|
433
|
+
return subscribeBalances(tokens ?? {}, allAddresses, balanceModules);
|
|
434
|
+
}, [allAddresses, balanceModules, tokens]);
|
|
447
435
|
useSharedSubscription(subscriptionKey, subscription);
|
|
448
436
|
}
|
|
437
|
+
|
|
438
|
+
// subscriptionless version of useTokens, prevents circular dependency
|
|
439
|
+
const useTokens$1 = withTestnets => {
|
|
440
|
+
const {
|
|
441
|
+
tokensWithTestnetsMap,
|
|
442
|
+
tokensWithoutTestnetsMap
|
|
443
|
+
} = useDbCache();
|
|
444
|
+
return withTestnets ? tokensWithTestnetsMap : tokensWithoutTestnetsMap;
|
|
445
|
+
};
|
|
449
446
|
const subscribeChainDataHydrate = (provider, type) => {
|
|
450
447
|
const chaindata = provider;
|
|
451
448
|
const delay = 300_000; // 300_000ms = 300s = 5 minutes
|
|
@@ -501,7 +498,7 @@ const subscribeTokenRates = tokens => {
|
|
|
501
498
|
if (timeout) clearTimeout(timeout);
|
|
502
499
|
};
|
|
503
500
|
};
|
|
504
|
-
const subscribeBalances = (tokens, addresses,
|
|
501
|
+
const subscribeBalances = (tokens, addresses, balanceModules) => {
|
|
505
502
|
const tokenIds = Object.values(tokens).map(({
|
|
506
503
|
id
|
|
507
504
|
}) => id);
|
|
@@ -525,28 +522,41 @@ const subscribeBalances = (tokens, addresses, chainConnectors, provider, balance
|
|
|
525
522
|
id
|
|
526
523
|
}) => id);
|
|
527
524
|
const addressesByModuleToken = Object.fromEntries(Object.entries(addressesByToken).filter(([tokenId]) => moduleTokenIds.includes(tokenId)));
|
|
528
|
-
const unsub = balances.balances(balanceModule, addressesByModuleToken, (error, balances) => {
|
|
525
|
+
const unsub = balances.balances(balanceModule, addressesByModuleToken, (error, balances$1) => {
|
|
529
526
|
// log errors
|
|
530
|
-
if (error)
|
|
527
|
+
if (error) {
|
|
528
|
+
if (error?.type === "STALE_RPC_ERROR") return balances.db.balances.where({
|
|
529
|
+
source: balanceModule.type,
|
|
530
|
+
chainId: error.chainId
|
|
531
|
+
}).filter(balance => {
|
|
532
|
+
if (!Object.keys(addressesByModuleToken).includes(balance.tokenId)) return false;
|
|
533
|
+
if (!addressesByModuleToken[balance.tokenId].includes(balance.address)) return false;
|
|
534
|
+
return true;
|
|
535
|
+
}).modify({
|
|
536
|
+
status: "stale"
|
|
537
|
+
});
|
|
538
|
+
return log.error(`Failed to fetch ${balanceModule.type} balances`, error);
|
|
539
|
+
}
|
|
531
540
|
// ignore empty balance responses
|
|
532
|
-
if (!balances) return;
|
|
541
|
+
if (!balances$1) return;
|
|
533
542
|
// ignore balances from old subscriptions which are still in the process of unsubscribing
|
|
534
543
|
if (unsubscribed) return;
|
|
535
|
-
updateDb(balances);
|
|
544
|
+
updateDb(balances$1);
|
|
536
545
|
});
|
|
537
546
|
return () => {
|
|
538
547
|
// wait 2 seconds before actually unsubscribing, allowing for websocket to be reused
|
|
539
548
|
unsub.then(unsubscribe => {
|
|
540
549
|
setTimeout(unsubscribe, 2_000);
|
|
541
550
|
});
|
|
542
|
-
balances.db.
|
|
543
|
-
|
|
551
|
+
balances.db.balances.where({
|
|
552
|
+
source: balanceModule.type
|
|
553
|
+
}).filter(balance => {
|
|
544
554
|
if (!Object.keys(addressesByModuleToken).includes(balance.tokenId)) return false;
|
|
545
555
|
if (!addressesByModuleToken[balance.tokenId].includes(balance.address)) return false;
|
|
546
556
|
return true;
|
|
547
557
|
}).modify({
|
|
548
558
|
status: "cache"
|
|
549
|
-
})
|
|
559
|
+
});
|
|
550
560
|
};
|
|
551
561
|
});
|
|
552
562
|
const unsubscribeAll = () => {
|
|
@@ -597,6 +607,20 @@ function useTokenRate(tokenId) {
|
|
|
597
607
|
return tokenId ? tokenRates[tokenId] : undefined;
|
|
598
608
|
}
|
|
599
609
|
|
|
610
|
+
function useTokens(withTestnets) {
|
|
611
|
+
// keep db data up to date
|
|
612
|
+
useDbCacheSubscription("tokens");
|
|
613
|
+
const {
|
|
614
|
+
tokensWithTestnetsMap,
|
|
615
|
+
tokensWithoutTestnetsMap
|
|
616
|
+
} = useDbCache();
|
|
617
|
+
return withTestnets ? tokensWithTestnetsMap : tokensWithoutTestnetsMap;
|
|
618
|
+
}
|
|
619
|
+
function useToken(tokenId, withTestnets) {
|
|
620
|
+
const tokens = useTokens(withTestnets);
|
|
621
|
+
return tokenId ? tokens[tokenId] : undefined;
|
|
622
|
+
}
|
|
623
|
+
|
|
600
624
|
const useBalancesHydrate = () => {
|
|
601
625
|
const {
|
|
602
626
|
withTestnets
|
|
@@ -643,6 +667,35 @@ function useBalances(addressesByToken) {
|
|
|
643
667
|
hydrate), [balances$1, hydrate, balanceModules, addressesByToken]);
|
|
644
668
|
}
|
|
645
669
|
|
|
670
|
+
/**
|
|
671
|
+
* Given a collection of `Balances`, this hook returns a `BalancesStatus` summary for the collection.
|
|
672
|
+
*
|
|
673
|
+
* @param balances The collection of balances to get the status from.
|
|
674
|
+
* @param isLoadingLocks Because the wallet currently fetches locks outside of the balances api, this param can be used to indicate that the locks are still loading, even if the `Balances` collection is not.
|
|
675
|
+
* @returns An instance of `BalancesStatus` which represents the status of the balances collection.
|
|
676
|
+
|
|
677
|
+
*/
|
|
678
|
+
const useBalancesStatus = (balances, isLoadingLocks) => react.useMemo(() => {
|
|
679
|
+
// stale
|
|
680
|
+
const staleChains = getStaleChains(balances);
|
|
681
|
+
if (staleChains.length > 0) return {
|
|
682
|
+
status: "stale",
|
|
683
|
+
staleChains
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
// fetching
|
|
687
|
+
const hasCachedBalances = balances.each.some(b => b.status === "cache");
|
|
688
|
+
if (hasCachedBalances || isLoadingLocks) return {
|
|
689
|
+
status: "fetching"
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
// live
|
|
693
|
+
return {
|
|
694
|
+
status: "live"
|
|
695
|
+
};
|
|
696
|
+
}, [balances, isLoadingLocks]);
|
|
697
|
+
const getStaleChains = balances => [...new Set(balances.sorted.filter(b => b.status === "stale").map(b => b.chain?.name ?? b.chainId ?? "Unknown"))];
|
|
698
|
+
|
|
646
699
|
const BalancesProvider = ({
|
|
647
700
|
balanceModules,
|
|
648
701
|
onfinalityApiKey,
|
|
@@ -674,11 +727,13 @@ exports.ChaindataProvider = ChaindataProvider;
|
|
|
674
727
|
exports.DbCacheProvider = DbCacheProvider;
|
|
675
728
|
exports.WithTestnetsProvider = WithTestnetsProvider;
|
|
676
729
|
exports.createMulticastSubscription = createMulticastSubscription;
|
|
730
|
+
exports.getStaleChains = getStaleChains;
|
|
677
731
|
exports.provideContext = provideContext;
|
|
678
732
|
exports.useAllAddresses = useAllAddresses;
|
|
679
733
|
exports.useBalanceModules = useBalanceModules;
|
|
680
734
|
exports.useBalances = useBalances;
|
|
681
735
|
exports.useBalancesHydrate = useBalancesHydrate;
|
|
736
|
+
exports.useBalancesStatus = useBalancesStatus;
|
|
682
737
|
exports.useChain = useChain;
|
|
683
738
|
exports.useChainConnectors = useChainConnectors;
|
|
684
739
|
exports.useChaindata = useChaindata;
|
|
@@ -6,6 +6,7 @@ var react = require('react');
|
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
7
|
var chainConnector = require('@talismn/chain-connector');
|
|
8
8
|
var chainConnectorEvm = require('@talismn/chain-connector-evm');
|
|
9
|
+
var connectionMeta = require('@talismn/connection-meta');
|
|
9
10
|
var chaindataProviderExtension = require('@talismn/chaindata-provider-extension');
|
|
10
11
|
var balances = require('@talismn/balances');
|
|
11
12
|
var tokenRates = require('@talismn/token-rates');
|
|
@@ -73,7 +74,7 @@ function useChainConnectorsProvider(options) {
|
|
|
73
74
|
const chaindata = useChaindata();
|
|
74
75
|
|
|
75
76
|
// substrate connector
|
|
76
|
-
const substrate = react.useMemo(() => new chainConnector.ChainConnector(chaindata), [chaindata]);
|
|
77
|
+
const substrate = react.useMemo(() => new chainConnector.ChainConnector(chaindata, connectionMeta.connectionMetaDb), [chaindata]);
|
|
77
78
|
|
|
78
79
|
// evm connector
|
|
79
80
|
const evm = react.useMemo(() => new chainConnectorEvm.ChainConnectorEvm(chaindata, {
|
|
@@ -199,7 +200,7 @@ const [DbCacheProvider, useDbCache] = provideContext(useDbCacheProvider);
|
|
|
199
200
|
|
|
200
201
|
var packageJson = {
|
|
201
202
|
name: "@talismn/balances-react",
|
|
202
|
-
version: "0.0.0-
|
|
203
|
+
version: "0.0.0-pr644-20230322035559",
|
|
203
204
|
author: "Talisman",
|
|
204
205
|
homepage: "https://talisman.xyz",
|
|
205
206
|
license: "UNLICENSED",
|
|
@@ -230,6 +231,7 @@ var packageJson = {
|
|
|
230
231
|
"@talismn/chain-connector-evm": "workspace:^",
|
|
231
232
|
"@talismn/chaindata-provider": "workspace:^",
|
|
232
233
|
"@talismn/chaindata-provider-extension": "workspace:^",
|
|
234
|
+
"@talismn/connection-meta": "workspace:^",
|
|
233
235
|
"@talismn/token-rates": "workspace:^",
|
|
234
236
|
anylogger: "^1.0.11",
|
|
235
237
|
"blueimp-md5": "2.19.0",
|
|
@@ -313,20 +315,6 @@ const useSharedSubscription = (key, subscribe) => {
|
|
|
313
315
|
}, [key, subscribe]);
|
|
314
316
|
};
|
|
315
317
|
|
|
316
|
-
function useTokens(withTestnets) {
|
|
317
|
-
// keep db data up to date
|
|
318
|
-
useDbCacheSubscription("tokens");
|
|
319
|
-
const {
|
|
320
|
-
tokensWithTestnetsMap,
|
|
321
|
-
tokensWithoutTestnetsMap
|
|
322
|
-
} = useDbCache();
|
|
323
|
-
return withTestnets ? tokensWithTestnetsMap : tokensWithoutTestnetsMap;
|
|
324
|
-
}
|
|
325
|
-
function useToken(tokenId, withTestnets) {
|
|
326
|
-
const tokens = useTokens(withTestnets);
|
|
327
|
-
return tokenId ? tokens[tokenId] : undefined;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
318
|
/**
|
|
331
319
|
* Creates a subscription function that can be used to subscribe to a multicast observable created from an upstream source.
|
|
332
320
|
*
|
|
@@ -404,7 +392,7 @@ function useDbCacheTokenRatesSubscription() {
|
|
|
404
392
|
const {
|
|
405
393
|
withTestnets
|
|
406
394
|
} = useWithTestnets();
|
|
407
|
-
const tokens = useTokens(withTestnets);
|
|
395
|
+
const tokens = useTokens$1(withTestnets);
|
|
408
396
|
const subscriptionKey = react.useMemo(
|
|
409
397
|
// not super sexy but we need key to change based on this stuff
|
|
410
398
|
() => {
|
|
@@ -431,7 +419,7 @@ function useDbCacheBalancesSubscription() {
|
|
|
431
419
|
const chaindataProvider = useChaindata();
|
|
432
420
|
const chainConnectors = useChainConnectors();
|
|
433
421
|
const [allAddresses] = useAllAddresses();
|
|
434
|
-
const tokens = useTokens(withTestnets);
|
|
422
|
+
const tokens = useTokens$1(withTestnets);
|
|
435
423
|
const subscriptionKey = react.useMemo(
|
|
436
424
|
// not super sexy but we need key to change based on this stuff
|
|
437
425
|
() => {
|
|
@@ -442,10 +430,19 @@ function useDbCacheBalancesSubscription() {
|
|
|
442
430
|
}, [allAddresses, balanceModules, chainConnectors, chaindataProvider, tokens]);
|
|
443
431
|
const subscription = react.useCallback(() => {
|
|
444
432
|
if (!Object.values(tokens ?? {}).length || !allAddresses.length) return () => {};
|
|
445
|
-
return subscribeBalances(tokens ?? {}, allAddresses,
|
|
446
|
-
}, [allAddresses, balanceModules,
|
|
433
|
+
return subscribeBalances(tokens ?? {}, allAddresses, balanceModules);
|
|
434
|
+
}, [allAddresses, balanceModules, tokens]);
|
|
447
435
|
useSharedSubscription(subscriptionKey, subscription);
|
|
448
436
|
}
|
|
437
|
+
|
|
438
|
+
// subscriptionless version of useTokens, prevents circular dependency
|
|
439
|
+
const useTokens$1 = withTestnets => {
|
|
440
|
+
const {
|
|
441
|
+
tokensWithTestnetsMap,
|
|
442
|
+
tokensWithoutTestnetsMap
|
|
443
|
+
} = useDbCache();
|
|
444
|
+
return withTestnets ? tokensWithTestnetsMap : tokensWithoutTestnetsMap;
|
|
445
|
+
};
|
|
449
446
|
const subscribeChainDataHydrate = (provider, type) => {
|
|
450
447
|
const chaindata = provider;
|
|
451
448
|
const delay = 300_000; // 300_000ms = 300s = 5 minutes
|
|
@@ -501,7 +498,7 @@ const subscribeTokenRates = tokens => {
|
|
|
501
498
|
if (timeout) clearTimeout(timeout);
|
|
502
499
|
};
|
|
503
500
|
};
|
|
504
|
-
const subscribeBalances = (tokens, addresses,
|
|
501
|
+
const subscribeBalances = (tokens, addresses, balanceModules) => {
|
|
505
502
|
const tokenIds = Object.values(tokens).map(({
|
|
506
503
|
id
|
|
507
504
|
}) => id);
|
|
@@ -525,28 +522,41 @@ const subscribeBalances = (tokens, addresses, chainConnectors, provider, balance
|
|
|
525
522
|
id
|
|
526
523
|
}) => id);
|
|
527
524
|
const addressesByModuleToken = Object.fromEntries(Object.entries(addressesByToken).filter(([tokenId]) => moduleTokenIds.includes(tokenId)));
|
|
528
|
-
const unsub = balances.balances(balanceModule, addressesByModuleToken, (error, balances) => {
|
|
525
|
+
const unsub = balances.balances(balanceModule, addressesByModuleToken, (error, balances$1) => {
|
|
529
526
|
// log errors
|
|
530
|
-
if (error)
|
|
527
|
+
if (error) {
|
|
528
|
+
if (error?.type === "STALE_RPC_ERROR") return balances.db.balances.where({
|
|
529
|
+
source: balanceModule.type,
|
|
530
|
+
chainId: error.chainId
|
|
531
|
+
}).filter(balance => {
|
|
532
|
+
if (!Object.keys(addressesByModuleToken).includes(balance.tokenId)) return false;
|
|
533
|
+
if (!addressesByModuleToken[balance.tokenId].includes(balance.address)) return false;
|
|
534
|
+
return true;
|
|
535
|
+
}).modify({
|
|
536
|
+
status: "stale"
|
|
537
|
+
});
|
|
538
|
+
return log.error(`Failed to fetch ${balanceModule.type} balances`, error);
|
|
539
|
+
}
|
|
531
540
|
// ignore empty balance responses
|
|
532
|
-
if (!balances) return;
|
|
541
|
+
if (!balances$1) return;
|
|
533
542
|
// ignore balances from old subscriptions which are still in the process of unsubscribing
|
|
534
543
|
if (unsubscribed) return;
|
|
535
|
-
updateDb(balances);
|
|
544
|
+
updateDb(balances$1);
|
|
536
545
|
});
|
|
537
546
|
return () => {
|
|
538
547
|
// wait 2 seconds before actually unsubscribing, allowing for websocket to be reused
|
|
539
548
|
unsub.then(unsubscribe => {
|
|
540
549
|
setTimeout(unsubscribe, 2_000);
|
|
541
550
|
});
|
|
542
|
-
balances.db.
|
|
543
|
-
|
|
551
|
+
balances.db.balances.where({
|
|
552
|
+
source: balanceModule.type
|
|
553
|
+
}).filter(balance => {
|
|
544
554
|
if (!Object.keys(addressesByModuleToken).includes(balance.tokenId)) return false;
|
|
545
555
|
if (!addressesByModuleToken[balance.tokenId].includes(balance.address)) return false;
|
|
546
556
|
return true;
|
|
547
557
|
}).modify({
|
|
548
558
|
status: "cache"
|
|
549
|
-
})
|
|
559
|
+
});
|
|
550
560
|
};
|
|
551
561
|
});
|
|
552
562
|
const unsubscribeAll = () => {
|
|
@@ -597,6 +607,20 @@ function useTokenRate(tokenId) {
|
|
|
597
607
|
return tokenId ? tokenRates[tokenId] : undefined;
|
|
598
608
|
}
|
|
599
609
|
|
|
610
|
+
function useTokens(withTestnets) {
|
|
611
|
+
// keep db data up to date
|
|
612
|
+
useDbCacheSubscription("tokens");
|
|
613
|
+
const {
|
|
614
|
+
tokensWithTestnetsMap,
|
|
615
|
+
tokensWithoutTestnetsMap
|
|
616
|
+
} = useDbCache();
|
|
617
|
+
return withTestnets ? tokensWithTestnetsMap : tokensWithoutTestnetsMap;
|
|
618
|
+
}
|
|
619
|
+
function useToken(tokenId, withTestnets) {
|
|
620
|
+
const tokens = useTokens(withTestnets);
|
|
621
|
+
return tokenId ? tokens[tokenId] : undefined;
|
|
622
|
+
}
|
|
623
|
+
|
|
600
624
|
const useBalancesHydrate = () => {
|
|
601
625
|
const {
|
|
602
626
|
withTestnets
|
|
@@ -643,6 +667,35 @@ function useBalances(addressesByToken) {
|
|
|
643
667
|
hydrate), [balances$1, hydrate, balanceModules, addressesByToken]);
|
|
644
668
|
}
|
|
645
669
|
|
|
670
|
+
/**
|
|
671
|
+
* Given a collection of `Balances`, this hook returns a `BalancesStatus` summary for the collection.
|
|
672
|
+
*
|
|
673
|
+
* @param balances The collection of balances to get the status from.
|
|
674
|
+
* @param isLoadingLocks Because the wallet currently fetches locks outside of the balances api, this param can be used to indicate that the locks are still loading, even if the `Balances` collection is not.
|
|
675
|
+
* @returns An instance of `BalancesStatus` which represents the status of the balances collection.
|
|
676
|
+
|
|
677
|
+
*/
|
|
678
|
+
const useBalancesStatus = (balances, isLoadingLocks) => react.useMemo(() => {
|
|
679
|
+
// stale
|
|
680
|
+
const staleChains = getStaleChains(balances);
|
|
681
|
+
if (staleChains.length > 0) return {
|
|
682
|
+
status: "stale",
|
|
683
|
+
staleChains
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
// fetching
|
|
687
|
+
const hasCachedBalances = balances.each.some(b => b.status === "cache");
|
|
688
|
+
if (hasCachedBalances || isLoadingLocks) return {
|
|
689
|
+
status: "fetching"
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
// live
|
|
693
|
+
return {
|
|
694
|
+
status: "live"
|
|
695
|
+
};
|
|
696
|
+
}, [balances, isLoadingLocks]);
|
|
697
|
+
const getStaleChains = balances => [...new Set(balances.sorted.filter(b => b.status === "stale").map(b => b.chain?.name ?? b.chainId ?? "Unknown"))];
|
|
698
|
+
|
|
646
699
|
const BalancesProvider = ({
|
|
647
700
|
balanceModules,
|
|
648
701
|
onfinalityApiKey,
|
|
@@ -674,11 +727,13 @@ exports.ChaindataProvider = ChaindataProvider;
|
|
|
674
727
|
exports.DbCacheProvider = DbCacheProvider;
|
|
675
728
|
exports.WithTestnetsProvider = WithTestnetsProvider;
|
|
676
729
|
exports.createMulticastSubscription = createMulticastSubscription;
|
|
730
|
+
exports.getStaleChains = getStaleChains;
|
|
677
731
|
exports.provideContext = provideContext;
|
|
678
732
|
exports.useAllAddresses = useAllAddresses;
|
|
679
733
|
exports.useBalanceModules = useBalanceModules;
|
|
680
734
|
exports.useBalances = useBalances;
|
|
681
735
|
exports.useBalancesHydrate = useBalancesHydrate;
|
|
736
|
+
exports.useBalancesStatus = useBalancesStatus;
|
|
682
737
|
exports.useChain = useChain;
|
|
683
738
|
exports.useChainConnectors = useChainConnectors;
|
|
684
739
|
exports.useChaindata = useChaindata;
|
|
@@ -2,6 +2,7 @@ import { useContext, createContext, useState, useEffect, useMemo, useRef, useCal
|
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { ChainConnector } from '@talismn/chain-connector';
|
|
4
4
|
import { ChainConnectorEvm } from '@talismn/chain-connector-evm';
|
|
5
|
+
import { connectionMetaDb } from '@talismn/connection-meta';
|
|
5
6
|
import { ChaindataProviderExtension } from '@talismn/chaindata-provider-extension';
|
|
6
7
|
import { db as db$1, balances, Balances } from '@talismn/balances';
|
|
7
8
|
import { db, fetchTokenRates } from '@talismn/token-rates';
|
|
@@ -64,7 +65,7 @@ function useChainConnectorsProvider(options) {
|
|
|
64
65
|
const chaindata = useChaindata();
|
|
65
66
|
|
|
66
67
|
// substrate connector
|
|
67
|
-
const substrate = useMemo(() => new ChainConnector(chaindata), [chaindata]);
|
|
68
|
+
const substrate = useMemo(() => new ChainConnector(chaindata, connectionMetaDb), [chaindata]);
|
|
68
69
|
|
|
69
70
|
// evm connector
|
|
70
71
|
const evm = useMemo(() => new ChainConnectorEvm(chaindata, {
|
|
@@ -190,7 +191,7 @@ const [DbCacheProvider, useDbCache] = provideContext(useDbCacheProvider);
|
|
|
190
191
|
|
|
191
192
|
var packageJson = {
|
|
192
193
|
name: "@talismn/balances-react",
|
|
193
|
-
version: "0.0.0-
|
|
194
|
+
version: "0.0.0-pr644-20230322035559",
|
|
194
195
|
author: "Talisman",
|
|
195
196
|
homepage: "https://talisman.xyz",
|
|
196
197
|
license: "UNLICENSED",
|
|
@@ -221,6 +222,7 @@ var packageJson = {
|
|
|
221
222
|
"@talismn/chain-connector-evm": "workspace:^",
|
|
222
223
|
"@talismn/chaindata-provider": "workspace:^",
|
|
223
224
|
"@talismn/chaindata-provider-extension": "workspace:^",
|
|
225
|
+
"@talismn/connection-meta": "workspace:^",
|
|
224
226
|
"@talismn/token-rates": "workspace:^",
|
|
225
227
|
anylogger: "^1.0.11",
|
|
226
228
|
"blueimp-md5": "2.19.0",
|
|
@@ -304,20 +306,6 @@ const useSharedSubscription = (key, subscribe) => {
|
|
|
304
306
|
}, [key, subscribe]);
|
|
305
307
|
};
|
|
306
308
|
|
|
307
|
-
function useTokens(withTestnets) {
|
|
308
|
-
// keep db data up to date
|
|
309
|
-
useDbCacheSubscription("tokens");
|
|
310
|
-
const {
|
|
311
|
-
tokensWithTestnetsMap,
|
|
312
|
-
tokensWithoutTestnetsMap
|
|
313
|
-
} = useDbCache();
|
|
314
|
-
return withTestnets ? tokensWithTestnetsMap : tokensWithoutTestnetsMap;
|
|
315
|
-
}
|
|
316
|
-
function useToken(tokenId, withTestnets) {
|
|
317
|
-
const tokens = useTokens(withTestnets);
|
|
318
|
-
return tokenId ? tokens[tokenId] : undefined;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
309
|
/**
|
|
322
310
|
* Creates a subscription function that can be used to subscribe to a multicast observable created from an upstream source.
|
|
323
311
|
*
|
|
@@ -395,7 +383,7 @@ function useDbCacheTokenRatesSubscription() {
|
|
|
395
383
|
const {
|
|
396
384
|
withTestnets
|
|
397
385
|
} = useWithTestnets();
|
|
398
|
-
const tokens = useTokens(withTestnets);
|
|
386
|
+
const tokens = useTokens$1(withTestnets);
|
|
399
387
|
const subscriptionKey = useMemo(
|
|
400
388
|
// not super sexy but we need key to change based on this stuff
|
|
401
389
|
() => {
|
|
@@ -422,7 +410,7 @@ function useDbCacheBalancesSubscription() {
|
|
|
422
410
|
const chaindataProvider = useChaindata();
|
|
423
411
|
const chainConnectors = useChainConnectors();
|
|
424
412
|
const [allAddresses] = useAllAddresses();
|
|
425
|
-
const tokens = useTokens(withTestnets);
|
|
413
|
+
const tokens = useTokens$1(withTestnets);
|
|
426
414
|
const subscriptionKey = useMemo(
|
|
427
415
|
// not super sexy but we need key to change based on this stuff
|
|
428
416
|
() => {
|
|
@@ -433,10 +421,19 @@ function useDbCacheBalancesSubscription() {
|
|
|
433
421
|
}, [allAddresses, balanceModules, chainConnectors, chaindataProvider, tokens]);
|
|
434
422
|
const subscription = useCallback(() => {
|
|
435
423
|
if (!Object.values(tokens ?? {}).length || !allAddresses.length) return () => {};
|
|
436
|
-
return subscribeBalances(tokens ?? {}, allAddresses,
|
|
437
|
-
}, [allAddresses, balanceModules,
|
|
424
|
+
return subscribeBalances(tokens ?? {}, allAddresses, balanceModules);
|
|
425
|
+
}, [allAddresses, balanceModules, tokens]);
|
|
438
426
|
useSharedSubscription(subscriptionKey, subscription);
|
|
439
427
|
}
|
|
428
|
+
|
|
429
|
+
// subscriptionless version of useTokens, prevents circular dependency
|
|
430
|
+
const useTokens$1 = withTestnets => {
|
|
431
|
+
const {
|
|
432
|
+
tokensWithTestnetsMap,
|
|
433
|
+
tokensWithoutTestnetsMap
|
|
434
|
+
} = useDbCache();
|
|
435
|
+
return withTestnets ? tokensWithTestnetsMap : tokensWithoutTestnetsMap;
|
|
436
|
+
};
|
|
440
437
|
const subscribeChainDataHydrate = (provider, type) => {
|
|
441
438
|
const chaindata = provider;
|
|
442
439
|
const delay = 300_000; // 300_000ms = 300s = 5 minutes
|
|
@@ -492,7 +489,7 @@ const subscribeTokenRates = tokens => {
|
|
|
492
489
|
if (timeout) clearTimeout(timeout);
|
|
493
490
|
};
|
|
494
491
|
};
|
|
495
|
-
const subscribeBalances = (tokens, addresses,
|
|
492
|
+
const subscribeBalances = (tokens, addresses, balanceModules) => {
|
|
496
493
|
const tokenIds = Object.values(tokens).map(({
|
|
497
494
|
id
|
|
498
495
|
}) => id);
|
|
@@ -518,7 +515,19 @@ const subscribeBalances = (tokens, addresses, chainConnectors, provider, balance
|
|
|
518
515
|
const addressesByModuleToken = Object.fromEntries(Object.entries(addressesByToken).filter(([tokenId]) => moduleTokenIds.includes(tokenId)));
|
|
519
516
|
const unsub = balances(balanceModule, addressesByModuleToken, (error, balances) => {
|
|
520
517
|
// log errors
|
|
521
|
-
if (error)
|
|
518
|
+
if (error) {
|
|
519
|
+
if (error?.type === "STALE_RPC_ERROR") return db$1.balances.where({
|
|
520
|
+
source: balanceModule.type,
|
|
521
|
+
chainId: error.chainId
|
|
522
|
+
}).filter(balance => {
|
|
523
|
+
if (!Object.keys(addressesByModuleToken).includes(balance.tokenId)) return false;
|
|
524
|
+
if (!addressesByModuleToken[balance.tokenId].includes(balance.address)) return false;
|
|
525
|
+
return true;
|
|
526
|
+
}).modify({
|
|
527
|
+
status: "stale"
|
|
528
|
+
});
|
|
529
|
+
return log.error(`Failed to fetch ${balanceModule.type} balances`, error);
|
|
530
|
+
}
|
|
522
531
|
// ignore empty balance responses
|
|
523
532
|
if (!balances) return;
|
|
524
533
|
// ignore balances from old subscriptions which are still in the process of unsubscribing
|
|
@@ -530,14 +539,15 @@ const subscribeBalances = (tokens, addresses, chainConnectors, provider, balance
|
|
|
530
539
|
unsub.then(unsubscribe => {
|
|
531
540
|
setTimeout(unsubscribe, 2_000);
|
|
532
541
|
});
|
|
533
|
-
db$1.
|
|
534
|
-
|
|
542
|
+
db$1.balances.where({
|
|
543
|
+
source: balanceModule.type
|
|
544
|
+
}).filter(balance => {
|
|
535
545
|
if (!Object.keys(addressesByModuleToken).includes(balance.tokenId)) return false;
|
|
536
546
|
if (!addressesByModuleToken[balance.tokenId].includes(balance.address)) return false;
|
|
537
547
|
return true;
|
|
538
548
|
}).modify({
|
|
539
549
|
status: "cache"
|
|
540
|
-
})
|
|
550
|
+
});
|
|
541
551
|
};
|
|
542
552
|
});
|
|
543
553
|
const unsubscribeAll = () => {
|
|
@@ -588,6 +598,20 @@ function useTokenRate(tokenId) {
|
|
|
588
598
|
return tokenId ? tokenRates[tokenId] : undefined;
|
|
589
599
|
}
|
|
590
600
|
|
|
601
|
+
function useTokens(withTestnets) {
|
|
602
|
+
// keep db data up to date
|
|
603
|
+
useDbCacheSubscription("tokens");
|
|
604
|
+
const {
|
|
605
|
+
tokensWithTestnetsMap,
|
|
606
|
+
tokensWithoutTestnetsMap
|
|
607
|
+
} = useDbCache();
|
|
608
|
+
return withTestnets ? tokensWithTestnetsMap : tokensWithoutTestnetsMap;
|
|
609
|
+
}
|
|
610
|
+
function useToken(tokenId, withTestnets) {
|
|
611
|
+
const tokens = useTokens(withTestnets);
|
|
612
|
+
return tokenId ? tokens[tokenId] : undefined;
|
|
613
|
+
}
|
|
614
|
+
|
|
591
615
|
const useBalancesHydrate = () => {
|
|
592
616
|
const {
|
|
593
617
|
withTestnets
|
|
@@ -634,6 +658,35 @@ function useBalances(addressesByToken) {
|
|
|
634
658
|
hydrate), [balances, hydrate, balanceModules, addressesByToken]);
|
|
635
659
|
}
|
|
636
660
|
|
|
661
|
+
/**
|
|
662
|
+
* Given a collection of `Balances`, this hook returns a `BalancesStatus` summary for the collection.
|
|
663
|
+
*
|
|
664
|
+
* @param balances The collection of balances to get the status from.
|
|
665
|
+
* @param isLoadingLocks Because the wallet currently fetches locks outside of the balances api, this param can be used to indicate that the locks are still loading, even if the `Balances` collection is not.
|
|
666
|
+
* @returns An instance of `BalancesStatus` which represents the status of the balances collection.
|
|
667
|
+
|
|
668
|
+
*/
|
|
669
|
+
const useBalancesStatus = (balances, isLoadingLocks) => useMemo(() => {
|
|
670
|
+
// stale
|
|
671
|
+
const staleChains = getStaleChains(balances);
|
|
672
|
+
if (staleChains.length > 0) return {
|
|
673
|
+
status: "stale",
|
|
674
|
+
staleChains
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
// fetching
|
|
678
|
+
const hasCachedBalances = balances.each.some(b => b.status === "cache");
|
|
679
|
+
if (hasCachedBalances || isLoadingLocks) return {
|
|
680
|
+
status: "fetching"
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
// live
|
|
684
|
+
return {
|
|
685
|
+
status: "live"
|
|
686
|
+
};
|
|
687
|
+
}, [balances, isLoadingLocks]);
|
|
688
|
+
const getStaleChains = balances => [...new Set(balances.sorted.filter(b => b.status === "stale").map(b => b.chain?.name ?? b.chainId ?? "Unknown"))];
|
|
689
|
+
|
|
637
690
|
const BalancesProvider = ({
|
|
638
691
|
balanceModules,
|
|
639
692
|
onfinalityApiKey,
|
|
@@ -657,4 +710,4 @@ const BalancesProvider = ({
|
|
|
657
710
|
})
|
|
658
711
|
});
|
|
659
712
|
|
|
660
|
-
export { AllAddressesProvider, BalanceModulesProvider, BalancesProvider, ChainConnectorsProvider, ChaindataProvider, DbCacheProvider, WithTestnetsProvider, createMulticastSubscription, provideContext, useAllAddresses, useBalanceModules, useBalances, useBalancesHydrate, useChain, useChainConnectors, useChaindata, useChains, useDbCache, useDbCacheBalancesSubscription, useDbCacheSubscription, useDbCacheTokenRatesSubscription, useEvmNetwork, useEvmNetworks, useMulticastSubscription, useToken, useTokenRate, useTokenRates, useTokens, useWithTestnets };
|
|
713
|
+
export { AllAddressesProvider, BalanceModulesProvider, BalancesProvider, ChainConnectorsProvider, ChaindataProvider, DbCacheProvider, WithTestnetsProvider, createMulticastSubscription, getStaleChains, provideContext, useAllAddresses, useBalanceModules, useBalances, useBalancesHydrate, useBalancesStatus, useChain, useChainConnectors, useChaindata, useChains, useDbCache, useDbCacheBalancesSubscription, useDbCacheSubscription, useDbCacheTokenRatesSubscription, useEvmNetwork, useEvmNetworks, useMulticastSubscription, useToken, useTokenRate, useTokenRates, useTokens, useWithTestnets };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@talismn/balances-react",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-pr644-20230322035559",
|
|
4
4
|
"author": "Talisman",
|
|
5
5
|
"homepage": "https://talisman.xyz",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -26,12 +26,13 @@
|
|
|
26
26
|
"clean": "rm -rf dist && rm -rf .turbo rm -rf node_modules"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@talismn/balances": "^0.0.0-
|
|
30
|
-
"@talismn/chain-connector": "^0.0.0-
|
|
31
|
-
"@talismn/chain-connector-evm": "^0.0.0-
|
|
32
|
-
"@talismn/chaindata-provider": "^0.0.0-
|
|
33
|
-
"@talismn/chaindata-provider-extension": "^0.0.0-
|
|
34
|
-
"@talismn/
|
|
29
|
+
"@talismn/balances": "^0.0.0-pr644-20230322035559",
|
|
30
|
+
"@talismn/chain-connector": "^0.0.0-pr644-20230322035559",
|
|
31
|
+
"@talismn/chain-connector-evm": "^0.0.0-pr644-20230322035559",
|
|
32
|
+
"@talismn/chaindata-provider": "^0.0.0-pr644-20230322035559",
|
|
33
|
+
"@talismn/chaindata-provider-extension": "^0.0.0-pr644-20230322035559",
|
|
34
|
+
"@talismn/connection-meta": "^0.0.0-pr644-20230322035559",
|
|
35
|
+
"@talismn/token-rates": "^0.0.0-pr644-20230322035559",
|
|
35
36
|
"anylogger": "^1.0.11",
|
|
36
37
|
"blueimp-md5": "2.19.0",
|
|
37
38
|
"dexie": "^3.2.3",
|