@talismn/balances-react 0.0.0-pr660-20230327112704 → 0.0.0-pr660-20230328111733

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @talismn/balances-react
2
2
 
3
- ## 0.0.0-pr660-20230327112704
3
+ ## 0.0.0-pr660-20230328111733
4
4
 
5
5
  ### Minor Changes
6
6
 
@@ -17,13 +17,13 @@
17
17
  - Updated dependencies [79f6ccf6]
18
18
  - Updated dependencies [6643a4e4]
19
19
  - Updated dependencies [c24dc1fb]
20
- - @talismn/chain-connector@0.0.0-pr660-20230327112704
21
- - @talismn/connection-meta@0.0.0-pr660-20230327112704
22
- - @talismn/balances@0.0.0-pr660-20230327112704
23
- - @talismn/token-rates@0.0.0-pr660-20230327112704
24
- - @talismn/chaindata-provider-extension@0.0.0-pr660-20230327112704
25
- - @talismn/chaindata-provider@0.0.0-pr660-20230327112704
26
- - @talismn/chain-connector-evm@0.0.0-pr660-20230327112704
20
+ - @talismn/chain-connector@0.0.0-pr660-20230328111733
21
+ - @talismn/connection-meta@0.0.0-pr660-20230328111733
22
+ - @talismn/balances@0.0.0-pr660-20230328111733
23
+ - @talismn/token-rates@0.0.0-pr660-20230328111733
24
+ - @talismn/chaindata-provider-extension@0.0.0-pr660-20230328111733
25
+ - @talismn/chaindata-provider@0.0.0-pr660-20230328111733
26
+ - @talismn/chain-connector-evm@0.0.0-pr660-20230328111733
27
27
 
28
28
  ## 0.3.3
29
29
 
@@ -17,6 +17,9 @@ type DbCache = {
17
17
  tokensWithoutTestnetsMap: Record<TokenId, Token>;
18
18
  tokenRatesMap: Record<TokenId, TokenRates>;
19
19
  balances: BalanceJson[];
20
+ balancesMeta: {
21
+ subscriptionId: string | undefined;
22
+ };
20
23
  };
21
24
  export declare const DbCacheProvider: import("react").FC<{
22
25
  children?: import("react").ReactNode;
@@ -117,9 +117,12 @@ const DEFAULT_VALUE = {
117
117
  tokensWithTestnetsMap: {},
118
118
  tokensWithoutTestnetsMap: {},
119
119
  tokenRatesMap: {},
120
- balances: []
120
+ balances: [],
121
+ balancesMeta: {
122
+ subscriptionId: undefined
123
+ }
121
124
  };
122
- const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, allBalances) => {
125
+ const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, allBalances, meta) => {
123
126
  if (!chainsMap || !evmNetworksMap || !tokensMap || !tokenRates || !allBalances) return DEFAULT_VALUE;
124
127
 
125
128
  // BEGIN: temp hack to indicate that
@@ -155,6 +158,11 @@ const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, al
155
158
 
156
159
  // return only balances for which we have a token
157
160
  const balances = allBalances.filter(b => tokensWithTestnetsMap[b.tokenId]);
161
+ const balancesMeta = {
162
+ subscriptionId: meta?.find(({
163
+ id
164
+ }) => id === "subscriptionId")?.value
165
+ };
158
166
  return {
159
167
  chainsWithTestnets,
160
168
  chainsWithoutTestnets,
@@ -169,7 +177,8 @@ const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, al
169
177
  tokensWithTestnetsMap,
170
178
  tokensWithoutTestnetsMap,
171
179
  tokenRatesMap,
172
- balances
180
+ balances,
181
+ balancesMeta
173
182
  };
174
183
  };
