@talismn/balances 0.0.0-pr2075-20250708110002 → 0.0.0-pr2075-20250708125508

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,7 +1,7 @@
1
1
  import { AnyMiniMetadata } from "@talismn/chaindata-provider";
2
2
  import { IBalance } from "../../../types";
3
3
  import { BalanceDef } from "../../shared";
4
- import { RpcQueryPack } from "../../util/RpcStateQueriesHelper";
4
+ import { RpcQueryPack } from "../../util/rpcQueryPack";
5
5
  import { MiniMetadataExtra } from "../config";
6
6
  export type NomPoolMemberInfo = {
7
7
  points: string;
@@ -1,6 +1,6 @@
1
1
  import { AnyMiniMetadata } from "@talismn/chaindata-provider";
2
2
  import { IBalance } from "../../../types";
3
- import { RpcQueryPack } from "../../util/RpcStateQueriesHelper";
3
+ import { RpcQueryPack } from "../../util/rpcQueryPack";
4
4
  import { MiniMetadataExtra } from "../config";
5
5
  import { BaseBalance } from "./buildBaseQueries";
6
6
  export declare const buildNomPoolQueries: (networkId: string, partialBalances: BaseBalance[], miniMetadata: Omit<AnyMiniMetadata, "extra"> & {
@@ -0,0 +1,11 @@
1
+ import { ChainConnector } from "@talismn/chain-connector";
2
+ import { DotNetworkId } from "@talismn/chaindata-provider";
3
+ import { Observable } from "rxjs";
4
+ type MaybeStateKey = `0x${string}` | null;
5
+ export type RpcQueryPack<T> = {
6
+ stateKeys: MaybeStateKey[];
7
+ decodeResult: (changes: MaybeStateKey[]) => T;
8
+ };
9
+ export declare const fetchRpcQueryPack: <T>(connector: ChainConnector, networkId: DotNetworkId, queries: RpcQueryPack<T>[]) => Promise<T[]>;
10
+ export declare const getRpcQueryPack$: <T>(connector: ChainConnector, networkId: DotNetworkId, queries: RpcQueryPack<T>[], timeout?: number | false) => Observable<T[]>;
11
+ export {};
@@ -1779,7 +1779,7 @@ const getTransferCallData$8 = ({
1779
1779
  };
1780
1780
  };
1781
1781
 
1782
- const SUBSCRIPTION_INTERVAL$8 = 6_000;
1782
+ const SUBSCRIPTION_INTERVAL$7 = 6_000;
1783
1783
  const subscribeBalances$8 = ({
1784
1784
  networkId,
1785
1785
  tokensWithAddresses,
@@ -1797,7 +1797,7 @@ const subscribeBalances$8 = ({
1797
1797
  });
1798
1798
  if (abortController.signal.aborted) return;
1799
1799
  subscriber.next(balances);
1800
- setTimeout(poll, SUBSCRIPTION_INTERVAL$8);
1800
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$7);
1801
1801
  } catch (error) {
1802
1802
  log.error("Error", {
1803
1803
  module: MODULE_TYPE$8,
@@ -1993,7 +1993,7 @@ const getTransferCallData$7 = ({
1993
1993
  };
1994
1994
  };
1995
1995
 
1996
- const SUBSCRIPTION_INTERVAL$7 = 6_000;
1996
+ const SUBSCRIPTION_INTERVAL$6 = 6_000;
1997
1997
  const subscribeBalances$7 = ({
1998
1998
  networkId,
1999
1999
  tokensWithAddresses,
@@ -2011,7 +2011,7 @@ const subscribeBalances$7 = ({
2011
2011
  });
2012
2012
  if (abortController.signal.aborted) return;
2013
2013
  subscriber.next(balances);
2014
- setTimeout(poll, SUBSCRIPTION_INTERVAL$7);
2014
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$6);
2015
2015
  } catch (error) {
2016
2016
  log.error("Error", {
2017
2017
  module: MODULE_TYPE$7,
@@ -2326,7 +2326,7 @@ const getTransferCallData$6 = ({
2326
2326
  };
2327
2327
  };
2328
2328
 
2329
- const SUBSCRIPTION_INTERVAL$6 = 6_000;
2329
+ const SUBSCRIPTION_INTERVAL$5 = 6_000;
2330
2330
  const subscribeBalances$6 = ({
2331
2331
  networkId,
2332
2332
  tokensWithAddresses,
@@ -2344,7 +2344,7 @@ const subscribeBalances$6 = ({
2344
2344
  });
2345
2345
  if (abortController.signal.aborted) return;
2346
2346
  subscriber.next(balances);
2347
- setTimeout(poll, SUBSCRIPTION_INTERVAL$6);
2347
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$5);
2348
2348
  } catch (error) {
2349
2349
  log.error("Error", {
2350
2350
  module: MODULE_TYPE$6,
@@ -3477,7 +3477,7 @@ const fetchBalances$6 = async ({
3477
3477
  }) => {
3478
3478
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
3479
3479
  if (!miniMetadata?.data) {
3480
- log.warn("MiniMetadata is required for fetching balances");
3480
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$5} balances on ${networkId}.`);
3481
3481
  return {
3482
3482
  success: [],
3483
3483
  errors: balanceDefs.map(def => ({
@@ -3847,7 +3847,7 @@ const getTransferAllEncodedArgs$2 = (assetId, to, codec) => {
3847
3847
  })]);
3848
3848
  };
3849
3849
 
3850
- const SUBSCRIPTION_INTERVAL$5 = 6_000;
3850
+ const SUBSCRIPTION_INTERVAL$4 = 6_000;
3851
3851
  const subscribeBalances$5 = ({
3852
3852
  networkId,
3853
3853
  tokensWithAddresses,
@@ -3870,7 +3870,7 @@ const subscribeBalances$5 = ({
3870
3870
  });
3871
3871
  if (abortController.signal.aborted) return;
3872
3872
  subscriber.next(balances);
3873
- setTimeout(poll, SUBSCRIPTION_INTERVAL$5);
3873
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
3874
3874
  } catch (error) {
3875
3875
  log.error("Error", {
3876
3876
  module: MODULE_TYPE$5,
@@ -3916,7 +3916,7 @@ const fetchBalances$5 = async ({
3916
3916
  }) => {
3917
3917
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
3918
3918
  if (!miniMetadata?.data) {
3919
- log.warn("MiniMetadata is required for fetching balances");
3919
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$4} balances on ${networkId}.`);
3920
3920
  return {
3921
3921
  success: [],
3922
3922
  errors: balanceDefs.map(def => ({
@@ -4245,7 +4245,7 @@ const getTransferAllEncodedArgs$1 = (onChainId, to, codec) => {
4245
4245
  })]);
4246
4246
  };
4247
4247
 
4248
- const SUBSCRIPTION_INTERVAL$4 = 6_000;
4248
+ const SUBSCRIPTION_INTERVAL$3 = 6_000;
4249
4249
  const subscribeBalances$4 = ({
4250
4250
  networkId,
4251
4251
  tokensWithAddresses,
@@ -4268,7 +4268,7 @@ const subscribeBalances$4 = ({
4268
4268
  });
4269
4269
  if (abortController.signal.aborted) return;
4270
4270
  subscriber.next(balances);
4271
- setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
4271
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
4272
4272
  } catch (error) {
4273
4273
  log.error("Error", {
4274
4274
  module: MODULE_TYPE$4,
@@ -4344,7 +4344,7 @@ const fetchBalances$4 = async ({
4344
4344
  }) => {
4345
4345
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
4346
4346
  if (!miniMetadata?.data) {
4347
- log.warn("MiniMetadata is required for fetching balances");
4347
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$3} balances on ${networkId}.`);
4348
4348
  return {
4349
4349
  success: [],
4350
4350
  errors: balanceDefs.map(def => ({
@@ -4591,7 +4591,7 @@ const getTransferCallData$3 = ({
4591
4591
  };
4592
4592
  };
4593
4593
 
4594
- const SUBSCRIPTION_INTERVAL$3 = 6_000;
4594
+ const SUBSCRIPTION_INTERVAL$2 = 6_000;
4595
4595
  const subscribeBalances$3 = ({
4596
4596
  networkId,
4597
4597
  tokensWithAddresses,
@@ -4614,7 +4614,7 @@ const subscribeBalances$3 = ({
4614
4614
  });
4615
4615
  if (abortController.signal.aborted) return;
4616
4616
  subscriber.next(balances);
4617
- setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
4617
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$2);
4618
4618
  } catch (error) {
4619
4619
  log.error("Error", {
4620
4620
  module: MODULE_TYPE$3,
@@ -4646,140 +4646,54 @@ const SubHydrationBalanceModule = {
4646
4646
  const MODULE_TYPE$2 = chaindataProvider.SubNativeTokenSchema.shape.type.value;
4647
4647
  const PLATFORM$2 = chaindataProvider.SubNativeTokenSchema.shape.platform.value;
4648
4648
 
4649
- /**
4650
- * Pass some these into an `RpcStateQueryHelper` in order to easily batch multiple state queries into the one rpc call.
4651
- */
4652
-
4653
- const fetchQueriesPack = async (connector, networkId, queries) => {
4649
+ const fetchRpcQueryPack = async (connector, networkId, queries) => {
4654
4650
  const allStateKeys = queries.flatMap(({
4655
4651
  stateKeys
4656
4652
  }) => stateKeys).filter(util.isNotNil);
4657
4653
 
4658
- // doing a query with only null keys would throw an error => return early
4654
+ // doing a query without keys would throw an error => return early
4659
4655
  if (!allStateKeys.length) return queries.map(({
4660
4656
  stateKeys,
4661
4657
  decodeResult
4662
4658
  }) => decodeResult(stateKeys.map(() => null)));
4663
- const response = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
4664
- const results = queries.reduce((acc, {
4659
+ const [result] = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
4660
+ return decodeRpcQueryPack(queries, result);
4661
+ };
4662
+ const getRpcQueryPack$ = (connector, networkId, queries, timeout = false) => {
4663
+ const allStateKeys = queries.flatMap(({
4664
+ stateKeys
4665
+ }) => stateKeys).filter(util.isNotNil);
4666
+
4667
+ // doing a query without keys would throw an error => return early
4668
+ if (!allStateKeys.length) return rxjs.of(queries.map(({
4669
+ stateKeys,
4670
+ decodeResult
4671
+ }) => decodeResult(stateKeys.map(() => null))));
4672
+ return new rxjs.Observable(subscriber => {
4673
+ const promUnsub = connector.subscribe(networkId, "state_subscribeStorage", "state_storage", [allStateKeys], (error, result) => {
4674
+ if (error) subscriber.error(error);else subscriber.next(decodeRpcQueryPack(queries, result));
4675
+ }, timeout);
4676
+ return () => {
4677
+ promUnsub.then(unsub => unsub("state_unsubscribeStorage"));
4678
+ };
4679
+ });
4680
+ };
4681
+ const decodeRpcQueryPack = (queries, result) => {
4682
+ return queries.reduce((acc, {
4665
4683
  stateKeys,
4666
4684
  decodeResult
4667
4685
  }) => {
4668
4686
  const changes = stateKeys.map(stateKey => {
4669
4687
  if (!stateKey) return null;
4670
- const change = response[0].changes.find(([key]) => key === stateKey);
4688
+ const change = result.changes.find(([key]) => key === stateKey);
4671
4689
  if (!change) return null;
4672
4690
  return change[1];
4673
4691
  });
4674
4692
  acc.push(decodeResult(changes));
4675
4693
  return acc;
4676
4694
  }, []);
4677
- return results;
4678
4695
  };
4679
4696
 
4680
- /**
4681
- * Used by a variety of balance modules to help batch multiple state queries into the one rpc call.
4682
- */
4683
- // export class RpcStateQueriesHelper<T> {
4684
- // #connector: ChainConnector
4685
- // #queries: Array<RpcStateQueries<T>>
4686
-
4687
- // constructor(connector: ChainConnector, queries: Array<RpcStateQueries<T>>) {
4688
- // this.#connector = connector
4689
- // this.#queries = queries
4690
- // }
4691
-
4692
- // async subscribe(
4693
- // networkId: DotNetworkId,
4694
- // callback: SubscriptionCallback<T[]>,
4695
- // timeout: number | false = false,
4696
- // subscribeMethod = "state_subscribeStorage",
4697
- // responseMethod = "state_storage",
4698
- // unsubscribeMethod = "state_unsubscribeStorage",
4699
- // ): Promise<UnsubscribeFn> {
4700
- // const params = [this.#queries.flatMap(({ stateKeys }) => stateKeys)]
4701
-
4702
- // const unsub = this.#connector.subscribe(
4703
- // networkId,
4704
- // subscribeMethod,
4705
- // responseMethod,
4706
- // params,
4707
- // (error, result) => {
4708
- // error
4709
- // ? callback(error)
4710
- // : callback(null, this.#distributeChangesToQueryDecoders.call(this, chainId, result))
4711
- // },
4712
- // timeout,
4713
- // )
4714
-
4715
- // const subscriptions = queries.map(([chainId, queries]) => {
4716
- // const params = [queries.map(({ stateKey }) => stateKey)]
4717
-
4718
- // const unsub = this.#connector.subscribe(
4719
- // networkId,
4720
- // subscribeMethod,
4721
- // responseMethod,
4722
- // params,
4723
- // (error, result) => {
4724
- // error
4725
- // ? callback(error)
4726
- // : callback(null, this.#distributeChangesToQueryDecoders.call(this, chainId, result))
4727
- // },
4728
- // timeout,
4729
- // )
4730
-
4731
- // return () => unsub.then((unsubscribe) => unsubscribe(unsubscribeMethod))
4732
- // })
4733
-
4734
- // return () => subscriptions.forEach((unsubscribe) => unsubscribe())
4735
- // }
4736
-
4737
- // async fetch(method = "state_queryStorageAt"): Promise<T[]> {
4738
- // const queriesByChain = groupBy(this.#queries, "chainId")
4739
-
4740
- // const resultsByChain = await Promise.all(
4741
- // Object.entries(queriesByChain).map(async ([chainId, queries]) => {
4742
- // const params = [queries.map(({ stateKey }) => stateKey)]
4743
-
4744
- // const result = (await this.#connector.send(chainId, method, params))[0]
4745
- // return this.#distributeChangesToQueryDecoders.call(this, chainId, result)
4746
- // }),
4747
- // )
4748
-
4749
- // return resultsByChain.flatMap((result) => result)
4750
- // }
4751
-
4752
- // #distributeChangesToQueryDecoders(chainId: DotNetworkId, result: unknown): T[] {
4753
- // if (typeof result !== "object" || result === null) return []
4754
- // if (!hasOwnProperty(result, "changes") || typeof result.changes !== "object") return []
4755
- // if (!Array.isArray(result.changes)) return []
4756
-
4757
- // return result.changes.flatMap(([reference, change]: [unknown, unknown]): [T] | [] => {
4758
- // if (typeof reference !== "string") {
4759
- // log.warn(`Received non-string reference in RPC result: ${reference}`)
4760
- // return []
4761
- // }
4762
-
4763
- // if (typeof change !== "string" && change !== null) {
4764
- // log.warn(`Received non-string and non-null change in RPC result: ${reference} | ${change}`)
4765
- // return []
4766
- // }
4767
-
4768
- // const query = this.#queries.find(
4769
- // ({ chainId: cId, stateKey }) => cId === chainId && stateKey === reference,
4770
- // )
4771
- // if (!query) {
4772
- // log.warn(
4773
- // `Failed to find query:\n${reference} in\n${this.#queries.map(({ stateKey }) => stateKey)}`,
4774
- // )
4775
- // return []
4776
- // }
4777
-
4778
- // return [query.decodeResult(change)]
4779
- // })
4780
- // }
4781
- // }
4782
-
4783
4697
  const SUBTENSOR_ROOT_NETUID$1 = 0;
4784
4698
  const SUBTENSOR_MIN_STAKE_AMOUNT_PLANK$1 = 1000000n;
4785
4699
  const TAO_DECIMALS$1 = 9n;
@@ -5499,7 +5413,7 @@ const fetchBalances$3 = async ({
5499
5413
  }) => {
5500
5414
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
5501
5415
  if (!miniMetadata?.data) {
5502
- log.warn("MiniMetadata is required for fetching balances");
5416
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$2} balances on ${networkId}.`);
5503
5417
  return {
5504
5418
  success: [],
5505
5419
  errors: balanceDefs.map(def => ({
@@ -5531,12 +5445,12 @@ const fetchBalances$3 = async ({
5531
5445
  }))
5532
5446
  };
5533
5447
  }
5534
- const queries = buildBaseQueries(networkId, balanceDefs, miniMetadata);
5535
- const partialBalances = await fetchQueriesPack(connector, networkId, queries);
5448
+ const baseQueries = buildBaseQueries(networkId, balanceDefs, miniMetadata);
5449
+ const partialBalances = await fetchRpcQueryPack(connector, networkId, baseQueries);
5536
5450
 
5537
5451
  // now for each balance that includes nomPoolStaking, we need to fetch the metadata for the pool
5538
5452
  const nomPoolQueries = buildNomPoolQueries(networkId, partialBalances, miniMetadata);
5539
- const balances = await fetchQueriesPack(connector, networkId, nomPoolQueries);
5453
+ const balances = await fetchRpcQueryPack(connector, networkId, nomPoolQueries);
5540
5454
 
5541
5455
  // TODO ⚠️ dedupe locks
5542
5456
 
@@ -5772,46 +5686,32 @@ const getTransferAllEncodedArgs = (to, codec) => {
5772
5686
  })]);
5773
5687
  };
5774
5688
 
5775
- const SUBSCRIPTION_INTERVAL$2 = 6_000;
5776
5689
  const subscribeBalances$2 = ({
5777
5690
  networkId,
5778
5691
  tokensWithAddresses,
5779
5692
  connector,
5780
5693
  miniMetadata
5781
5694
  }) => {
5782
- return new rxjs.Observable(subscriber => {
5783
- const abortController = new AbortController();
5784
-
5785
- // on hydration balances are fetched using a runtimeApi, which can't be subscribed to.
5786
- // => poll values for each block
5787
- const poll = async () => {
5788
- try {
5789
- if (abortController.signal.aborted) return;
5790
- const balances = await fetchBalances$3({
5791
- networkId,
5792
- tokensWithAddresses: tokensWithAddresses,
5793
- connector,
5794
- miniMetadata
5795
- });
5796
- if (abortController.signal.aborted) return;
5797
- subscriber.next(balances);
5798
- setTimeout(poll, SUBSCRIPTION_INTERVAL$2);
5799
- } catch (error) {
5800
- log.error("Error", {
5801
- module: MODULE_TYPE$2,
5802
- networkId,
5803
- miniMetadata,
5804
- addressesByToken: tokensWithAddresses,
5805
- error
5806
- });
5807
- subscriber.error(error);
5808
- }
5809
- };
5810
- poll();
5811
- return () => {
5812
- abortController.abort();
5695
+ // could be use as shared observable key if we decide to cache the sub
5696
+ const balanceDefs = getBalanceDefs(tokensWithAddresses);
5697
+ const baseQueries = buildBaseQueries(networkId, balanceDefs, miniMetadata);
5698
+ const baseBalances$ = getRpcQueryPack$(connector, networkId, baseQueries).pipe(rxjs.switchMap(partialBalances => {
5699
+ // now for each balance that includes nomPoolStaking, we need to fetch the metadata for the pool
5700
+ const nomPoolQueries = buildNomPoolQueries(networkId, partialBalances, miniMetadata);
5701
+ return getRpcQueryPack$(connector, networkId, nomPoolQueries);
5702
+ }));
5703
+ const subtensorBalancesByAddress$ = getSubtensorStakingBalances$(connector, networkId, balanceDefs, miniMetadata);
5704
+ return rxjs.combineLatest([baseBalances$, subtensorBalancesByAddress$]).pipe(rxjs.map(([baseBalances, subtensorBalancesByAddress]) => {
5705
+ // add subtensor balances to base balances
5706
+ for (const [address, subtensorBalances] of lodash.toPairs(subtensorBalancesByAddress)) {
5707
+ const balance = baseBalances.find(b => b.address === address);
5708
+ if (balance?.values) balance.values.push(...subtensorBalances);
5709
+ }
5710
+ return {
5711
+ success: baseBalances,
5712
+ errors: []
5813
5713
  };
5814
- }).pipe(rxjs.distinctUntilChanged(lodash.isEqual));
5714
+ }));
5815
5715
  };
5816
5716
 
5817
5717
  const SubNativeBalanceModule = {
@@ -7251,7 +7151,7 @@ const fetchBalances$1 = async ({
7251
7151
  }) => {
7252
7152
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
7253
7153
  if (!miniMetadata?.data) {
7254
- log.warn("MiniMetadata is required for fetching balances");
7154
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE} balances on ${networkId}.`);
7255
7155
  return {
7256
7156
  success: [],
7257
7157
  errors: balanceDefs.map(def => ({
@@ -1779,7 +1779,7 @@ const getTransferCallData$8 = ({
1779
1779
  };
1780
1780
  };
1781
1781
 
1782
- const SUBSCRIPTION_INTERVAL$8 = 6_000;
1782
+ const SUBSCRIPTION_INTERVAL$7 = 6_000;
1783
1783
  const subscribeBalances$8 = ({
1784
1784
  networkId,
1785
1785
  tokensWithAddresses,
@@ -1797,7 +1797,7 @@ const subscribeBalances$8 = ({
1797
1797
  });
1798
1798
  if (abortController.signal.aborted) return;
1799
1799
  subscriber.next(balances);
1800
- setTimeout(poll, SUBSCRIPTION_INTERVAL$8);
1800
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$7);
1801
1801
  } catch (error) {
1802
1802
  log.error("Error", {
1803
1803
  module: MODULE_TYPE$8,
@@ -1993,7 +1993,7 @@ const getTransferCallData$7 = ({
1993
1993
  };
1994
1994
  };
1995
1995
 
1996
- const SUBSCRIPTION_INTERVAL$7 = 6_000;
1996
+ const SUBSCRIPTION_INTERVAL$6 = 6_000;
1997
1997
  const subscribeBalances$7 = ({
1998
1998
  networkId,
1999
1999
  tokensWithAddresses,
@@ -2011,7 +2011,7 @@ const subscribeBalances$7 = ({
2011
2011
  });
2012
2012
  if (abortController.signal.aborted) return;
2013
2013
  subscriber.next(balances);
2014
- setTimeout(poll, SUBSCRIPTION_INTERVAL$7);
2014
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$6);
2015
2015
  } catch (error) {
2016
2016
  log.error("Error", {
2017
2017
  module: MODULE_TYPE$7,
@@ -2326,7 +2326,7 @@ const getTransferCallData$6 = ({
2326
2326
  };
2327
2327
  };
2328
2328
 
2329
- const SUBSCRIPTION_INTERVAL$6 = 6_000;
2329
+ const SUBSCRIPTION_INTERVAL$5 = 6_000;
2330
2330
  const subscribeBalances$6 = ({
2331
2331
  networkId,
2332
2332
  tokensWithAddresses,
@@ -2344,7 +2344,7 @@ const subscribeBalances$6 = ({
2344
2344
  });
2345
2345
  if (abortController.signal.aborted) return;
2346
2346
  subscriber.next(balances);
2347
- setTimeout(poll, SUBSCRIPTION_INTERVAL$6);
2347
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$5);
2348
2348
  } catch (error) {
2349
2349
  log.error("Error", {
2350
2350
  module: MODULE_TYPE$6,
@@ -3477,7 +3477,7 @@ const fetchBalances$6 = async ({
3477
3477
  }) => {
3478
3478
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
3479
3479
  if (!miniMetadata?.data) {
3480
- log.warn("MiniMetadata is required for fetching balances");
3480
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$5} balances on ${networkId}.`);
3481
3481
  return {
3482
3482
  success: [],
3483
3483
  errors: balanceDefs.map(def => ({
@@ -3847,7 +3847,7 @@ const getTransferAllEncodedArgs$2 = (assetId, to, codec) => {
3847
3847
  })]);
3848
3848
  };
3849
3849
 
3850
- const SUBSCRIPTION_INTERVAL$5 = 6_000;
3850
+ const SUBSCRIPTION_INTERVAL$4 = 6_000;
3851
3851
  const subscribeBalances$5 = ({
3852
3852
  networkId,
3853
3853
  tokensWithAddresses,
@@ -3870,7 +3870,7 @@ const subscribeBalances$5 = ({
3870
3870
  });
3871
3871
  if (abortController.signal.aborted) return;
3872
3872
  subscriber.next(balances);
3873
- setTimeout(poll, SUBSCRIPTION_INTERVAL$5);
3873
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
3874
3874
  } catch (error) {
3875
3875
  log.error("Error", {
3876
3876
  module: MODULE_TYPE$5,
@@ -3916,7 +3916,7 @@ const fetchBalances$5 = async ({
3916
3916
  }) => {
3917
3917
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
3918
3918
  if (!miniMetadata?.data) {
3919
- log.warn("MiniMetadata is required for fetching balances");
3919
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$4} balances on ${networkId}.`);
3920
3920
  return {
3921
3921
  success: [],
3922
3922
  errors: balanceDefs.map(def => ({
@@ -4245,7 +4245,7 @@ const getTransferAllEncodedArgs$1 = (onChainId, to, codec) => {
4245
4245
  })]);
4246
4246
  };
4247
4247
 
4248
- const SUBSCRIPTION_INTERVAL$4 = 6_000;
4248
+ const SUBSCRIPTION_INTERVAL$3 = 6_000;
4249
4249
  const subscribeBalances$4 = ({
4250
4250
  networkId,
4251
4251
  tokensWithAddresses,
@@ -4268,7 +4268,7 @@ const subscribeBalances$4 = ({
4268
4268
  });
4269
4269
  if (abortController.signal.aborted) return;
4270
4270
  subscriber.next(balances);
4271
- setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
4271
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
4272
4272
  } catch (error) {
4273
4273
  log.error("Error", {
4274
4274
  module: MODULE_TYPE$4,
@@ -4344,7 +4344,7 @@ const fetchBalances$4 = async ({
4344
4344
  }) => {
4345
4345
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
4346
4346
  if (!miniMetadata?.data) {
4347
- log.warn("MiniMetadata is required for fetching balances");
4347
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$3} balances on ${networkId}.`);
4348
4348
  return {
4349
4349
  success: [],
4350
4350
  errors: balanceDefs.map(def => ({
@@ -4591,7 +4591,7 @@ const getTransferCallData$3 = ({
4591
4591
  };
4592
4592
  };
4593
4593
 
4594
- const SUBSCRIPTION_INTERVAL$3 = 6_000;
4594
+ const SUBSCRIPTION_INTERVAL$2 = 6_000;
4595
4595
  const subscribeBalances$3 = ({
4596
4596
  networkId,
4597
4597
  tokensWithAddresses,
@@ -4614,7 +4614,7 @@ const subscribeBalances$3 = ({
4614
4614
  });
4615
4615
  if (abortController.signal.aborted) return;
4616
4616
  subscriber.next(balances);
4617
- setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
4617
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$2);
4618
4618
  } catch (error) {
4619
4619
  log.error("Error", {
4620
4620
  module: MODULE_TYPE$3,
@@ -4646,140 +4646,54 @@ const SubHydrationBalanceModule = {
4646
4646
  const MODULE_TYPE$2 = chaindataProvider.SubNativeTokenSchema.shape.type.value;
4647
4647
  const PLATFORM$2 = chaindataProvider.SubNativeTokenSchema.shape.platform.value;
4648
4648
 
4649
- /**
4650
- * Pass some these into an `RpcStateQueryHelper` in order to easily batch multiple state queries into the one rpc call.
4651
- */
4652
-
4653
- const fetchQueriesPack = async (connector, networkId, queries) => {
4649
+ const fetchRpcQueryPack = async (connector, networkId, queries) => {
4654
4650
  const allStateKeys = queries.flatMap(({
4655
4651
  stateKeys
4656
4652
  }) => stateKeys).filter(util.isNotNil);
4657
4653
 
4658
- // doing a query with only null keys would throw an error => return early
4654
+ // doing a query without keys would throw an error => return early
4659
4655
  if (!allStateKeys.length) return queries.map(({
4660
4656
  stateKeys,
4661
4657
  decodeResult
4662
4658
  }) => decodeResult(stateKeys.map(() => null)));
4663
- const response = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
4664
- const results = queries.reduce((acc, {
4659
+ const [result] = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
4660
+ return decodeRpcQueryPack(queries, result);
4661
+ };
4662
+ const getRpcQueryPack$ = (connector, networkId, queries, timeout = false) => {
4663
+ const allStateKeys = queries.flatMap(({
4664
+ stateKeys
4665
+ }) => stateKeys).filter(util.isNotNil);
4666
+
4667
+ // doing a query without keys would throw an error => return early
4668
+ if (!allStateKeys.length) return rxjs.of(queries.map(({
4669
+ stateKeys,
4670
+ decodeResult
4671
+ }) => decodeResult(stateKeys.map(() => null))));
4672
+ return new rxjs.Observable(subscriber => {
4673
+ const promUnsub = connector.subscribe(networkId, "state_subscribeStorage", "state_storage", [allStateKeys], (error, result) => {
4674
+ if (error) subscriber.error(error);else subscriber.next(decodeRpcQueryPack(queries, result));
4675
+ }, timeout);
4676
+ return () => {
4677
+ promUnsub.then(unsub => unsub("state_unsubscribeStorage"));
4678
+ };
4679
+ });
4680
+ };
4681
+ const decodeRpcQueryPack = (queries, result) => {
4682
+ return queries.reduce((acc, {
4665
4683
  stateKeys,
4666
4684
  decodeResult
4667
4685
  }) => {
4668
4686
  const changes = stateKeys.map(stateKey => {
4669
4687
  if (!stateKey) return null;
4670
- const change = response[0].changes.find(([key]) => key === stateKey);
4688
+ const change = result.changes.find(([key]) => key === stateKey);
4671
4689
  if (!change) return null;
4672
4690
  return change[1];
4673
4691
  });
4674
4692
  acc.push(decodeResult(changes));
4675
4693
  return acc;
4676
4694
  }, []);
4677
- return results;
4678
4695
  };
4679
4696
 
4680
- /**
4681
- * Used by a variety of balance modules to help batch multiple state queries into the one rpc call.
4682
- */
4683
- // export class RpcStateQueriesHelper<T> {
4684
- // #connector: ChainConnector
4685
- // #queries: Array<RpcStateQueries<T>>
4686
-
4687
- // constructor(connector: ChainConnector, queries: Array<RpcStateQueries<T>>) {
4688
- // this.#connector = connector
4689
- // this.#queries = queries
4690
- // }
4691
-
4692
- // async subscribe(
4693
- // networkId: DotNetworkId,
4694
- // callback: SubscriptionCallback<T[]>,
4695
- // timeout: number | false = false,
4696
- // subscribeMethod = "state_subscribeStorage",
4697
- // responseMethod = "state_storage",
4698
- // unsubscribeMethod = "state_unsubscribeStorage",
4699
- // ): Promise<UnsubscribeFn> {
4700
- // const params = [this.#queries.flatMap(({ stateKeys }) => stateKeys)]
4701
-
4702
- // const unsub = this.#connector.subscribe(
4703
- // networkId,
4704
- // subscribeMethod,
4705
- // responseMethod,
4706
- // params,
4707
- // (error, result) => {
4708
- // error
4709
- // ? callback(error)
4710
- // : callback(null, this.#distributeChangesToQueryDecoders.call(this, chainId, result))
4711
- // },
4712
- // timeout,
4713
- // )
4714
-
4715
- // const subscriptions = queries.map(([chainId, queries]) => {
4716
- // const params = [queries.map(({ stateKey }) => stateKey)]
4717
-
4718
- // const unsub = this.#connector.subscribe(
4719
- // networkId,
4720
- // subscribeMethod,
4721
- // responseMethod,
4722
- // params,
4723
- // (error, result) => {
4724
- // error
4725
- // ? callback(error)
4726
- // : callback(null, this.#distributeChangesToQueryDecoders.call(this, chainId, result))
4727
- // },
4728
- // timeout,
4729
- // )
4730
-
4731
- // return () => unsub.then((unsubscribe) => unsubscribe(unsubscribeMethod))
4732
- // })
4733
-
4734
- // return () => subscriptions.forEach((unsubscribe) => unsubscribe())
4735
- // }
4736
-
4737
- // async fetch(method = "state_queryStorageAt"): Promise<T[]> {
4738
- // const queriesByChain = groupBy(this.#queries, "chainId")
4739
-
4740
- // const resultsByChain = await Promise.all(
4741
- // Object.entries(queriesByChain).map(async ([chainId, queries]) => {
4742
- // const params = [queries.map(({ stateKey }) => stateKey)]
4743
-
4744
- // const result = (await this.#connector.send(chainId, method, params))[0]
4745
- // return this.#distributeChangesToQueryDecoders.call(this, chainId, result)
4746
- // }),
4747
- // )
4748
-
4749
- // return resultsByChain.flatMap((result) => result)
4750
- // }
4751
-
4752
- // #distributeChangesToQueryDecoders(chainId: DotNetworkId, result: unknown): T[] {
4753
- // if (typeof result !== "object" || result === null) return []
4754
- // if (!hasOwnProperty(result, "changes") || typeof result.changes !== "object") return []
4755
- // if (!Array.isArray(result.changes)) return []
4756
-
4757
- // return result.changes.flatMap(([reference, change]: [unknown, unknown]): [T] | [] => {
4758
- // if (typeof reference !== "string") {
4759
- // log.warn(`Received non-string reference in RPC result: ${reference}`)
4760
- // return []
4761
- // }
4762
-
4763
- // if (typeof change !== "string" && change !== null) {
4764
- // log.warn(`Received non-string and non-null change in RPC result: ${reference} | ${change}`)
4765
- // return []
4766
- // }
4767
-
4768
- // const query = this.#queries.find(
4769
- // ({ chainId: cId, stateKey }) => cId === chainId && stateKey === reference,
4770
- // )
4771
- // if (!query) {
4772
- // log.warn(
4773
- // `Failed to find query:\n${reference} in\n${this.#queries.map(({ stateKey }) => stateKey)}`,
4774
- // )
4775
- // return []
4776
- // }
4777
-
4778
- // return [query.decodeResult(change)]
4779
- // })
4780
- // }
4781
- // }
4782
-
4783
4697
  const SUBTENSOR_ROOT_NETUID$1 = 0;
4784
4698
  const SUBTENSOR_MIN_STAKE_AMOUNT_PLANK$1 = 1000000n;
4785
4699
  const TAO_DECIMALS$1 = 9n;
@@ -5499,7 +5413,7 @@ const fetchBalances$3 = async ({
5499
5413
  }) => {
5500
5414
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
5501
5415
  if (!miniMetadata?.data) {
5502
- log.warn("MiniMetadata is required for fetching balances");
5416
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$2} balances on ${networkId}.`);
5503
5417
  return {
5504
5418
  success: [],
5505
5419
  errors: balanceDefs.map(def => ({
@@ -5531,12 +5445,12 @@ const fetchBalances$3 = async ({
5531
5445
  }))
5532
5446
  };
5533
5447
  }
5534
- const queries = buildBaseQueries(networkId, balanceDefs, miniMetadata);
5535
- const partialBalances = await fetchQueriesPack(connector, networkId, queries);
5448
+ const baseQueries = buildBaseQueries(networkId, balanceDefs, miniMetadata);
5449
+ const partialBalances = await fetchRpcQueryPack(connector, networkId, baseQueries);
5536
5450
 
5537
5451
  // now for each balance that includes nomPoolStaking, we need to fetch the metadata for the pool
5538
5452
  const nomPoolQueries = buildNomPoolQueries(networkId, partialBalances, miniMetadata);
5539
- const balances = await fetchQueriesPack(connector, networkId, nomPoolQueries);
5453
+ const balances = await fetchRpcQueryPack(connector, networkId, nomPoolQueries);
5540
5454
 
5541
5455
  // TODO ⚠️ dedupe locks
5542
5456
 
@@ -5772,46 +5686,32 @@ const getTransferAllEncodedArgs = (to, codec) => {
5772
5686
  })]);
5773
5687
  };
5774
5688
 
5775
- const SUBSCRIPTION_INTERVAL$2 = 6_000;
5776
5689
  const subscribeBalances$2 = ({
5777
5690
  networkId,
5778
5691
  tokensWithAddresses,
5779
5692
  connector,
5780
5693
  miniMetadata
5781
5694
  }) => {
5782
- return new rxjs.Observable(subscriber => {
5783
- const abortController = new AbortController();
5784
-
5785
- // on hydration balances are fetched using a runtimeApi, which can't be subscribed to.
5786
- // => poll values for each block
5787
- const poll = async () => {
5788
- try {
5789
- if (abortController.signal.aborted) return;
5790
- const balances = await fetchBalances$3({
5791
- networkId,
5792
- tokensWithAddresses: tokensWithAddresses,
5793
- connector,
5794
- miniMetadata
5795
- });
5796
- if (abortController.signal.aborted) return;
5797
- subscriber.next(balances);
5798
- setTimeout(poll, SUBSCRIPTION_INTERVAL$2);
5799
- } catch (error) {
5800
- log.error("Error", {
5801
- module: MODULE_TYPE$2,
5802
- networkId,
5803
- miniMetadata,
5804
- addressesByToken: tokensWithAddresses,
5805
- error
5806
- });
5807
- subscriber.error(error);
5808
- }
5809
- };
5810
- poll();
5811
- return () => {
5812
- abortController.abort();
5695
+ // could be use as shared observable key if we decide to cache the sub
5696
+ const balanceDefs = getBalanceDefs(tokensWithAddresses);
5697
+ const baseQueries = buildBaseQueries(networkId, balanceDefs, miniMetadata);
5698
+ const baseBalances$ = getRpcQueryPack$(connector, networkId, baseQueries).pipe(rxjs.switchMap(partialBalances => {
5699
+ // now for each balance that includes nomPoolStaking, we need to fetch the metadata for the pool
5700
+ const nomPoolQueries = buildNomPoolQueries(networkId, partialBalances, miniMetadata);
5701
+ return getRpcQueryPack$(connector, networkId, nomPoolQueries);
5702
+ }));
5703
+ const subtensorBalancesByAddress$ = getSubtensorStakingBalances$(connector, networkId, balanceDefs, miniMetadata);
5704
+ return rxjs.combineLatest([baseBalances$, subtensorBalancesByAddress$]).pipe(rxjs.map(([baseBalances, subtensorBalancesByAddress]) => {
5705
+ // add subtensor balances to base balances
5706
+ for (const [address, subtensorBalances] of lodash.toPairs(subtensorBalancesByAddress)) {
5707
+ const balance = baseBalances.find(b => b.address === address);
5708
+ if (balance?.values) balance.values.push(...subtensorBalances);
5709
+ }
5710
+ return {
5711
+ success: baseBalances,
5712
+ errors: []
5813
5713
  };
5814
- }).pipe(rxjs.distinctUntilChanged(lodash.isEqual));
5714
+ }));
5815
5715
  };
5816
5716
 
5817
5717
  const SubNativeBalanceModule = {
@@ -7251,7 +7151,7 @@ const fetchBalances$1 = async ({
7251
7151
  }) => {
7252
7152
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
7253
7153
  if (!miniMetadata?.data) {
7254
- log.warn("MiniMetadata is required for fetching balances");
7154
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE} balances on ${networkId}.`);
7255
7155
  return {
7256
7156
  success: [],
7257
7157
  errors: balanceDefs.map(def => ({
@@ -11,7 +11,7 @@ import pako from 'pako';
11
11
  import { parseAbi, erc20Abi, getContract, ContractFunctionExecutionError, hexToString, erc20Abi_bytes32, encodeFunctionData, isHex, hexToBigInt, withRetry } from 'viem';
12
12
  import { assign, omit, isEqual, fromPairs, toPairs, keys, keyBy, uniq, values, groupBy as groupBy$1 } from 'lodash';
13
13
  import z from 'zod/v4';
14
- import { Observable, distinctUntilChanged, of, timer, switchMap, from, firstValueFrom, scan, share, map, switchAll, combineLatest, mergeMap, toArray, interval, startWith, exhaustMap, BehaviorSubject, debounceTime, takeUntil, withLatestFrom, concatMap, tap } from 'rxjs';
14
+ import { Observable, distinctUntilChanged, of, timer, switchMap, from, firstValueFrom, combineLatest, map, scan, share, switchAll, mergeMap, toArray, interval, startWith, exhaustMap, BehaviorSubject, debounceTime, takeUntil, withLatestFrom, concatMap, tap } from 'rxjs';
15
15
  import isEqual$1 from 'lodash/isEqual';
16
16
  import { unifyMetadata, decAnyMetadata, getDynamicBuilder, getLookupFn, decodeScale, parseMetadataRpc, getStorageKeyPrefix, compactMetadata, encodeMetadata, papiParse, papiStringify, toHex, getMetadataVersion, encodeStateKey } from '@talismn/scale';
17
17
  import { Metadata, TypeRegistry } from '@polkadot/types';
@@ -1766,7 +1766,7 @@ const getTransferCallData$8 = ({
1766
1766
  };
1767
1767
  };
1768
1768
 
1769
- const SUBSCRIPTION_INTERVAL$8 = 6_000;
1769
+ const SUBSCRIPTION_INTERVAL$7 = 6_000;
1770
1770
  const subscribeBalances$8 = ({
1771
1771
  networkId,
1772
1772
  tokensWithAddresses,
@@ -1784,7 +1784,7 @@ const subscribeBalances$8 = ({
1784
1784
  });
1785
1785
  if (abortController.signal.aborted) return;
1786
1786
  subscriber.next(balances);
1787
- setTimeout(poll, SUBSCRIPTION_INTERVAL$8);
1787
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$7);
1788
1788
  } catch (error) {
1789
1789
  log.error("Error", {
1790
1790
  module: MODULE_TYPE$8,
@@ -1980,7 +1980,7 @@ const getTransferCallData$7 = ({
1980
1980
  };
1981
1981
  };
1982
1982
 
1983
- const SUBSCRIPTION_INTERVAL$7 = 6_000;
1983
+ const SUBSCRIPTION_INTERVAL$6 = 6_000;
1984
1984
  const subscribeBalances$7 = ({
1985
1985
  networkId,
1986
1986
  tokensWithAddresses,
@@ -1998,7 +1998,7 @@ const subscribeBalances$7 = ({
1998
1998
  });
1999
1999
  if (abortController.signal.aborted) return;
2000
2000
  subscriber.next(balances);
2001
- setTimeout(poll, SUBSCRIPTION_INTERVAL$7);
2001
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$6);
2002
2002
  } catch (error) {
2003
2003
  log.error("Error", {
2004
2004
  module: MODULE_TYPE$7,
@@ -2313,7 +2313,7 @@ const getTransferCallData$6 = ({
2313
2313
  };
2314
2314
  };
2315
2315
 
2316
- const SUBSCRIPTION_INTERVAL$6 = 6_000;
2316
+ const SUBSCRIPTION_INTERVAL$5 = 6_000;
2317
2317
  const subscribeBalances$6 = ({
2318
2318
  networkId,
2319
2319
  tokensWithAddresses,
@@ -2331,7 +2331,7 @@ const subscribeBalances$6 = ({
2331
2331
  });
2332
2332
  if (abortController.signal.aborted) return;
2333
2333
  subscriber.next(balances);
2334
- setTimeout(poll, SUBSCRIPTION_INTERVAL$6);
2334
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$5);
2335
2335
  } catch (error) {
2336
2336
  log.error("Error", {
2337
2337
  module: MODULE_TYPE$6,
@@ -3464,7 +3464,7 @@ const fetchBalances$6 = async ({
3464
3464
  }) => {
3465
3465
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
3466
3466
  if (!miniMetadata?.data) {
3467
- log.warn("MiniMetadata is required for fetching balances");
3467
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$5} balances on ${networkId}.`);
3468
3468
  return {
3469
3469
  success: [],
3470
3470
  errors: balanceDefs.map(def => ({
@@ -3834,7 +3834,7 @@ const getTransferAllEncodedArgs$2 = (assetId, to, codec) => {
3834
3834
  })]);
3835
3835
  };
3836
3836
 
3837
- const SUBSCRIPTION_INTERVAL$5 = 6_000;
3837
+ const SUBSCRIPTION_INTERVAL$4 = 6_000;
3838
3838
  const subscribeBalances$5 = ({
3839
3839
  networkId,
3840
3840
  tokensWithAddresses,
@@ -3857,7 +3857,7 @@ const subscribeBalances$5 = ({
3857
3857
  });
3858
3858
  if (abortController.signal.aborted) return;
3859
3859
  subscriber.next(balances);
3860
- setTimeout(poll, SUBSCRIPTION_INTERVAL$5);
3860
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
3861
3861
  } catch (error) {
3862
3862
  log.error("Error", {
3863
3863
  module: MODULE_TYPE$5,
@@ -3903,7 +3903,7 @@ const fetchBalances$5 = async ({
3903
3903
  }) => {
3904
3904
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
3905
3905
  if (!miniMetadata?.data) {
3906
- log.warn("MiniMetadata is required for fetching balances");
3906
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$4} balances on ${networkId}.`);
3907
3907
  return {
3908
3908
  success: [],
3909
3909
  errors: balanceDefs.map(def => ({
@@ -4232,7 +4232,7 @@ const getTransferAllEncodedArgs$1 = (onChainId, to, codec) => {
4232
4232
  })]);
4233
4233
  };
4234
4234
 
4235
- const SUBSCRIPTION_INTERVAL$4 = 6_000;
4235
+ const SUBSCRIPTION_INTERVAL$3 = 6_000;
4236
4236
  const subscribeBalances$4 = ({
4237
4237
  networkId,
4238
4238
  tokensWithAddresses,
@@ -4255,7 +4255,7 @@ const subscribeBalances$4 = ({
4255
4255
  });
4256
4256
  if (abortController.signal.aborted) return;
4257
4257
  subscriber.next(balances);
4258
- setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
4258
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
4259
4259
  } catch (error) {
4260
4260
  log.error("Error", {
4261
4261
  module: MODULE_TYPE$4,
@@ -4331,7 +4331,7 @@ const fetchBalances$4 = async ({
4331
4331
  }) => {
4332
4332
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
4333
4333
  if (!miniMetadata?.data) {
4334
- log.warn("MiniMetadata is required for fetching balances");
4334
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$3} balances on ${networkId}.`);
4335
4335
  return {
4336
4336
  success: [],
4337
4337
  errors: balanceDefs.map(def => ({
@@ -4578,7 +4578,7 @@ const getTransferCallData$3 = ({
4578
4578
  };
4579
4579
  };
4580
4580
 
4581
- const SUBSCRIPTION_INTERVAL$3 = 6_000;
4581
+ const SUBSCRIPTION_INTERVAL$2 = 6_000;
4582
4582
  const subscribeBalances$3 = ({
4583
4583
  networkId,
4584
4584
  tokensWithAddresses,
@@ -4601,7 +4601,7 @@ const subscribeBalances$3 = ({
4601
4601
  });
4602
4602
  if (abortController.signal.aborted) return;
4603
4603
  subscriber.next(balances);
4604
- setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
4604
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$2);
4605
4605
  } catch (error) {
4606
4606
  log.error("Error", {
4607
4607
  module: MODULE_TYPE$3,
@@ -4633,140 +4633,54 @@ const SubHydrationBalanceModule = {
4633
4633
  const MODULE_TYPE$2 = SubNativeTokenSchema.shape.type.value;
4634
4634
  const PLATFORM$2 = SubNativeTokenSchema.shape.platform.value;
4635
4635
 
4636
- /**
4637
- * Pass some these into an `RpcStateQueryHelper` in order to easily batch multiple state queries into the one rpc call.
4638
- */
4639
-
4640
- const fetchQueriesPack = async (connector, networkId, queries) => {
4636
+ const fetchRpcQueryPack = async (connector, networkId, queries) => {
4641
4637
  const allStateKeys = queries.flatMap(({
4642
4638
  stateKeys
4643
4639
  }) => stateKeys).filter(isNotNil);
4644
4640
 
4645
- // doing a query with only null keys would throw an error => return early
4641
+ // doing a query without keys would throw an error => return early
4646
4642
  if (!allStateKeys.length) return queries.map(({
4647
4643
  stateKeys,
4648
4644
  decodeResult
4649
4645
  }) => decodeResult(stateKeys.map(() => null)));
4650
- const response = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
4651
- const results = queries.reduce((acc, {
4646
+ const [result] = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
4647
+ return decodeRpcQueryPack(queries, result);
4648
+ };
4649
+ const getRpcQueryPack$ = (connector, networkId, queries, timeout = false) => {
4650
+ const allStateKeys = queries.flatMap(({
4651
+ stateKeys
4652
+ }) => stateKeys).filter(isNotNil);
4653
+
4654
+ // doing a query without keys would throw an error => return early
4655
+ if (!allStateKeys.length) return of(queries.map(({
4656
+ stateKeys,
4657
+ decodeResult
4658
+ }) => decodeResult(stateKeys.map(() => null))));
4659
+ return new Observable(subscriber => {
4660
+ const promUnsub = connector.subscribe(networkId, "state_subscribeStorage", "state_storage", [allStateKeys], (error, result) => {
4661
+ if (error) subscriber.error(error);else subscriber.next(decodeRpcQueryPack(queries, result));
4662
+ }, timeout);
4663
+ return () => {
4664
+ promUnsub.then(unsub => unsub("state_unsubscribeStorage"));
4665
+ };
4666
+ });
4667
+ };
4668
+ const decodeRpcQueryPack = (queries, result) => {
4669
+ return queries.reduce((acc, {
4652
4670
  stateKeys,
4653
4671
  decodeResult
4654
4672
  }) => {
4655
4673
  const changes = stateKeys.map(stateKey => {
4656
4674
  if (!stateKey) return null;
4657
- const change = response[0].changes.find(([key]) => key === stateKey);
4675
+ const change = result.changes.find(([key]) => key === stateKey);
4658
4676
  if (!change) return null;
4659
4677
  return change[1];
4660
4678
  });
4661
4679
  acc.push(decodeResult(changes));
4662
4680
  return acc;
4663
4681
  }, []);
4664
- return results;
4665
4682
  };
4666
4683
 
4667
- /**
4668
- * Used by a variety of balance modules to help batch multiple state queries into the one rpc call.
4669
- */
4670
- // export class RpcStateQueriesHelper<T> {
4671
- // #connector: ChainConnector
4672
- // #queries: Array<RpcStateQueries<T>>
4673
-
4674
- // constructor(connector: ChainConnector, queries: Array<RpcStateQueries<T>>) {
4675
- // this.#connector = connector
4676
- // this.#queries = queries
4677
- // }
4678
-
4679
- // async subscribe(
4680
- // networkId: DotNetworkId,
4681
- // callback: SubscriptionCallback<T[]>,
4682
- // timeout: number | false = false,
4683
- // subscribeMethod = "state_subscribeStorage",
4684
- // responseMethod = "state_storage",
4685
- // unsubscribeMethod = "state_unsubscribeStorage",
4686
- // ): Promise<UnsubscribeFn> {
4687
- // const params = [this.#queries.flatMap(({ stateKeys }) => stateKeys)]
4688
-
4689
- // const unsub = this.#connector.subscribe(
4690
- // networkId,
4691
- // subscribeMethod,
4692
- // responseMethod,
4693
- // params,
4694
- // (error, result) => {
4695
- // error
4696
- // ? callback(error)
4697
- // : callback(null, this.#distributeChangesToQueryDecoders.call(this, chainId, result))
4698
- // },
4699
- // timeout,
4700
- // )
4701
-
4702
- // const subscriptions = queries.map(([chainId, queries]) => {
4703
- // const params = [queries.map(({ stateKey }) => stateKey)]
4704
-
4705
- // const unsub = this.#connector.subscribe(
4706
- // networkId,
4707
- // subscribeMethod,
4708
- // responseMethod,
4709
- // params,
4710
- // (error, result) => {
4711
- // error
4712
- // ? callback(error)
4713
- // : callback(null, this.#distributeChangesToQueryDecoders.call(this, chainId, result))
4714
- // },
4715
- // timeout,
4716
- // )
4717
-
4718
- // return () => unsub.then((unsubscribe) => unsubscribe(unsubscribeMethod))
4719
- // })
4720
-
4721
- // return () => subscriptions.forEach((unsubscribe) => unsubscribe())
4722
- // }
4723
-
4724
- // async fetch(method = "state_queryStorageAt"): Promise<T[]> {
4725
- // const queriesByChain = groupBy(this.#queries, "chainId")
4726
-
4727
- // const resultsByChain = await Promise.all(
4728
- // Object.entries(queriesByChain).map(async ([chainId, queries]) => {
4729
- // const params = [queries.map(({ stateKey }) => stateKey)]
4730
-
4731
- // const result = (await this.#connector.send(chainId, method, params))[0]
4732
- // return this.#distributeChangesToQueryDecoders.call(this, chainId, result)
4733
- // }),
4734
- // )
4735
-
4736
- // return resultsByChain.flatMap((result) => result)
4737
- // }
4738
-
4739
- // #distributeChangesToQueryDecoders(chainId: DotNetworkId, result: unknown): T[] {
4740
- // if (typeof result !== "object" || result === null) return []
4741
- // if (!hasOwnProperty(result, "changes") || typeof result.changes !== "object") return []
4742
- // if (!Array.isArray(result.changes)) return []
4743
-
4744
- // return result.changes.flatMap(([reference, change]: [unknown, unknown]): [T] | [] => {
4745
- // if (typeof reference !== "string") {
4746
- // log.warn(`Received non-string reference in RPC result: ${reference}`)
4747
- // return []
4748
- // }
4749
-
4750
- // if (typeof change !== "string" && change !== null) {
4751
- // log.warn(`Received non-string and non-null change in RPC result: ${reference} | ${change}`)
4752
- // return []
4753
- // }
4754
-
4755
- // const query = this.#queries.find(
4756
- // ({ chainId: cId, stateKey }) => cId === chainId && stateKey === reference,
4757
- // )
4758
- // if (!query) {
4759
- // log.warn(
4760
- // `Failed to find query:\n${reference} in\n${this.#queries.map(({ stateKey }) => stateKey)}`,
4761
- // )
4762
- // return []
4763
- // }
4764
-
4765
- // return [query.decodeResult(change)]
4766
- // })
4767
- // }
4768
- // }
4769
-
4770
4684
  const SUBTENSOR_ROOT_NETUID$1 = 0;
4771
4685
  const SUBTENSOR_MIN_STAKE_AMOUNT_PLANK$1 = 1000000n;
4772
4686
  const TAO_DECIMALS$1 = 9n;
@@ -5486,7 +5400,7 @@ const fetchBalances$3 = async ({
5486
5400
  }) => {
5487
5401
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
5488
5402
  if (!miniMetadata?.data) {
5489
- log.warn("MiniMetadata is required for fetching balances");
5403
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$2} balances on ${networkId}.`);
5490
5404
  return {
5491
5405
  success: [],
5492
5406
  errors: balanceDefs.map(def => ({
@@ -5518,12 +5432,12 @@ const fetchBalances$3 = async ({
5518
5432
  }))
5519
5433
  };
5520
5434
  }
5521
- const queries = buildBaseQueries(networkId, balanceDefs, miniMetadata);
5522
- const partialBalances = await fetchQueriesPack(connector, networkId, queries);
5435
+ const baseQueries = buildBaseQueries(networkId, balanceDefs, miniMetadata);
5436
+ const partialBalances = await fetchRpcQueryPack(connector, networkId, baseQueries);
5523
5437
 
5524
5438
  // now for each balance that includes nomPoolStaking, we need to fetch the metadata for the pool
5525
5439
  const nomPoolQueries = buildNomPoolQueries(networkId, partialBalances, miniMetadata);
5526
- const balances = await fetchQueriesPack(connector, networkId, nomPoolQueries);
5440
+ const balances = await fetchRpcQueryPack(connector, networkId, nomPoolQueries);
5527
5441
 
5528
5442
  // TODO ⚠️ dedupe locks
5529
5443
 
@@ -5759,46 +5673,32 @@ const getTransferAllEncodedArgs = (to, codec) => {
5759
5673
  })]);
5760
5674
  };
5761
5675
 
5762
- const SUBSCRIPTION_INTERVAL$2 = 6_000;
5763
5676
  const subscribeBalances$2 = ({
5764
5677
  networkId,
5765
5678
  tokensWithAddresses,
5766
5679
  connector,
5767
5680
  miniMetadata
5768
5681
  }) => {
5769
- return new Observable(subscriber => {
5770
- const abortController = new AbortController();
5771
-
5772
- // on hydration balances are fetched using a runtimeApi, which can't be subscribed to.
5773
- // => poll values for each block
5774
- const poll = async () => {
5775
- try {
5776
- if (abortController.signal.aborted) return;
5777
- const balances = await fetchBalances$3({
5778
- networkId,
5779
- tokensWithAddresses: tokensWithAddresses,
5780
- connector,
5781
- miniMetadata
5782
- });
5783
- if (abortController.signal.aborted) return;
5784
- subscriber.next(balances);
5785
- setTimeout(poll, SUBSCRIPTION_INTERVAL$2);
5786
- } catch (error) {
5787
- log.error("Error", {
5788
- module: MODULE_TYPE$2,
5789
- networkId,
5790
- miniMetadata,
5791
- addressesByToken: tokensWithAddresses,
5792
- error
5793
- });
5794
- subscriber.error(error);
5795
- }
5796
- };
5797
- poll();
5798
- return () => {
5799
- abortController.abort();
5682
+ // could be use as shared observable key if we decide to cache the sub
5683
+ const balanceDefs = getBalanceDefs(tokensWithAddresses);
5684
+ const baseQueries = buildBaseQueries(networkId, balanceDefs, miniMetadata);
5685
+ const baseBalances$ = getRpcQueryPack$(connector, networkId, baseQueries).pipe(switchMap(partialBalances => {
5686
+ // now for each balance that includes nomPoolStaking, we need to fetch the metadata for the pool
5687
+ const nomPoolQueries = buildNomPoolQueries(networkId, partialBalances, miniMetadata);
5688
+ return getRpcQueryPack$(connector, networkId, nomPoolQueries);
5689
+ }));
5690
+ const subtensorBalancesByAddress$ = getSubtensorStakingBalances$(connector, networkId, balanceDefs, miniMetadata);
5691
+ return combineLatest([baseBalances$, subtensorBalancesByAddress$]).pipe(map(([baseBalances, subtensorBalancesByAddress]) => {
5692
+ // add subtensor balances to base balances
5693
+ for (const [address, subtensorBalances] of toPairs(subtensorBalancesByAddress)) {
5694
+ const balance = baseBalances.find(b => b.address === address);
5695
+ if (balance?.values) balance.values.push(...subtensorBalances);
5696
+ }
5697
+ return {
5698
+ success: baseBalances,
5699
+ errors: []
5800
5700
  };
5801
- }).pipe(distinctUntilChanged(isEqual));
5701
+ }));
5802
5702
  };
5803
5703
 
5804
5704
  const SubNativeBalanceModule = {
@@ -7238,7 +7138,7 @@ const fetchBalances$1 = async ({
7238
7138
  }) => {
7239
7139
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
7240
7140
  if (!miniMetadata?.data) {
7241
- log.warn("MiniMetadata is required for fetching balances");
7141
+ log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE} balances on ${networkId}.`);
7242
7142
  return {
7243
7143
  success: [],
7244
7144
  errors: balanceDefs.map(def => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@talismn/balances",
3
- "version": "0.0.0-pr2075-20250708110002",
3
+ "version": "0.0.0-pr2075-20250708125508",
4
4
  "author": "Talisman",
5
5
  "homepage": "https://talisman.xyz",
6
6
  "license": "GPL-3.0-or-later",
@@ -35,13 +35,13 @@
35
35
  "scale-ts": "^1.6.1",
36
36
  "viem": "^2.27.3",
37
37
  "zod": "^3.25.62",
38
- "@talismn/chain-connector": "0.0.0-pr2075-20250708110002",
39
- "@talismn/chain-connector-evm": "0.0.0-pr2075-20250708110002",
40
- "@talismn/sapi": "0.0.0-pr2075-20250708110002",
41
- "@talismn/scale": "0.0.0-pr2075-20250708110002",
42
- "@talismn/chaindata-provider": "0.0.0-pr2075-20250708110002",
43
- "@talismn/token-rates": "0.0.0-pr2075-20250708110002",
44
- "@talismn/util": "0.0.0-pr2075-20250708110002"
38
+ "@talismn/chain-connector": "0.0.0-pr2075-20250708125508",
39
+ "@talismn/chaindata-provider": "0.0.0-pr2075-20250708125508",
40
+ "@talismn/chain-connector-evm": "0.0.0-pr2075-20250708125508",
41
+ "@talismn/sapi": "0.0.0-pr2075-20250708125508",
42
+ "@talismn/scale": "0.0.0-pr2075-20250708125508",
43
+ "@talismn/token-rates": "0.0.0-pr2075-20250708125508",
44
+ "@talismn/util": "0.0.0-pr2075-20250708125508"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@polkadot/api-contract": "16.1.2",
@@ -1,12 +0,0 @@
1
- import { ChainConnector } from "@talismn/chain-connector";
2
- /**
3
- * Pass some these into an `RpcStateQueryHelper` in order to easily batch multiple state queries into the one rpc call.
4
- */
5
- export type RpcQueryPack<T> = {
6
- stateKeys: (`0x${string}` | null)[];
7
- decodeResult: (changes: (`0x${string}` | null)[]) => T;
8
- };
9
- export declare const fetchQueriesPack: <T>(connector: ChainConnector, networkId: string, queries: RpcQueryPack<T>[]) => Promise<T[]>;
10
- /**
11
- * Used by a variety of balance modules to help batch multiple state queries into the one rpc call.
12
- */