@talismn/balances-react 0.1.6 → 0.1.8
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 +26 -0
- package/dist/hooks/useBalances.js +92 -54
- package/dist/hooks/useChaindata.js +1 -0
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,31 @@
|
|
1
1
|
# @talismn/balances-react
|
2
2
|
|
3
|
+
## 0.1.8
|
4
|
+
|
5
|
+
### Patch Changes
|
6
|
+
|
7
|
+
- 3db774a: fix: useBalances creating too many subscriptions when called from multiple components
|
8
|
+
- Updated dependencies [cbd4770]
|
9
|
+
- Updated dependencies [3db774a]
|
10
|
+
- @talismn/balances-substrate-native@0.1.8
|
11
|
+
- @talismn/balances-substrate-orml@0.1.8
|
12
|
+
- @talismn/balances@0.1.8
|
13
|
+
- @talismn/balances-evm-erc20@0.1.8
|
14
|
+
- @talismn/balances-evm-native@0.1.8
|
15
|
+
- @talismn/balances-example@0.1.8
|
16
|
+
|
17
|
+
## 0.1.7
|
18
|
+
|
19
|
+
### Patch Changes
|
20
|
+
|
21
|
+
- Updated dependencies [1582220]
|
22
|
+
- @talismn/balances-substrate-native@0.1.7
|
23
|
+
- @talismn/balances-substrate-orml@0.1.7
|
24
|
+
- @talismn/balances@0.1.7
|
25
|
+
- @talismn/balances-evm-erc20@0.1.7
|
26
|
+
- @talismn/balances-evm-native@0.1.7
|
27
|
+
- @talismn/balances-example@0.1.7
|
28
|
+
|
3
29
|
## 0.1.6
|
4
30
|
|
5
31
|
### Patch Changes
|
@@ -18,6 +18,89 @@ import { useChains, useEvmNetworks, useTokens } from "./useChaindata";
|
|
18
18
|
export function useBalances(
|
19
19
|
// TODO: Make this array of BalanceModules more type-safe
|
20
20
|
balanceModules, chaindataProvider, addressesByToken) {
|
21
|
+
useBalancesSubscriptions(balanceModules, chaindataProvider, addressesByToken);
|
22
|
+
const chains = useChains(chaindataProvider);
|
23
|
+
const evmNetworks = useEvmNetworks(chaindataProvider);
|
24
|
+
const tokens = useTokens(chaindataProvider);
|
25
|
+
const balances = useLiveQuery(() => __awaiter(this, void 0, void 0, function* () {
|
26
|
+
return new Balances(yield db.balances
|
27
|
+
.filter((balance) => {
|
28
|
+
if (!balanceModules.map(({ type }) => type).includes(balance.source))
|
29
|
+
return false;
|
30
|
+
if (!addressesByToken)
|
31
|
+
return false;
|
32
|
+
if (!Object.keys(addressesByToken).includes(balance.tokenId))
|
33
|
+
return false;
|
34
|
+
if (!addressesByToken[balance.tokenId].includes(balance.address))
|
35
|
+
return false;
|
36
|
+
return true;
|
37
|
+
})
|
38
|
+
.toArray(), { chains, evmNetworks, tokens });
|
39
|
+
}), [balanceModules, addressesByToken, chains, evmNetworks, tokens]);
|
40
|
+
// debounce every 100ms to prevent hammering UI with updates
|
41
|
+
const [debouncedBalances, setDebouncedBalances] = useState(balances);
|
42
|
+
useDebounce(() => balances && setDebouncedBalances(balances), 100, [balances]);
|
43
|
+
return debouncedBalances;
|
44
|
+
}
|
45
|
+
// TODO: Turn into react context
|
46
|
+
const subscriptions = {};
|
47
|
+
// This hook is responsible for allowing us to call useBalances
|
48
|
+
// from multiple components, without setting up unnecessary
|
49
|
+
// balance subscriptions
|
50
|
+
function useBalancesSubscriptions(
|
51
|
+
// TODO: Make this array of BalanceModules more type-safe
|
52
|
+
balanceModules, chaindataProvider, addressesByToken) {
|
53
|
+
// const subscriptions = useRef<
|
54
|
+
// Record<string, { unsub: Promise<() => void>; refcount: number; generation: number }>
|
55
|
+
// >({})
|
56
|
+
const addSubscription = (key, balanceModule, chainConnector, chaindataProvider, addressesByToken) => {
|
57
|
+
var _a;
|
58
|
+
// create subscription if it doesn't already exist
|
59
|
+
if (!subscriptions[key] || subscriptions[key].refcount === 0) {
|
60
|
+
const generation = ((((_a = subscriptions[key]) === null || _a === void 0 ? void 0 : _a.generation) || 0) + 1) % Number.MAX_SAFE_INTEGER;
|
61
|
+
const unsub = balancesFn(balanceModule, chainConnector, chaindataProvider, addressesByToken, (error, balances) => {
|
62
|
+
if (error)
|
63
|
+
return log.error(`Failed to fetch ${balanceModule.type} balances`, error);
|
64
|
+
if (!balances)
|
65
|
+
return;
|
66
|
+
// ignore balances from old subscriptions which are still in the process of unsubscribing
|
67
|
+
if (subscriptions[key].generation !== generation)
|
68
|
+
return;
|
69
|
+
const putBalances = Object.entries(balances.toJSON()).map(([id, balance]) => (Object.assign({ id }, balance)));
|
70
|
+
db.transaction("rw", db.balances, () => __awaiter(this, void 0, void 0, function* () { return yield db.balances.bulkPut(putBalances); }));
|
71
|
+
});
|
72
|
+
subscriptions[key] = { unsub, refcount: 0, generation };
|
73
|
+
}
|
74
|
+
// bump up the refcount by 1
|
75
|
+
subscriptions[key].refcount += 1;
|
76
|
+
};
|
77
|
+
const removeSubscription = (key, balanceModule, addressesByToken) => {
|
78
|
+
// ignore dead subscriptions
|
79
|
+
if (!subscriptions[key] || subscriptions[key].refcount === 0)
|
80
|
+
return;
|
81
|
+
// drop the refcount by one
|
82
|
+
subscriptions[key].refcount -= 1;
|
83
|
+
// unsubscribe if refcount is now 0 (nobody wants this subcription anymore)
|
84
|
+
if (subscriptions[key].refcount < 1) {
|
85
|
+
// remove subscription
|
86
|
+
subscriptions[key].unsub.then((unsub) => unsub());
|
87
|
+
delete subscriptions[key];
|
88
|
+
// set this subscription's balances in the store to status: cache
|
89
|
+
db.transaction("rw", db.balances, () => __awaiter(this, void 0, void 0, function* () {
|
90
|
+
return yield db.balances
|
91
|
+
.filter((balance) => {
|
92
|
+
if (balance.source !== balanceModule.type)
|
93
|
+
return false;
|
94
|
+
if (!Object.keys(addressesByToken).includes(balance.tokenId))
|
95
|
+
return false;
|
96
|
+
if (!addressesByToken[balance.tokenId].includes(balance.address))
|
97
|
+
return false;
|
98
|
+
return true;
|
99
|
+
})
|
100
|
+
.modify({ status: "cache" });
|
101
|
+
}));
|
102
|
+
}
|
103
|
+
};
|
21
104
|
const chainConnector = useChainConnector(chaindataProvider);
|
22
105
|
useEffect(() => {
|
23
106
|
if (chainConnector === null)
|
@@ -26,61 +109,16 @@ balanceModules, chaindataProvider, addressesByToken) {
|
|
26
109
|
return;
|
27
110
|
if (addressesByToken === null)
|
28
111
|
return;
|
29
|
-
const
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
// TODO: Set balances status to cache on unmount
|
39
|
-
return () => {
|
40
|
-
unsubscribePromises.forEach((unsubscribePromise) => unsubscribePromise.then((unsub) => unsub()));
|
41
|
-
};
|
112
|
+
const unsubs = balanceModules.map((balanceModule) => {
|
113
|
+
const subscriptionKey = `${balanceModule.type}-${JSON.stringify(addressesByToken)}`;
|
114
|
+
// add balance subscription for this module
|
115
|
+
addSubscription(subscriptionKey, balanceModule, chainConnector, chaindataProvider, addressesByToken);
|
116
|
+
// return an unsub method, to be called when this effect unmounts
|
117
|
+
return () => removeSubscription(subscriptionKey, balanceModule, addressesByToken);
|
118
|
+
});
|
119
|
+
const unsubAll = () => unsubs.forEach((unsub) => unsub());
|
120
|
+
return unsubAll;
|
42
121
|
}, [addressesByToken, chainConnector]);
|
43
|
-
const chains = useChains(chaindataProvider);
|
44
|
-
const evmNetworks = useEvmNetworks(chaindataProvider);
|
45
|
-
const tokens = useTokens(chaindataProvider);
|
46
|
-
const balances = useLiveQuery(() => __awaiter(this, void 0, void 0, function* () { return new Balances(yield db.balances.toArray(), { chains, evmNetworks, tokens }); }), [chains, evmNetworks, tokens]);
|
47
|
-
// debounce every 100ms to prevent hammering UI with updates
|
48
|
-
const [debouncedBalances, setDebouncedBalances] = useState(balances);
|
49
|
-
useDebounce(() => balances && setDebouncedBalances(balances), 100, [balances]);
|
50
|
-
// // TMP
|
51
|
-
// // TMP
|
52
|
-
// // TMP
|
53
|
-
// useEffect(() => {
|
54
|
-
// if (chainConnector === null) return
|
55
|
-
// if (chaindataProvider === null) return
|
56
|
-
// const SubNativeModule = balanceModules.find((module) => module.type === "substrate-native")
|
57
|
-
// if (!SubNativeModule) return
|
58
|
-
// ;(async () => {
|
59
|
-
// const chainIds = ["polkadot", "kusama", "acala", "gm", "westend-testnet"]
|
60
|
-
// await Promise.all(
|
61
|
-
// chainIds.map(async (chainId) => {
|
62
|
-
// const chainMeta = await SubNativeModule.fetchSubstrateChainMeta(
|
63
|
-
// chainConnector,
|
64
|
-
// chaindataProvider,
|
65
|
-
// chainId
|
66
|
-
// )
|
67
|
-
// console.log(chainId, "chainMeta", chainMeta)
|
68
|
-
// const tokens = await SubNativeModule.fetchSubstrateChainTokens(
|
69
|
-
// chainConnector,
|
70
|
-
// chaindataProvider,
|
71
|
-
// chainId,
|
72
|
-
// chainMeta
|
73
|
-
// )
|
74
|
-
// console.log(chainId, "tokens", tokens)
|
75
|
-
// return tokens
|
76
|
-
// })
|
77
|
-
// )
|
78
|
-
// })()
|
79
|
-
// }, [chainConnector, chaindataProvider])
|
80
|
-
// // END TMP
|
81
|
-
// // END TMP
|
82
|
-
// // END TMP
|
83
|
-
return debouncedBalances;
|
84
122
|
}
|
85
123
|
// TODO: Allow advanced users of this library to provide their own chain connector
|
86
124
|
function useChainConnector(chaindataProvider) {
|
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
10
10
|
import { ChaindataProviderExtension } from "@talismn/chaindata-provider-extension";
|
11
11
|
import { useEffect, useState } from "react";
|
12
12
|
import log from "../log";
|
13
|
+
// TODO: Allow user to call useChaindata from multiple places
|
13
14
|
export function useChaindata() {
|
14
15
|
const [chaindataProvider, setChaindataProvider] = useState(null);
|
15
16
|
// this number is incremented each time the chaindataProvider has fetched new data
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@talismn/balances-react",
|
3
|
-
"version": "0.1.
|
3
|
+
"version": "0.1.8",
|
4
4
|
"author": "Talisman",
|
5
5
|
"homepage": "https://talisman.xyz",
|
6
6
|
"license": "UNLICENSED",
|
@@ -30,12 +30,12 @@
|
|
30
30
|
"clean": "rm -rf dist && rm -rf .turbo rm -rf node_modules"
|
31
31
|
},
|
32
32
|
"dependencies": {
|
33
|
-
"@talismn/balances": "^0.1.
|
34
|
-
"@talismn/balances-evm-erc20": "^0.1.
|
35
|
-
"@talismn/balances-evm-native": "^0.1.
|
36
|
-
"@talismn/balances-example": "^0.1.
|
37
|
-
"@talismn/balances-substrate-native": "^0.1.
|
38
|
-
"@talismn/balances-substrate-orml": "^0.1.
|
33
|
+
"@talismn/balances": "^0.1.8",
|
34
|
+
"@talismn/balances-evm-erc20": "^0.1.8",
|
35
|
+
"@talismn/balances-evm-native": "^0.1.8",
|
36
|
+
"@talismn/balances-example": "^0.1.8",
|
37
|
+
"@talismn/balances-substrate-native": "^0.1.8",
|
38
|
+
"@talismn/balances-substrate-orml": "^0.1.8",
|
39
39
|
"@talismn/chain-connector": "^0.1.4",
|
40
40
|
"@talismn/chaindata-provider": "^0.1.4",
|
41
41
|
"@talismn/chaindata-provider-extension": "^0.1.4",
|