@talismn/balances-react 1.3.0 → 1.3.2

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.
@@ -1,3 +0,0 @@
1
- import { ChaindataProvider } from "@talismn/chaindata-provider";
2
- export declare const chaindataProviderAtom: import("jotai").Atom<ChaindataProvider>;
3
- export declare const useSyncSwapsChaindata: () => [void, never];
@@ -1,11 +0,0 @@
1
- import { CoinsApiConfig } from "@talismn/token-rates";
2
- export declare const coinsApiConfigAtom: import("jotai").WritableAtom<CoinsApiConfig, [Partial<CoinsApiConfig>], void>;
3
- export declare const enableTestnetsAtom: import("jotai").PrimitiveAtom<boolean> & {
4
- init: boolean;
5
- };
6
- export declare const enabledChainsAtom: import("jotai").PrimitiveAtom<string[] | undefined> & {
7
- init: string[] | undefined;
8
- };
9
- export declare const enabledTokensAtom: import("jotai").PrimitiveAtom<string[] | undefined> & {
10
- init: string[] | undefined;
11
- };
@@ -1 +0,0 @@
1
- export declare const cryptoWaitReadyAtom: import("jotai").Atom<Promise<boolean>>;
@@ -1 +0,0 @@
1
- export declare const tokenRatesAtom: import("jotai").Atom<Promise<import("@talismn/token-rates").TokenRatesList>>;
@@ -1,26 +0,0 @@
1
- import { Balances } from "@talismn/balances";
2
- export declare const useSetBalancesAddresses: (addresses: string[]) => void;
3
- /**
4
- * @name useBalances
5
- * @description Hook to get the current balances state.
6
- * @param persistBackend an optional BalancesPersistBackend backend to use for persisting the balances state. By default, indexedDB is used.
7
- * @returns a Balances object containing the current balances state.
8
- */
9
- export declare const useBalances: () => Balances;
10
- export type BalancesStatus = {
11
- status: "live";
12
- } | {
13
- status: "fetching";
14
- } | {
15
- status: "stale";
16
- staleChains: string[];
17
- };
18
- /**
19
- * Given a collection of `Balances`, this hook returns a `BalancesStatus` summary for the collection.
20
- *
21
- * @param balances The collection of balances to get the status from.
22
- * @returns An instance of `BalancesStatus` which represents the status of the balances collection.
23
-
24
- */
25
- export declare const useBalancesStatus: (balances: Balances) => BalancesStatus;
26
- export declare const getStaleChains: (balances: Balances) => string[];
@@ -1 +0,0 @@
1
- export declare const useChainConnectors: () => import("@talismn/balances").ChainConnectors;
@@ -1,3 +0,0 @@
1
- import { TokenId } from "@talismn/chaindata-provider";
2
- export declare const useTokenRates: () => import("@talismn/token-rates").TokenRatesList;
3
- export declare const useTokenRate: (tokenId?: TokenId) => import("@talismn/token-rates").TokenRates;
@@ -1,68 +0,0 @@
1
- import { ReactNode } from "react";
2
- export { evmErc20TokenId, evmNativeTokenId, subAssetTokenId, subNativeTokenId, subPsp22TokenId, subTokensTokenId, } from "@talismn/chaindata-provider";
3
- export * from "./hooks/useBalances";
4
- export * from "./hooks/useChainConnectors";
5
- export * from "./hooks/useChaindata";
6
- export * from "./hooks/useTokenRates";
7
- export * from "./atoms/allAddresses";
8
- export * from "./atoms/balances";
9
- export * from "./atoms/chainConnectors";
10
- export * from "./atoms/chaindata";
11
- export * from "./atoms/chaindataProvider";
12
- export * from "./atoms/config";
13
- export * from "./atoms/cryptoWaitReady";
14
- export * from "./atoms/tokenRates";
15
- export type BalancesConfig = {
16
- coinsApiUrl?: string;
17
- /** Enables balances fetching for tokens on testnet chains. */
18
- withTestnets?: boolean;
19
- /**
20
- * A list of chain genesisHashes to fetch balances for.
21
- *
22
- * If undefined, balances will be fetched for all chains.
23
- *
24
- * Only applies to built-in chains, custom chains will always fetch balances.
25
- *
26
- * NOTE: This is an allowlist to enable the dapp to disable balances for chains it does not care about.
27
- * Adding a chain here which is not already supported by the library will not automagically begin to fetch balances.
28
- * It will just be ignored.
29
- *
30
- * In a similar vein, if you add testnets here then make sure you've also set the `useTestnets` prop to `true`.
31
- *
32
- * @example
33
- * enabledChains={[
34
- * // polkadot
35
- * "0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3",
36
- * // kusama
37
- * "0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe",
38
- * // rococo
39
- * "0x6408de7737c59c238890533af25896a2c20608d8b380bb01029acb392781063e",
40
- * // westend
41
- * "0xe143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e",
42
- * ]}
43
- */
44
- enabledChains?: string[];
45
- /**
46
- * A list of token ids to fetch balances for.
47
- *
48
- * If undefined, balances will be fetched for all tokens.
49
- *
50
- * If `enabledChains` is also defined, both filters will be applied,
51
- * such that only the intersection of enabledChains and enabledTokens will be fetched.
52
- *
53
- * @example
54
- * enabledTokens={[
55
- * // DOT (polkadot relay chain)
56
- * "polkadot-substrate-native",
57
- * // USDC (polkadot asset hub)
58
- * "polkadot-asset-hub-substrate-assets-1337-usdc",
59
- * // ETH (ethereum mainnet)
60
- * "1-evm-native",
61
- * // GM (gm chain)
62
- * "gm-substrate-tokens-gm",
63
- * ]}
64
- */
65
- enabledTokens?: string[];
66
- children?: ReactNode;
67
- };
68
- export declare const BalancesProvider: ({ coinsApiUrl, withTestnets, enabledChains, enabledTokens, children, }: BalancesConfig) => import("react/jsx-runtime").JSX.Element;
@@ -1,2 +0,0 @@
1
- declare const _default: import("anylogger").Logger<import("anylogger").BaseLevels>;
2
- export default _default;
@@ -1 +0,0 @@
1
- export * from "./declarations/src/index";
@@ -1,351 +0,0 @@
1
- 'use strict';
2
-
3
- var jotai = require('jotai');
4
- var react = require('react');
5
- var tokenRates = require('@talismn/token-rates');
6
- var jsxRuntime = require('react/jsx-runtime');
7
- var chaindataProvider = require('@talismn/chaindata-provider');
8
- var balances = require('@talismn/balances');
9
- var jotaiEffect = require('jotai-effect');
10
- var lodashEs = require('lodash-es');
11
- var chainConnectors = require('@talismn/chain-connectors');
12
- var connectionMeta = require('@talismn/connection-meta');
13
- var util = require('@talismn/util');
14
- var utils = require('jotai/utils');
15
- var rxjs = require('rxjs');
16
- var anylogger = require('anylogger');
17
- var utilCrypto = require('@polkadot/util-crypto');
18
-
19
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
20
-
21
- var anylogger__default = /*#__PURE__*/_interopDefault(anylogger);
22
-
23
- const innerCoinsApiConfigAtom = jotai.atom(tokenRates.DEFAULT_COINSAPI_CONFIG);
24
- const coinsApiConfigAtom = jotai.atom(get => get(innerCoinsApiConfigAtom), (_get, set, options) => set(innerCoinsApiConfigAtom, {
25
- apiUrl: options.apiUrl ?? tokenRates.DEFAULT_COINSAPI_CONFIG.apiUrl
26
- }));
27
- const enableTestnetsAtom = jotai.atom(false);
28
- const enabledChainsAtom = jotai.atom(undefined);
29
- const enabledTokensAtom = jotai.atom(undefined);
30
-
31
- /** Sets the list of addresses for which token balances will be fetched by the balances subscription */
32
- const allAddressesAtom = jotai.atom([]);
33
-
34
- const chaindataProviderAtom = jotai.atom(() => {
35
- return new chaindataProvider.ChaindataProvider({
36
- // TODO pass persistedStorage
37
- });
38
- });
39
- const useSyncSwapsChaindata = () => jotai.useAtom(syncSwapsChaindataAtomEffect);
40
- const syncSwapsChaindataAtomEffect = jotaiEffect.atomEffect(get => {
41
- const chaindataProvider = get(chaindataProviderAtom);
42
-
43
- // keep subscription open when swaps modal is open
44
- const subscription = chaindataProvider.networks$.subscribe();
45
-
46
- // close susbcription when swaps modal closes
47
- return () => subscription.unsubscribe();
48
- });
49
-
50
- const chainConnectorsAtom = jotai.atom(get => {
51
- const chaindataProvider = get(chaindataProviderAtom);
52
- const substrate = new chainConnectors.ChainConnectorDot(chaindataProvider, connectionMeta.connectionMetaDb);
53
- const evm = new chainConnectors.ChainConnectorEth(chaindataProvider);
54
- const solana = new chainConnectors.ChainConnectorSol(chaindataProvider);
55
- return {
56
- substrate,
57
- evm,
58
- solana
59
- };
60
- });
61
-
62
- const balancesProviderAtom = jotai.atom(get => {
63
- return new balances.BalancesProvider(get(chaindataProviderAtom), get(chainConnectorsAtom)) // TODO pass storage
64
- ;
65
- });
66
-
67
- const chaindataAtom = utils.atomWithObservable(get => {
68
- return rxjs.combineLatest({
69
- networks: get(chaindataProviderAtom).networks$,
70
- tokens: get(chaindataProviderAtom).tokens$
71
- }).pipe(util.firstThenDebounce(1_000));
72
- });
73
- const filteredChaindataAtom = jotai.atom(async get => {
74
- const enabledNetworkIds = get(enabledChainsAtom);
75
- const enabledTokenIds = get(enabledTokensAtom);
76
- const enableTestnets = get(enableTestnetsAtom);
77
- const chaindata = await get(chaindataAtom);
78
- const networks = chaindata.networks.filter(n => (enabledNetworkIds?.includes(n.id) || n.isDefault) && (enableTestnets || !n.isTestnet));
79
- const networkById = lodashEs.keyBy(networks, n => n.id);
80
- const tokens = chaindata.tokens.filter(token => (enabledTokenIds?.includes(token.id) || token.isDefault) && networkById[token.networkId]);
81
- return {
82
- networks,
83
- tokens
84
- };
85
- });
86
- const tokensAtom = jotai.atom(async get => {
87
- const chaindata = await get(filteredChaindataAtom);
88
- return chaindata.tokens;
89
- });
90
- const networksAtom = jotai.atom(async get => {
91
- const chaindata = await get(filteredChaindataAtom);
92
- return chaindata.networks;
93
- });
94
-
95
- var packageJson = {
96
- name: "@talismn/balances-react"};
97
-
98
- var log = anylogger__default.default(packageJson.name);
99
-
100
- const tokenRatesAtom = jotai.atom(async get => {
101
- // runs a timer to keep tokenRates up to date
102
- get(tokenRatesFetcherAtomEffect);
103
- return (await get(tokenRatesDbAtom)).tokenRates;
104
- });
105
-
106
- // TODO: Persist to storage
107
- const tokenRates$ = new rxjs.ReplaySubject(1);
108
- const tokenRatesDbAtom = utils.atomWithObservable(() => {
109
- tokenRates.tryToDeleteOldTokenRatesDb();
110
- return tokenRates$.asObservable();
111
- });
112
- const tokenRatesFetcherAtomEffect = jotaiEffect.atomEffect(get => {
113
- // lets us tear down the existing timer when the effect is restarted
114
- const abort = new AbortController();
115
-
116
- // we have to get these synchronously so that jotai knows to restart our timer when they change
117
- const coinsApiConfig = get(coinsApiConfigAtom);
118
- const tokensPromise = get(tokensAtom);
119
- (async () => {
120
- const tokensById = lodashEs.keyBy(await tokensPromise, "id");
121
- const loopMs = 300_000; // 300_000ms = 300s = 5 minutes
122
- const retryTimeout = 5_000; // 5_000ms = 5 seconds
123
-
124
- const hydrate = async () => {
125
- try {
126
- if (abort.signal.aborted) return; // don't fetch if aborted
127
- const tokenRates$1 = await tokenRates.fetchTokenRates(tokensById, tokenRates.ALL_CURRENCY_IDS, coinsApiConfig);
128
- const putTokenRates = {
129
- tokenRates: tokenRates$1
130
- };
131
- if (abort.signal.aborted) return; // don't insert into db if aborted
132
- tokenRates$.next(putTokenRates);
133
- if (abort.signal.aborted) return; // don't schedule next loop if aborted
134
- setTimeout(hydrate, loopMs);
135
- } catch (error) {
136
- const retrying = !abort.signal.aborted;
137
- const messageParts = ["Failed to fetch tokenRates", retrying && `retrying in ${Math.round(retryTimeout / 1000)} seconds`, !retrying && `giving up (timer no longer needed)`].filter(util.isTruthy);
138
- log.error(messageParts.join(", "), error);
139
- if (util.isAbortError(error)) return; // don't schedule retry if aborted
140
- setTimeout(hydrate, retryTimeout);
141
- }
142
- };
143
-
144
- // launch the loop
145
- hydrate();
146
- })();
147
- return () => abort.abort("Unsubscribed");
148
- });
149
-
150
- const addressesByTokenIdAtom = jotai.atom(async get => {
151
- const [tokens, addresses] = await Promise.all([get(tokensAtom), get(allAddressesAtom)]);
152
- return lodashEs.fromPairs(tokens.map(token => [token.id, addresses]));
153
- });
154
- const rawBalancesAtom = jotai.atom([]);
155
- const subscribeBalancesAtom = jotaiEffect.atomEffect((get, set) => {
156
- const unsub = (async () => {
157
- const balancesProvider = get(balancesProviderAtom);
158
- const addressesByTokenId = await get(addressesByTokenIdAtom);
159
- const sub = balancesProvider.getBalances$(addressesByTokenId).subscribe(balances => {
160
- set(rawBalancesAtom, balances.balances);
161
- });
162
- return () => {
163
- return sub.unsubscribe();
164
- };
165
- })();
166
- return () => {
167
- unsub.then(unsubscribe => unsubscribe());
168
- };
169
- });
170
- const balancesHydrateDataAtom = jotai.atom(async get => {
171
- const [chaindata, tokenRates] = await Promise.all([get(chaindataAtom), get(tokenRatesAtom)]);
172
- const networksById = lodashEs.keyBy(chaindata.networks, "id");
173
- const tokensById = lodashEs.keyBy(chaindata.tokens, "id");
174
- return {
175
- networks: networksById,
176
- tokens: tokensById,
177
- tokenRates
178
- };
179
- });
180
- const balancesAtom = jotai.atom(async get => {
181
- // subscribe to balancesProvider getBalance with addressesByTokenIdAtom as param
182
- get(subscribeBalancesAtom);
183
- const hydrate = await get(balancesHydrateDataAtom);
184
- const rawBalances = get(rawBalancesAtom);
185
- return new balances.Balances(rawBalances, hydrate);
186
- });
187
-
188
- const useSetBalancesAddresses = addresses => {
189
- const setAllAddresses = jotai.useSetAtom(allAddressesAtom);
190
- react.useEffect(() => {
191
- setAllAddresses(a => JSON.stringify(a) === JSON.stringify(addresses) ? a : addresses);
192
- }, [addresses, setAllAddresses]);
193
- };
194
-
195
- /**
196
- * @name useBalances
197
- * @description Hook to get the current balances state.
198
- * @param persistBackend an optional BalancesPersistBackend backend to use for persisting the balances state. By default, indexedDB is used.
199
- * @returns a Balances object containing the current balances state.
200
- */
201
-
202
- const useBalances = () => {
203
- return jotai.useAtomValue(balancesAtom);
204
- };
205
-
206
- // TODO: Extract to shared definition between extension and @talismn/balances-react
207
-
208
- /**
209
- * Given a collection of `Balances`, this hook returns a `BalancesStatus` summary for the collection.
210
- *
211
- * @param balances The collection of balances to get the status from.
212
- * @returns An instance of `BalancesStatus` which represents the status of the balances collection.
213
-
214
- */
215
- const useBalancesStatus = balances => react.useMemo(() => {
216
- // stale
217
- const staleChains = getStaleChains(balances);
218
- if (staleChains.length > 0) return {
219
- status: "stale",
220
- staleChains
221
- };
222
-
223
- // fetching
224
- const hasCachedBalances = balances.each.some(b => b.status === "cache");
225
- if (hasCachedBalances) return {
226
- status: "fetching"
227
- };
228
-
229
- // live
230
- return {
231
- status: "live"
232
- };
233
- }, [balances]);
234
- const getStaleChains = balances => [...new Set(balances.each.filter(b => b.status === "stale").map(b => b.network?.name ?? b.networkId ?? "Unknown"))];
235
-
236
- const useChainConnectors = () => jotai.useAtomValue(chainConnectorsAtom);
237
-
238
- const useChaindataProvider = () => jotai.useAtomValue(chaindataProviderAtom);
239
- const useChaindata = () => jotai.useAtomValue(chaindataAtom);
240
- const useNetworks = () => useChaindata().networks;
241
- const useNetworksById = () => {
242
- const {
243
- networks
244
- } = useChaindata();
245
- return react.useMemo(() => lodashEs.keyBy(networks, n => n.id), [networks]);
246
- };
247
- const useNetwork = networkId => {
248
- const networksById = useNetworksById();
249
- return networksById[networkId ?? ""] ?? null;
250
- };
251
- const useTokens = () => useChaindata().tokens;
252
- const useTokensById = () => {
253
- const {
254
- tokens
255
- } = useChaindata();
256
- return react.useMemo(() => lodashEs.keyBy(tokens, t => t.id), [tokens]);
257
- };
258
- const useToken = tokenId => {
259
- const tokensById = useTokensById();
260
- return tokensById[tokenId ?? ""] ?? null;
261
- };
262
-
263
- const useTokenRates = () => jotai.useAtomValue(tokenRatesAtom);
264
- const useTokenRate = tokenId => useTokenRates()[tokenId ?? ""] ?? undefined;
265
-
266
- const cryptoWaitReadyAtom = jotai.atom(async () => await utilCrypto.cryptoWaitReady());
267
-
268
- const BalancesProvider = ({
269
- coinsApiUrl,
270
- withTestnets,
271
- enabledChains,
272
- enabledTokens,
273
- children
274
- }) => {
275
- const setCoinsApiConfig = jotai.useSetAtom(coinsApiConfigAtom);
276
- react.useEffect(() => {
277
- setCoinsApiConfig({
278
- apiUrl: coinsApiUrl
279
- });
280
- }, [coinsApiUrl, setCoinsApiConfig]);
281
- const setEnableTestnets = jotai.useSetAtom(enableTestnetsAtom);
282
- react.useEffect(() => {
283
- setEnableTestnets(withTestnets ?? false);
284
- }, [setEnableTestnets, withTestnets]);
285
- const setEnabledChains = jotai.useSetAtom(enabledChainsAtom);
286
- react.useEffect(() => {
287
- setEnabledChains(enabledChains);
288
- }, [enabledChains, setEnabledChains]);
289
- const setEnabledTokens = jotai.useSetAtom(enabledTokensAtom);
290
- react.useEffect(() => {
291
- setEnabledTokens(enabledTokens);
292
- }, [enabledTokens, setEnabledTokens]);
293
- return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
294
- children: children
295
- });
296
- };
297
-
298
- Object.defineProperty(exports, "evmErc20TokenId", {
299
- enumerable: true,
300
- get: function () { return chaindataProvider.evmErc20TokenId; }
301
- });
302
- Object.defineProperty(exports, "evmNativeTokenId", {
303
- enumerable: true,
304
- get: function () { return chaindataProvider.evmNativeTokenId; }
305
- });
306
- Object.defineProperty(exports, "subAssetTokenId", {
307
- enumerable: true,
308
- get: function () { return chaindataProvider.subAssetTokenId; }
309
- });
310
- Object.defineProperty(exports, "subNativeTokenId", {
311
- enumerable: true,
312
- get: function () { return chaindataProvider.subNativeTokenId; }
313
- });
314
- Object.defineProperty(exports, "subPsp22TokenId", {
315
- enumerable: true,
316
- get: function () { return chaindataProvider.subPsp22TokenId; }
317
- });
318
- Object.defineProperty(exports, "subTokensTokenId", {
319
- enumerable: true,
320
- get: function () { return chaindataProvider.subTokensTokenId; }
321
- });
322
- exports.BalancesProvider = BalancesProvider;
323
- exports.allAddressesAtom = allAddressesAtom;
324
- exports.balancesAtom = balancesAtom;
325
- exports.chainConnectorsAtom = chainConnectorsAtom;
326
- exports.chaindataAtom = chaindataAtom;
327
- exports.chaindataProviderAtom = chaindataProviderAtom;
328
- exports.coinsApiConfigAtom = coinsApiConfigAtom;
329
- exports.cryptoWaitReadyAtom = cryptoWaitReadyAtom;
330
- exports.enableTestnetsAtom = enableTestnetsAtom;
331
- exports.enabledChainsAtom = enabledChainsAtom;
332
- exports.enabledTokensAtom = enabledTokensAtom;
333
- exports.getStaleChains = getStaleChains;
334
- exports.networksAtom = networksAtom;
335
- exports.tokenRatesAtom = tokenRatesAtom;
336
- exports.tokensAtom = tokensAtom;
337
- exports.useBalances = useBalances;
338
- exports.useBalancesStatus = useBalancesStatus;
339
- exports.useChainConnectors = useChainConnectors;
340
- exports.useChaindata = useChaindata;
341
- exports.useChaindataProvider = useChaindataProvider;
342
- exports.useNetwork = useNetwork;
343
- exports.useNetworks = useNetworks;
344
- exports.useNetworksById = useNetworksById;
345
- exports.useSetBalancesAddresses = useSetBalancesAddresses;
346
- exports.useSyncSwapsChaindata = useSyncSwapsChaindata;
347
- exports.useToken = useToken;
348
- exports.useTokenRate = useTokenRate;
349
- exports.useTokenRates = useTokenRates;
350
- exports.useTokens = useTokens;
351
- exports.useTokensById = useTokensById;
@@ -1,7 +0,0 @@
1
- 'use strict';
2
-
3
- if (process.env.NODE_ENV === "production") {
4
- module.exports = require("./talismn-balances-react.cjs.prod.js");
5
- } else {
6
- module.exports = require("./talismn-balances-react.cjs.dev.js");
7
- }