175
184
  const useDbCacheProvider = () => {
@@ -179,28 +188,29 @@ const useDbCacheProvider = () => {
179
188
  const tokenList = dexieReactHooks.useLiveQuery(() => chaindataProvider?.tokens(), [chaindataProvider]);
180
189
  const tokenRates$1 = dexieReactHooks.useLiveQuery(() => tokenRates.db.tokenRates.toArray(), []);
181
190
  const rawBalances = dexieReactHooks.useLiveQuery(() => balances.db.balances.toArray(), []);
191
+ const meta = dexieReactHooks.useLiveQuery(() => balances.db.meta.toArray(), []);
182
192
  const [dbData, setDbData] = react.useState(DEFAULT_VALUE);
183
193
 
184
194
  // debounce every 500ms to prevent hammering UI with updates
185
195
  reactUse.useDebounce(() => {
186
- setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances));
187
- }, 500, [chainList, evmNetworkList, tokenList, rawBalances, tokenRates$1]);
196
+ setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances, meta));
197
+ }, 500, [chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances, meta]);
188
198
  const refInitialized = react.useRef(false);
189
199
 
190
200
  // force an update as soon as all datasources are fetched, so UI can display data ASAP
191
201
  react.useEffect(() => {
192
- if (!refInitialized.current && chainList && evmNetworkList && tokenList && tokenRates$1 && rawBalances) {
193
- setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances));
202
+ if (!refInitialized.current && chainList && evmNetworkList && tokenList && tokenRates$1 && rawBalances && meta) {
203
+ setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances, meta));
194
204
  refInitialized.current = true;
195
205
  }
196
- }, [chainList, evmNetworkList, rawBalances, tokenList, tokenRates$1]);
206
+ }, [chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances, meta]);
197
207
  return dbData;
198
208
  };
199
209
  const [DbCacheProvider, useDbCache] = provideContext(useDbCacheProvider);
200
210
 
201
211
  var packageJson = {
202
212
  name: "@talismn/balances-react",
203
- version: "0.0.0-pr660-20230327112704",
213
+ version: "0.0.0-pr660-20230328111733",
204
214
  author: "Talisman",
205
215
  homepage: "https://talisman.xyz",
206
216
  license: "UNLICENSED",
@@ -503,10 +513,29 @@ const subscribeBalances = (tokens, addresses, balanceModules) => {
503
513
  id
504
514
  }) => id);
505
515
  const addressesByToken = Object.fromEntries(tokenIds.map(tokenId => [tokenId, addresses]));
516
+ const subscriptionId = Date.now().toString();
517
+ balances.db.meta.put({
518
+ id: "subscriptionId",
519
+ value: subscriptionId
520
+ });
521
+
522
+ // TODO: Create subscriptions in a service worker, where we can detect page closes
523
+ // and therefore reliably delete the subscriptionId when the user closes our dapp
524
+ //
525
+ // For more information, check out https://developer.chrome.com/blog/page-lifecycle-api/#faqs
526
+ // and scroll down to:
527
+ // - `What is the back/forward cache?`, and
528
+ // - `If I can't run asynchronous APIs in the frozen or terminated states, how can I save data to IndexedDB?
529
+ //
530
+ // For now, we'll just last-ditch remove the subscriptionId (it works surprisingly well!) in the beforeunload event
531
+ window.onbeforeunload = () => {
532
+ balances.db.meta.delete("subscriptionId");
533
+ };
506
534
  const updateDb = balances$1 => {
507
535
  const putBalances = Object.entries(balances$1.toJSON()).map(([id, balance]) => ({
508
536
  id,
509
- ...balance
537
+ ...balance,
538
+ status: balances.BalanceStatusLive(subscriptionId)
510
539
  }));
511
540
  balances.db.transaction("rw", balances.db.balances, async () => await balances.db.balances.bulkPut(putBalances));
512
541
  };
@@ -525,7 +554,7 @@ const subscribeBalances = (tokens, addresses, balanceModules) => {
525
554
  const unsub = balances.balances(balanceModule, addressesByModuleToken, (error, balances$1) => {
526
555
  // log errors
527
556
  if (error) {
528
- if (error?.type === "STALE_RPC_ERROR") return balances.db.balances.where({
557
+ if (error?.type === "STALE_RPC_ERROR" || error?.type === "WEBSOCKET_ALLOCATION_EXHAUSTED_ERROR") return balances.db.balances.where({
529
558
  source: balanceModule.type,
530
559
  chainId: error.chainId
531
560
  }).filter(balance => {
@@ -548,15 +577,7 @@ const subscribeBalances = (tokens, addresses, balanceModules) => {
548
577
  unsub.then(unsubscribe => {
549
578
  setTimeout(unsubscribe, 2_000);
550
579
  });
551
- balances.db.balances.where({
552
- source: balanceModule.type
553
- }).filter(balance => {
554
- if (!Object.keys(addressesByModuleToken).includes(balance.tokenId)) return false;
555
- if (!addressesByModuleToken[balance.tokenId].includes(balance.address)) return false;
556
- return true;
557
- }).modify({
558
- status: "cache"
559
- });
580
+ balances.db.meta.delete("subscriptionId");
560
581
  };
561
582
  });
562
583
  const unsubscribeAll = () => {
@@ -642,10 +663,11 @@ function useBalances(addressesByToken) {
642
663
  useDbCacheBalancesSubscription();
643
664
  const balanceModules = useBalanceModules();
644
665
  const {
645
- balances: balances$1
666
+ balances: balances$1,
667
+ balancesMeta
646
668
  } = useDbCache();
647
669
  const hydrate = useBalancesHydrate();
648
- return react.useMemo(() => new balances.Balances(balances$1.filter(balance => {
670
+ return react.useMemo(() => new balances.Balances(balances.deriveStatuses(balancesMeta.subscriptionId, balances$1.filter(balance => {
649
671
  // check that this balance is included in our queried balance modules
650
672
  if (!balanceModules.map(({
651
673
  type
@@ -662,9 +684,9 @@ function useBalances(addressesByToken) {
662
684
 
663
685
  // keep this balance
664
686
  return true;
665
- }),
687
+ })),
666
688
  // hydrate balance chains, evmNetworks, tokens and tokenRates
667
- hydrate), [balances$1, hydrate, balanceModules, addressesByToken]);
689
+ hydrate), [balancesMeta.subscriptionId, balances$1, hydrate, balanceModules, addressesByToken]);
668
690
  }
669
691
 
670
692
  /**
@@ -117,9 +117,12 @@ const DEFAULT_VALUE = {
117
117
  tokensWithTestnetsMap: {},
118
118
  tokensWithoutTestnetsMap: {},
119
119
  tokenRatesMap: {},
120
- balances: []
120
+ balances: [],
121
+ balancesMeta: {
122
+ subscriptionId: undefined
123
+ }
121
124
  };
122
- const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, allBalances) => {
125
+ const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, allBalances, meta) => {
123
126
  if (!chainsMap || !evmNetworksMap || !tokensMap || !tokenRates || !allBalances) return DEFAULT_VALUE;
124
127
 
125
128
  // BEGIN: temp hack to indicate that
@@ -155,6 +158,11 @@ const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, al
155
158
 
156
159
  // return only balances for which we have a token
157
160
  const balances = allBalances.filter(b => tokensWithTestnetsMap[b.tokenId]);
161
+ const balancesMeta = {
162
+ subscriptionId: meta?.find(({
163
+ id
164
+ }) => id === "subscriptionId")?.value
165
+ };
158
166
  return {
159
167
  chainsWithTestnets,
160
168
  chainsWithoutTestnets,
@@ -169,7 +177,8 @@ const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, al
169
177
  tokensWithTestnetsMap,
170
178
  tokensWithoutTestnetsMap,
171
179
  tokenRatesMap,
172
- balances
180
+ balances,
181
+ balancesMeta
173
182
  };
174
183
  };
175
184
  const useDbCacheProvider = () => {
@@ -179,28 +188,29 @@ const useDbCacheProvider = () => {
179
188
  const tokenList = dexieReactHooks.useLiveQuery(() => chaindataProvider?.tokens(), [chaindataProvider]);
180
189
  const tokenRates$1 = dexieReactHooks.useLiveQuery(() => tokenRates.db.tokenRates.toArray(), []);
181
190
  const rawBalances = dexieReactHooks.useLiveQuery(() => balances.db.balances.toArray(), []);
191
+ const meta = dexieReactHooks.useLiveQuery(() => balances.db.meta.toArray(), []);
182
192
  const [dbData, setDbData] = react.useState(DEFAULT_VALUE);
183
193
 
184
194
  // debounce every 500ms to prevent hammering UI with updates
185
195
  reactUse.useDebounce(() => {
186
- setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances));
187
- }, 500, [chainList, evmNetworkList, tokenList, rawBalances, tokenRates$1]);
196
+ setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances, meta));
197
+ }, 500, [chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances, meta]);
188
198
  const refInitialized = react.useRef(false);
189
199
 
190
200
  // force an update as soon as all datasources are fetched, so UI can display data ASAP
191
201
  react.useEffect(() => {
192
- if (!refInitialized.current && chainList && evmNetworkList && tokenList && tokenRates$1 && rawBalances) {
193
- setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances));
202
+ if (!refInitialized.current && chainList && evmNetworkList && tokenList && tokenRates$1 && rawBalances && meta) {
203
+ setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances, meta));
194
204
  refInitialized.current = true;
195
205
  }
196
- }, [chainList, evmNetworkList, rawBalances, tokenList, tokenRates$1]);
206
+ }, [chainList, evmNetworkList, tokenList, tokenRates$1, rawBalances, meta]);
197
207
  return dbData;
198
208
  };
199
209
  const [DbCacheProvider, useDbCache] = provideContext(useDbCacheProvider);
200
210
 
201
211
  var packageJson = {
202
212
  name: "@talismn/balances-react",
203
- version: "0.0.0-pr660-20230327112704",
213
+ version: "0.0.0-pr660-20230328111733",
204
214
  author: "Talisman",
205
215
  homepage: "https://talisman.xyz",
206
216
  license: "UNLICENSED",
@@ -503,10 +513,29 @@ const subscribeBalances = (tokens, addresses, balanceModules) => {
503
513
  id
504
514
  }) => id);
505
515
  const addressesByToken = Object.fromEntries(tokenIds.map(tokenId => [tokenId, addresses]));
516
+ const subscriptionId = Date.now().toString();
517
+ balances.db.meta.put({
518
+ id: "subscriptionId",
519
+ value: subscriptionId
520
+ });
521
+
522
+ // TODO: Create subscriptions in a service worker, where we can detect page closes
523
+ // and therefore reliably delete the subscriptionId when the user closes our dapp
524
+ //
525
+ // For more information, check out https://developer.chrome.com/blog/page-lifecycle-api/#faqs
526
+ // and scroll down to:
527
+ // - `What is the back/forward cache?`, and
528
+ // - `If I can't run asynchronous APIs in the frozen or terminated states, how can I save data to IndexedDB?
529
+ //
530
+ // For now, we'll just last-ditch remove the subscriptionId (it works surprisingly well!) in the beforeunload event
531
+ window.onbeforeunload = () => {
532
+ balances.db.meta.delete("subscriptionId");
533
+ };
506
534
  const updateDb = balances$1 => {
507
535
  const putBalances = Object.entries(balances$1.toJSON()).map(([id, balance]) => ({
508
536
  id,
509
- ...balance
537
+ ...balance,
538
+ status: balances.BalanceStatusLive(subscriptionId)
510
539
  }));
511
540
  balances.db.transaction("rw", balances.db.balances, async () => await balances.db.balances.bulkPut(putBalances));
512
541
  };
@@ -525,7 +554,7 @@ const subscribeBalances = (tokens, addresses, balanceModules) => {
525
554
  const unsub = balances.balances(balanceModule, addressesByModuleToken, (error, balances$1) => {
526
555
  // log errors
527
556
  if (error) {
528
- if (error?.type === "STALE_RPC_ERROR") return balances.db.balances.where({
557
+ if (error?.type === "STALE_RPC_ERROR" || error?.type === "WEBSOCKET_ALLOCATION_EXHAUSTED_ERROR") return balances.db.balances.where({
529
558
  source: balanceModule.type,
530
559
  chainId: error.chainId
531
560
  }).filter(balance => {
@@ -548,15 +577,7 @@ const subscribeBalances = (tokens, addresses, balanceModules) => {
548
577
  unsub.then(unsubscribe => {
549
578
  setTimeout(unsubscribe, 2_000);
550
579
  });
551
- balances.db.balances.where({
552
- source: balanceModule.type
553
- }).filter(balance => {
554
- if (!Object.keys(addressesByModuleToken).includes(balance.tokenId)) return false;
555
- if (!addressesByModuleToken[balance.tokenId].includes(balance.address)) return false;
556
- return true;
557
- }).modify({
558
- status: "cache"
559
- });
580
+ balances.db.meta.delete("subscriptionId");
560
581
  };
561
582
  });
562
583
  const unsubscribeAll = () => {
@@ -642,10 +663,11 @@ function useBalances(addressesByToken) {
642
663
  useDbCacheBalancesSubscription();
643
664
  const balanceModules = useBalanceModules();
644
665
  const {
645
- balances: balances$1
666
+ balances: balances$1,
667
+ balancesMeta
646
668
  } = useDbCache();
647
669
  const hydrate = useBalancesHydrate();
648
- return react.useMemo(() => new balances.Balances(balances$1.filter(balance => {
670
+ return react.useMemo(() => new balances.Balances(balances.deriveStatuses(balancesMeta.subscriptionId, balances$1.filter(balance => {
649
671
  // check that this balance is included in our queried balance modules
650
672
  if (!balanceModules.map(({
651
673
  type
@@ -662,9 +684,9 @@ function useBalances(addressesByToken) {
662
684
 
663
685
  // keep this balance
664
686
  return true;
665
- }),
687
+ })),
666
688
  // hydrate balance chains, evmNetworks, tokens and tokenRates
667
- hydrate), [balances$1, hydrate, balanceModules, addressesByToken]);
689
+ hydrate), [balancesMeta.subscriptionId, balances$1, hydrate, balanceModules, addressesByToken]);
668
690
  }
669
691
 
670
692
  /**
@@ -4,7 +4,7 @@ import { ChainConnector } from '@talismn/chain-connector';
4
4
  import { ChainConnectorEvm } from '@talismn/chain-connector-evm';
5
5
  import { connectionMetaDb } from '@talismn/connection-meta';
6
6
  import { ChaindataProviderExtension } from '@talismn/chaindata-provider-extension';
7
- import { db as db$1, balances, Balances } from '@talismn/balances';
7
+ import { db as db$1, balances, BalanceStatusLive, Balances, deriveStatuses } from '@talismn/balances';
8
8
  import { db, fetchTokenRates } from '@talismn/token-rates';
9
9
  import { useLiveQuery } from 'dexie-react-hooks';
10
10
  import { useDebounce } from 'react-use';
@@ -108,9 +108,12 @@ const DEFAULT_VALUE = {
108
108
  tokensWithTestnetsMap: {},
109
109
  tokensWithoutTestnetsMap: {},
110
110
  tokenRatesMap: {},
111
- balances: []
111
+ balances: [],
112
+ balancesMeta: {
113
+ subscriptionId: undefined
114
+ }
112
115
  };
113
- const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, allBalances) => {
116
+ const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, allBalances, meta) => {
114
117
  if (!chainsMap || !evmNetworksMap || !tokensMap || !tokenRates || !allBalances) return DEFAULT_VALUE;
115
118
 
116
119
  // BEGIN: temp hack to indicate that
@@ -146,6 +149,11 @@ const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, al
146
149
 
147
150
  // return only balances for which we have a token
148
151
  const balances = allBalances.filter(b => tokensWithTestnetsMap[b.tokenId]);
152
+ const balancesMeta = {
153
+ subscriptionId: meta?.find(({
154
+ id
155
+ }) => id === "subscriptionId")?.value
156
+ };
149
157
  return {
150
158
  chainsWithTestnets,
151
159
  chainsWithoutTestnets,
@@ -160,7 +168,8 @@ const consolidateDbCache = (chainsMap, evmNetworksMap, tokensMap, tokenRates, al
160
168
  tokensWithTestnetsMap,
161
169
  tokensWithoutTestnetsMap,
162
170
  tokenRatesMap,
163
- balances
171
+ balances,
172
+ balancesMeta
164
173
  };
165
174
  };
166
175
  const useDbCacheProvider = () => {
@@ -170,28 +179,29 @@ const useDbCacheProvider = () => {
170
179
  const tokenList = useLiveQuery(() => chaindataProvider?.tokens(), [chaindataProvider]);
171
180
  const tokenRates = useLiveQuery(() => db.tokenRates.toArray(), []);
172
181
  const rawBalances = useLiveQuery(() => db$1.balances.toArray(), []);
182
+ const meta = useLiveQuery(() => db$1.meta.toArray(), []);
173
183
  const [dbData, setDbData] = useState(DEFAULT_VALUE);
174
184
 
175
185
  // debounce every 500ms to prevent hammering UI with updates
176
186
  useDebounce(() => {
177
- setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates, rawBalances));
178
- }, 500, [chainList, evmNetworkList, tokenList, rawBalances, tokenRates]);
187
+ setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates, rawBalances, meta));
188
+ }, 500, [chainList, evmNetworkList, tokenList, tokenRates, rawBalances, meta]);
179
189
  const refInitialized = useRef(false);
180
190
 
181
191
  // force an update as soon as all datasources are fetched, so UI can display data ASAP
182
192
  useEffect(() => {
183
- if (!refInitialized.current && chainList && evmNetworkList && tokenList && tokenRates && rawBalances) {
184
- setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates, rawBalances));
193
+ if (!refInitialized.current && chainList && evmNetworkList && tokenList && tokenRates && rawBalances && meta) {
194
+ setDbData(consolidateDbCache(chainList, evmNetworkList, tokenList, tokenRates, rawBalances, meta));
185
195
  refInitialized.current = true;
186
196
  }
187
- }, [chainList, evmNetworkList, rawBalances, tokenList, tokenRates]);
197
+ }, [chainList, evmNetworkList, tokenList, tokenRates, rawBalances, meta]);
188
198
  return dbData;
189
199
  };
190
200
  const [DbCacheProvider, useDbCache] = provideContext(useDbCacheProvider);
191
201
 
192
202
  var packageJson = {
193
203
  name: "@talismn/balances-react",
194
- version: "0.0.0-pr660-20230327112704",
204
+ version: "0.0.0-pr660-20230328111733",
195
205
  author: "Talisman",
196
206
  homepage: "https://talisman.xyz",
197
207
  license: "UNLICENSED",
@@ -494,10 +504,29 @@ const subscribeBalances = (tokens, addresses, balanceModules) => {
494
504
  id
495
505
  }) => id);
496
506
  const addressesByToken = Object.fromEntries(tokenIds.map(tokenId => [tokenId, addresses]));
507
+ const subscriptionId = Date.now().toString();
508
+ db$1.meta.put({
509
+ id: "subscriptionId",
510
+ value: subscriptionId
511
+ });
512
+
513
+ // TODO: Create subscriptions in a service worker, where we can detect page closes
514
+ // and therefore reliably delete the subscriptionId when the user closes our dapp
515
+ //
516
+ // For more information, check out https://developer.chrome.com/blog/page-lifecycle-api/#faqs
517
+ // and scroll down to:
518
+ // - `What is the back/forward cache?`, and
519
+ // - `If I can't run asynchronous APIs in the frozen or terminated states, how can I save data to IndexedDB?
520
+ //
521
+ // For now, we'll just last-ditch remove the subscriptionId (it works surprisingly well!) in the beforeunload event
522
+ window.onbeforeunload = () => {
523
+ db$1.meta.delete("subscriptionId");
524
+ };
497
525
  const updateDb = balances => {
498
526
  const putBalances = Object.entries(balances.toJSON()).map(([id, balance]) => ({
499
527
  id,
500
- ...balance
528
+ ...balance,
529
+ status: BalanceStatusLive(subscriptionId)
501
530
  }));
502
531
  db$1.transaction("rw", db$1.balances, async () => await db$1.balances.bulkPut(putBalances));
503
532
  };
@@ -516,7 +545,7 @@ const subscribeBalances = (tokens, addresses, balanceModules) => {
516
545
  const unsub = balances(balanceModule, addressesByModuleToken, (error, balances) => {
517
546
  // log errors
518
547
  if (error) {
519
- if (error?.type === "STALE_RPC_ERROR") return db$1.balances.where({
548
+ if (error?.type === "STALE_RPC_ERROR" || error?.type === "WEBSOCKET_ALLOCATION_EXHAUSTED_ERROR") return db$1.balances.where({
520
549
  source: balanceModule.type,
521
550
  chainId: error.chainId
522
551
  }).filter(balance => {
@@ -539,15 +568,7 @@ const subscribeBalances = (tokens, addresses, balanceModules) => {
539
568
  unsub.then(unsubscribe => {
540
569
  setTimeout(unsubscribe, 2_000);
541
570
  });
542
- db$1.balances.where({
543
- source: balanceModule.type
544
- }).filter(balance => {
545
- if (!Object.keys(addressesByModuleToken).includes(balance.tokenId)) return false;
546
- if (!addressesByModuleToken[balance.tokenId].includes(balance.address)) return false;
547
- return true;
548
- }).modify({
549
- status: "cache"
550
- });
571
+ db$1.meta.delete("subscriptionId");
551
572
  };
552
573
  });
553
574
  const unsubscribeAll = () => {
@@ -633,10 +654,11 @@ function useBalances(addressesByToken) {
633
654
  useDbCacheBalancesSubscription();
634
655
  const balanceModules = useBalanceModules();
635
656
  const {
636
- balances
657
+ balances,
658
+ balancesMeta
637
659
  } = useDbCache();
638
660
  const hydrate = useBalancesHydrate();
639
- return useMemo(() => new Balances(balances.filter(balance => {
661
+ return useMemo(() => new Balances(deriveStatuses(balancesMeta.subscriptionId, balances.filter(balance => {
640
662
  // check that this balance is included in our queried balance modules
641
663
  if (!balanceModules.map(({
642
664
  type
@@ -653,9 +675,9 @@ function useBalances(addressesByToken) {
653
675
 
654
676
  // keep this balance
655
677
  return true;
656
- }),
678
+ })),
657
679
  // hydrate balance chains, evmNetworks, tokens and tokenRates
658
- hydrate), [balances, hydrate, balanceModules, addressesByToken]);
680
+ hydrate), [balancesMeta.subscriptionId, balances, hydrate, balanceModules, addressesByToken]);
659
681
  }
660
682
 
661
683
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@talismn/balances-react",
3
- "version": "0.0.0-pr660-20230327112704",
3
+ "version": "0.0.0-pr660-20230328111733",
4
4
  "author": "Talisman",
5
5
  "homepage": "https://talisman.xyz",
6
6
  "license": "UNLICENSED",
@@ -26,13 +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-pr660-20230327112704",
30
- "@talismn/chain-connector": "^0.0.0-pr660-20230327112704",
31
- "@talismn/chain-connector-evm": "^0.0.0-pr660-20230327112704",
32
- "@talismn/chaindata-provider": "^0.0.0-pr660-20230327112704",
33
- "@talismn/chaindata-provider-extension": "^0.0.0-pr660-20230327112704",
34
- "@talismn/connection-meta": "^0.0.0-pr660-20230327112704",
35
- "@talismn/token-rates": "^0.0.0-pr660-20230327112704",
29
+ "@talismn/balances": "^0.0.0-pr660-20230328111733",
30
+ "@talismn/chain-connector": "^0.0.0-pr660-20230328111733",
31
+ "@talismn/chain-connector-evm": "^0.0.0-pr660-20230328111733",
32
+ "@talismn/chaindata-provider": "^0.0.0-pr660-20230328111733",
33
+ "@talismn/chaindata-provider-extension": "^0.0.0-pr660-20230328111733",
34
+ "@talismn/connection-meta": "^0.0.0-pr660-20230328111733",
35
+ "@talismn/token-rates": "^0.0.0-pr660-20230328111733",
36
36
  "anylogger": "^1.0.11",
37
37
  "blueimp-md5": "2.19.0",
38
38
  "dexie": "^3.2.3",