@talismn/balances 0.0.0-pr2075-20250710071608 → 0.0.0-pr2075-20250710094113

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.
Files changed (64) hide show
  1. package/dist/declarations/src/BalancesProvider.d.ts +1 -0
  2. package/dist/declarations/src/getMiniMetadatas/index.d.ts +1 -1
  3. package/dist/declarations/src/modules/evm-erc20/fetchBalances.d.ts +1 -1
  4. package/dist/declarations/src/modules/evm-erc20/fetchTokens.d.ts +1 -1
  5. package/dist/declarations/src/modules/evm-erc20/getMiniMetadata.d.ts +1 -1
  6. package/dist/declarations/src/modules/evm-erc20/getTransferCallData.d.ts +1 -1
  7. package/dist/declarations/src/modules/evm-erc20/module.d.ts +1 -1
  8. package/dist/declarations/src/modules/evm-erc20/subscribeBalances.d.ts +1 -1
  9. package/dist/declarations/src/modules/evm-native/fetchBalances.d.ts +1 -1
  10. package/dist/declarations/src/modules/evm-native/fetchTokens.d.ts +1 -1
  11. package/dist/declarations/src/modules/evm-native/getMiniMetadata.d.ts +1 -1
  12. package/dist/declarations/src/modules/evm-native/getTransferCallData.d.ts +1 -1
  13. package/dist/declarations/src/modules/evm-native/module.d.ts +1 -1
  14. package/dist/declarations/src/modules/evm-native/subscribeBalances.d.ts +1 -1
  15. package/dist/declarations/src/modules/evm-uniswapv2/fetchBalances.d.ts +1 -1
  16. package/dist/declarations/src/modules/evm-uniswapv2/fetchTokens.d.ts +1 -1
  17. package/dist/declarations/src/modules/evm-uniswapv2/getMiniMetadata.d.ts +1 -1
  18. package/dist/declarations/src/modules/evm-uniswapv2/getTransferCallData.d.ts +1 -1
  19. package/dist/declarations/src/modules/evm-uniswapv2/module.d.ts +1 -1
  20. package/dist/declarations/src/modules/evm-uniswapv2/subscribeBalances.d.ts +1 -1
  21. package/dist/declarations/src/modules/index.d.ts +10 -10
  22. package/dist/declarations/src/modules/shared/types.d.ts +2 -2
  23. package/dist/declarations/src/modules/substrate-assets/fetchBalances.d.ts +1 -1
  24. package/dist/declarations/src/modules/substrate-assets/fetchTokens.d.ts +1 -1
  25. package/dist/declarations/src/modules/substrate-assets/getMiniMetadata.d.ts +1 -1
  26. package/dist/declarations/src/modules/substrate-assets/getTransferCallData.d.ts +1 -1
  27. package/dist/declarations/src/modules/substrate-assets/module.d.ts +1 -1
  28. package/dist/declarations/src/modules/substrate-assets/subscribeBalances.d.ts +1 -1
  29. package/dist/declarations/src/modules/substrate-foreignassets/fetchBalances.d.ts +1 -1
  30. package/dist/declarations/src/modules/substrate-foreignassets/fetchTokens.d.ts +1 -1
  31. package/dist/declarations/src/modules/substrate-foreignassets/getMiniMetadata.d.ts +1 -1
  32. package/dist/declarations/src/modules/substrate-foreignassets/getTransferCallData.d.ts +1 -1
  33. package/dist/declarations/src/modules/substrate-foreignassets/module.d.ts +1 -1
  34. package/dist/declarations/src/modules/substrate-foreignassets/subscribeBalances.d.ts +1 -1
  35. package/dist/declarations/src/modules/substrate-hydration/fetchBalances.d.ts +1 -1
  36. package/dist/declarations/src/modules/substrate-hydration/fetchTokens.d.ts +1 -1
  37. package/dist/declarations/src/modules/substrate-hydration/getMiniMetadata.d.ts +1 -1
  38. package/dist/declarations/src/modules/substrate-hydration/getTransferCallData.d.ts +1 -1
  39. package/dist/declarations/src/modules/substrate-hydration/module.d.ts +1 -1
  40. package/dist/declarations/src/modules/substrate-hydration/subscribeBalances.d.ts +1 -1
  41. package/dist/declarations/src/modules/substrate-native/fetchBalances.d.ts +1 -1
  42. package/dist/declarations/src/modules/substrate-native/fetchTokens.d.ts +1 -1
  43. package/dist/declarations/src/modules/substrate-native/getMiniMetadata.d.ts +1 -1
  44. package/dist/declarations/src/modules/substrate-native/getTransferCallData.d.ts +1 -1
  45. package/dist/declarations/src/modules/substrate-native/module.d.ts +1 -1
  46. package/dist/declarations/src/modules/substrate-native/subscribeBalances.d.ts +1 -1
  47. package/dist/declarations/src/modules/substrate-psp22/fetchBalances.d.ts +1 -1
  48. package/dist/declarations/src/modules/substrate-psp22/fetchTokens.d.ts +1 -1
  49. package/dist/declarations/src/modules/substrate-psp22/getMiniMetadata.d.ts +1 -1
  50. package/dist/declarations/src/modules/substrate-psp22/getTransferCallData.d.ts +1 -1
  51. package/dist/declarations/src/modules/substrate-psp22/module.d.ts +1 -1
  52. package/dist/declarations/src/modules/substrate-psp22/subscribeBalances.d.ts +1 -1
  53. package/dist/declarations/src/modules/substrate-tokens/fetchBalances.d.ts +1 -1
  54. package/dist/declarations/src/modules/substrate-tokens/fetchTokens.d.ts +1 -1
  55. package/dist/declarations/src/modules/substrate-tokens/getMiniMetadata.d.ts +1 -1
  56. package/dist/declarations/src/modules/substrate-tokens/getTransferCallData.d.ts +1 -1
  57. package/dist/declarations/src/modules/substrate-tokens/module.d.ts +1 -1
  58. package/dist/declarations/src/modules/substrate-tokens/subscribeBalances.d.ts +1 -1
  59. package/dist/declarations/src/{modules → types}/IBalanceModule.d.ts +16 -26
  60. package/dist/declarations/src/types/index.d.ts +1 -0
  61. package/dist/talismn-balances.cjs.dev.js +61 -57
  62. package/dist/talismn-balances.cjs.prod.js +61 -57
  63. package/dist/talismn-balances.esm.js +64 -60
  64. package/package.json +8 -8
@@ -2570,7 +2570,7 @@ const deriveMiniMetadataId = ({
2570
2570
  source,
2571
2571
  chainId,
2572
2572
  specVersion
2573
- }) => scale.toHex(scale.Twox64Concat(new TextEncoder().encode(`${source}${chainId}${specVersion}${chaindataProvider.MINIMETADATA_VERSION}`))).slice(-64);
2573
+ }) => scale.toHex(scale.Twox128(new TextEncoder().encode(`${source}${chainId}${specVersion}${chaindataProvider.MINIMETADATA_VERSION}`))).slice(-32);
2574
2574
 
2575
2575
  const getMiniMetadata$5 = ({
2576
2576
  networkId,
@@ -3572,11 +3572,11 @@ const fetchStakeInfoByAddress = async (connector, networkId, miniMetadata, addre
3572
3572
 
3573
3573
  // assume dynamic info doesnt change over the course of a browser session
3574
3574
  const dynamicInfoCache = new Map();
3575
- const getCacheKey = (networkId, netuid) => `${networkId}:${netuid}`;
3575
+ const getCacheKey$1 = (networkId, netuid) => `${networkId}:${netuid}`;
3576
3576
  const fetchDynamicInfoByNetuid = async (connector, networkId, miniMetadata, uniqueNetuids) => {
3577
3577
  const fetchInfo = async netuid => {
3578
3578
  if (netuid === SUBTENSOR_ROOT_NETUID) return null;
3579
- const cacheKey = getCacheKey(networkId, netuid);
3579
+ const cacheKey = getCacheKey$1(networkId, netuid);
3580
3580
  if (!dynamicInfoCache.has(cacheKey)) {
3581
3581
  await viem.withRetry(async () => {
3582
3582
  const result = await fetchRuntimeCallResult(connector, networkId, miniMetadata.data, "SubnetInfoRuntimeApi", "get_dynamic_info", [netuid]);
@@ -6192,42 +6192,37 @@ const getSpecVersion = async (chainConnector, networkId) => {
6192
6192
  }
6193
6193
  };
6194
6194
 
6195
- // share requests as all modules will call this at once
6195
+ const getCacheKey = (networkId, specVersion) => `${networkId}:${specVersion}`;
6196
6196
  const CACHE = new Map();
6197
6197
 
6198
6198
  // ensures we dont fetch miniMetadatas on more than 4 chains at once
6199
6199
  const POOL = new PQueue__default.default({
6200
6200
  concurrency: 4
6201
6201
  });
6202
- const getMiniMetadatas = async (chainConnector, chaindataProvider, networkId, specVersion, signal) => {
6203
- if (CACHE.has(networkId)) return CACHE.get(networkId);
6204
- if (!signal) log.warn("[miniMetadata] getMiniMetadatas called without signal, this may hang the updates", new Error("No signal provided") // this will show the stack trace so the culprit can fix it
6205
- );
6202
+ const getMiniMetadatas = async (chainConnector, chaindataProvider, networkId, specVersion) => {
6206
6203
  if (specVersion === undefined) specVersion = await getSpecVersion(chainConnector, networkId);
6207
- const pResult = POOL.add(() => fetchMiniMetadatas(chainConnector, chaindataProvider, networkId, specVersion), {
6208
- signal
6209
- });
6210
- CACHE.set(networkId, pResult);
6204
+ const cacheKey = getCacheKey(networkId, specVersion);
6205
+ if (CACHE.has(cacheKey)) return CACHE.get(cacheKey);
6206
+ const pResult = POOL.add(() => fetchMiniMetadatas(chainConnector, chaindataProvider, networkId, specVersion));
6207
+
6208
+ // keep the results in cache (unless call fails) as observables call this function a lot of times
6209
+ CACHE.set(cacheKey, pResult);
6211
6210
  try {
6212
6211
  return await pResult;
6213
6212
  } catch (cause) {
6214
- if (util.isAbortError(cause)) throw cause;
6213
+ CACHE.delete(cacheKey);
6215
6214
  throw new Error(`Failed to fetch metadataRpc for network ${networkId}`, {
6216
6215
  cause
6217
6216
  });
6218
- } finally {
6219
- CACHE.delete(networkId);
6220
6217
  }
6221
6218
  };
6222
- const fetchMiniMetadatas = async (chainConnector, chaindataProvider, chainId, specVersion, signal) => {
6219
+ const fetchMiniMetadatas = async (chainConnector, chaindataProvider, chainId, specVersion) => {
6223
6220
  const start = performance.now();
6224
6221
  log.info("[miniMetadata] fetching minimetadatas for %s", chainId);
6225
6222
  try {
6226
6223
  const network = await chaindataProvider.getNetworkById(chainId, "polkadot");
6227
6224
  if (!network) throw new Error(`Network ${chainId} not found in chaindataProvider`);
6228
- signal?.throwIfAborted();
6229
6225
  const metadataRpc = await getMetadataRpc(chainConnector, chainId);
6230
- signal?.throwIfAborted();
6231
6226
  return Promise.all(BALANCE_MODULES.filter(m => m.platform === "polkadot").map(mod => mod.getMiniMetadata({
6232
6227
  networkId: chainId,
6233
6228
  metadataRpc,
@@ -6264,6 +6259,9 @@ class BalancesProvider {
6264
6259
  miniMetadatas: lodashEs.values(miniMetadatas).filter(util.isNotNil)
6265
6260
  })));
6266
6261
  }
6262
+ get storedMiniMetadataMapById$() {
6263
+ return this.#storage.pipe(rxjs.map(storage => lodashEs.keyBy(storage.miniMetadatas, m => m.id)), rxjs.distinctUntilChanged(lodashEs.isEqual), rxjs.shareReplay(1));
6264
+ }
6267
6265
 
6268
6266
  // this is the only public method
6269
6267
  getBalances$(addressesByTokenId) {
@@ -6393,46 +6391,52 @@ class BalancesProvider {
6393
6391
  return this.#chaindataProvider.getNetworkById$(networkId).pipe(rxjs.switchMap(network => chaindataProvider.isNetworkDot(network) && this.#chainConnectors.substrate ? rxjs.from(getSpecVersion(this.#chainConnectors.substrate, networkId)).pipe(rxjs.switchMap(specVersion => this.getMiniMetadatas$(networkId, specVersion))) : rxjs.of([])));
6394
6392
  }
6395
6393
  getMiniMetadatas$(networkId, specVersion) {
6396
- return new rxjs.Observable(subscriber => {
6397
- const controller = new AbortController();
6398
- const subscription = rxjs.combineLatest({
6399
- defaultMiniMetadatas: this.getDefaultMiniMetadatas$(networkId, specVersion),
6400
- storedMiniMetadatas: this.getStoredMiniMetadatas$(networkId, specVersion)
6401
- }).pipe(rxjs.switchMap(({
6402
- storedMiniMetadatas,
6403
- defaultMiniMetadatas
6404
- }) => {
6405
- if (defaultMiniMetadatas.length) return rxjs.of(defaultMiniMetadatas);
6406
- if (storedMiniMetadatas.length) return rxjs.of(storedMiniMetadatas);
6407
- if (!this.#chainConnectors.substrate) return rxjs.of([]);
6408
- return rxjs.from(
6409
- // fetch them from the chain
6410
- getMiniMetadatas(this.#chainConnectors.substrate, this.#chaindataProvider, networkId, specVersion, controller.signal)).pipe(
6411
- // and persist in storage for later reuse
6412
- rxjs.tap(newMiniMetadatas => {
6413
- if (!newMiniMetadatas.length) return;
6414
- const storage = this.#storage.getValue();
6415
- const miniMetadatas = lodashEs.assign(
6416
- // keep minimetadatas of other networks
6417
- lodashEs.keyBy(lodashEs.values(storage.miniMetadatas).filter(m => m.chainId !== networkId), m => m.id),
6418
- // add the ones for our network
6419
- lodashEs.keyBy(newMiniMetadatas, m => m.id));
6420
- this.#storage.next(lodashEs.assign({}, storage, {
6421
- miniMetadatas
6422
- }));
6394
+ const miniMetadataIds = BALANCE_MODULES.filter(mod => mod.platform === "polkadot").map(mod => deriveMiniMetadataId({
6395
+ chainId: networkId,
6396
+ specVersion,
6397
+ source: mod.type
6398
+ }));
6399
+ return rxjs.combineLatest({
6400
+ defaultMiniMetadatas: this.getDefaultMiniMetadatas$(miniMetadataIds),
6401
+ storedMiniMetadatas: this.getStoredMiniMetadatas$(miniMetadataIds)
6402
+ }).pipe(rxjs.switchMap(({
6403
+ storedMiniMetadatas,
6404
+ defaultMiniMetadatas
6405
+ }) => {
6406
+ if (defaultMiniMetadatas) return rxjs.of(defaultMiniMetadatas);
6407
+ if (storedMiniMetadatas) return rxjs.of(storedMiniMetadatas);
6408
+ if (!this.#chainConnectors.substrate) return rxjs.of([]);
6409
+ return rxjs.from(getMiniMetadatas(this.#chainConnectors.substrate, this.#chaindataProvider, networkId, specVersion)).pipe(
6410
+ // and persist in storage for later reuse
6411
+ rxjs.tap(newMiniMetadatas => {
6412
+ if (!newMiniMetadatas.length) return;
6413
+ const storage = this.#storage.getValue();
6414
+ const miniMetadatas = lodashEs.assign(
6415
+ // keep minimetadatas of other networks
6416
+ lodashEs.keyBy(lodashEs.values(storage.miniMetadatas).filter(m => m.chainId !== networkId), m => m.id),
6417
+ // add the ones for our network
6418
+ lodashEs.keyBy(newMiniMetadatas, m => m.id));
6419
+ this.#storage.next(lodashEs.assign({}, storage, {
6420
+ miniMetadatas
6423
6421
  }));
6424
- })).subscribe(subscriber);
6425
- return () => {
6426
- subscription.unsubscribe();
6427
- controller.abort();
6428
- };
6429
- });
6430
- }
6431
- getStoredMiniMetadatas$(networkId, specVersion) {
6432
- return this.storage$.pipe(rxjs.map(storage => storage.miniMetadatas.filter(m => m.chainId === networkId && m.specVersion === specVersion && m.version === chaindataProvider.MINIMETADATA_VERSION)), rxjs.distinctUntilChanged(lodashEs.isEqual));
6433
- }
6434
- getDefaultMiniMetadatas$(networkId, specVersion) {
6435
- return this.#chaindataProvider.miniMetadatas$.pipe(rxjs.map(miniMetadatas => miniMetadatas.filter(m => m.chainId === networkId && m.specVersion === specVersion && m.version === chaindataProvider.MINIMETADATA_VERSION)), rxjs.distinctUntilChanged(lodashEs.isEqual));
6422
+ }));
6423
+ }),
6424
+ // emit only when mini metadata changes, as a change here would restart all subscriptions for the network
6425
+ rxjs.distinctUntilChanged(lodashEs.isEqual));
6426
+ }
6427
+ getStoredMiniMetadatas$(miniMetadataIds) {
6428
+ return this.storedMiniMetadataMapById$.pipe(rxjs.map(mapById => {
6429
+ const miniMetadatas = miniMetadataIds.map(id => mapById[id]);
6430
+ return miniMetadatas.length && miniMetadatas.every(util.isTruthy) ? miniMetadatas : null;
6431
+ }),
6432
+ // source changes very often
6433
+ rxjs.distinctUntilChanged(lodashEs.isEqual));
6434
+ }
6435
+ getDefaultMiniMetadatas$(miniMetadataIds) {
6436
+ return this.#chaindataProvider.miniMetadatasMapById$.pipe(rxjs.map(mapById => {
6437
+ const miniMetadatas = miniMetadataIds.map(id => mapById[id]);
6438
+ return miniMetadatas.length && miniMetadatas.every(util.isTruthy) ? miniMetadatas : null;
6439
+ }));
6436
6440
  }
6437
6441
  getStoredBalances(addressesByToken) {
6438
6442
  const balanceDefs = lodashEs.toPairs(addressesByToken).flatMap(([tokenId, addresses]) => addresses.map(address => [tokenId, address]));
@@ -2570,7 +2570,7 @@ const deriveMiniMetadataId = ({
2570
2570
  source,
2571
2571
  chainId,
2572
2572
  specVersion
2573
- }) => scale.toHex(scale.Twox64Concat(new TextEncoder().encode(`${source}${chainId}${specVersion}${chaindataProvider.MINIMETADATA_VERSION}`))).slice(-64);
2573
+ }) => scale.toHex(scale.Twox128(new TextEncoder().encode(`${source}${chainId}${specVersion}${chaindataProvider.MINIMETADATA_VERSION}`))).slice(-32);
2574
2574
 
2575
2575
  const getMiniMetadata$5 = ({
2576
2576
  networkId,
@@ -3572,11 +3572,11 @@ const fetchStakeInfoByAddress = async (connector, networkId, miniMetadata, addre
3572
3572
 
3573
3573
  // assume dynamic info doesnt change over the course of a browser session
3574
3574
  const dynamicInfoCache = new Map();
3575
- const getCacheKey = (networkId, netuid) => `${networkId}:${netuid}`;
3575
+ const getCacheKey$1 = (networkId, netuid) => `${networkId}:${netuid}`;
3576
3576
  const fetchDynamicInfoByNetuid = async (connector, networkId, miniMetadata, uniqueNetuids) => {
3577
3577
  const fetchInfo = async netuid => {
3578
3578
  if (netuid === SUBTENSOR_ROOT_NETUID) return null;
3579
- const cacheKey = getCacheKey(networkId, netuid);
3579
+ const cacheKey = getCacheKey$1(networkId, netuid);
3580
3580
  if (!dynamicInfoCache.has(cacheKey)) {
3581
3581
  await viem.withRetry(async () => {
3582
3582
  const result = await fetchRuntimeCallResult(connector, networkId, miniMetadata.data, "SubnetInfoRuntimeApi", "get_dynamic_info", [netuid]);
@@ -6192,42 +6192,37 @@ const getSpecVersion = async (chainConnector, networkId) => {
6192
6192
  }
6193
6193
  };
6194
6194
 
6195
- // share requests as all modules will call this at once
6195
+ const getCacheKey = (networkId, specVersion) => `${networkId}:${specVersion}`;
6196
6196
  const CACHE = new Map();
6197
6197
 
6198
6198
  // ensures we dont fetch miniMetadatas on more than 4 chains at once
6199
6199
  const POOL = new PQueue__default.default({
6200
6200
  concurrency: 4
6201
6201
  });
6202
- const getMiniMetadatas = async (chainConnector, chaindataProvider, networkId, specVersion, signal) => {
6203
- if (CACHE.has(networkId)) return CACHE.get(networkId);
6204
- if (!signal) log.warn("[miniMetadata] getMiniMetadatas called without signal, this may hang the updates", new Error("No signal provided") // this will show the stack trace so the culprit can fix it
6205
- );
6202
+ const getMiniMetadatas = async (chainConnector, chaindataProvider, networkId, specVersion) => {
6206
6203
  if (specVersion === undefined) specVersion = await getSpecVersion(chainConnector, networkId);
6207
- const pResult = POOL.add(() => fetchMiniMetadatas(chainConnector, chaindataProvider, networkId, specVersion), {
6208
- signal
6209
- });
6210
- CACHE.set(networkId, pResult);
6204
+ const cacheKey = getCacheKey(networkId, specVersion);
6205
+ if (CACHE.has(cacheKey)) return CACHE.get(cacheKey);
6206
+ const pResult = POOL.add(() => fetchMiniMetadatas(chainConnector, chaindataProvider, networkId, specVersion));
6207
+
6208
+ // keep the results in cache (unless call fails) as observables call this function a lot of times
6209
+ CACHE.set(cacheKey, pResult);
6211
6210
  try {
6212
6211
  return await pResult;
6213
6212
  } catch (cause) {
6214
- if (util.isAbortError(cause)) throw cause;
6213
+ CACHE.delete(cacheKey);
6215
6214
  throw new Error(`Failed to fetch metadataRpc for network ${networkId}`, {
6216
6215
  cause
6217
6216
  });
6218
- } finally {
6219
- CACHE.delete(networkId);
6220
6217
  }
6221
6218
  };
6222
- const fetchMiniMetadatas = async (chainConnector, chaindataProvider, chainId, specVersion, signal) => {
6219
+ const fetchMiniMetadatas = async (chainConnector, chaindataProvider, chainId, specVersion) => {
6223
6220
  const start = performance.now();
6224
6221
  log.info("[miniMetadata] fetching minimetadatas for %s", chainId);
6225
6222
  try {
6226
6223
  const network = await chaindataProvider.getNetworkById(chainId, "polkadot");
6227
6224
  if (!network) throw new Error(`Network ${chainId} not found in chaindataProvider`);
6228
- signal?.throwIfAborted();
6229
6225
  const metadataRpc = await getMetadataRpc(chainConnector, chainId);
6230
- signal?.throwIfAborted();
6231
6226
  return Promise.all(BALANCE_MODULES.filter(m => m.platform === "polkadot").map(mod => mod.getMiniMetadata({
6232
6227
  networkId: chainId,
6233
6228
  metadataRpc,
@@ -6264,6 +6259,9 @@ class BalancesProvider {
6264
6259
  miniMetadatas: lodashEs.values(miniMetadatas).filter(util.isNotNil)
6265
6260
  })));
6266
6261
  }
6262
+ get storedMiniMetadataMapById$() {
6263
+ return this.#storage.pipe(rxjs.map(storage => lodashEs.keyBy(storage.miniMetadatas, m => m.id)), rxjs.distinctUntilChanged(lodashEs.isEqual), rxjs.shareReplay(1));
6264
+ }
6267
6265
 
6268
6266
  // this is the only public method
6269
6267
  getBalances$(addressesByTokenId) {
@@ -6393,46 +6391,52 @@ class BalancesProvider {
6393
6391
  return this.#chaindataProvider.getNetworkById$(networkId).pipe(rxjs.switchMap(network => chaindataProvider.isNetworkDot(network) && this.#chainConnectors.substrate ? rxjs.from(getSpecVersion(this.#chainConnectors.substrate, networkId)).pipe(rxjs.switchMap(specVersion => this.getMiniMetadatas$(networkId, specVersion))) : rxjs.of([])));
6394
6392
  }
6395
6393
  getMiniMetadatas$(networkId, specVersion) {
6396
- return new rxjs.Observable(subscriber => {
6397
- const controller = new AbortController();
6398
- const subscription = rxjs.combineLatest({
6399
- defaultMiniMetadatas: this.getDefaultMiniMetadatas$(networkId, specVersion),
6400
- storedMiniMetadatas: this.getStoredMiniMetadatas$(networkId, specVersion)
6401
- }).pipe(rxjs.switchMap(({
6402
- storedMiniMetadatas,
6403
- defaultMiniMetadatas
6404
- }) => {
6405
- if (defaultMiniMetadatas.length) return rxjs.of(defaultMiniMetadatas);
6406
- if (storedMiniMetadatas.length) return rxjs.of(storedMiniMetadatas);
6407
- if (!this.#chainConnectors.substrate) return rxjs.of([]);
6408
- return rxjs.from(
6409
- // fetch them from the chain
6410
- getMiniMetadatas(this.#chainConnectors.substrate, this.#chaindataProvider, networkId, specVersion, controller.signal)).pipe(
6411
- // and persist in storage for later reuse
6412
- rxjs.tap(newMiniMetadatas => {
6413
- if (!newMiniMetadatas.length) return;
6414
- const storage = this.#storage.getValue();
6415
- const miniMetadatas = lodashEs.assign(
6416
- // keep minimetadatas of other networks
6417
- lodashEs.keyBy(lodashEs.values(storage.miniMetadatas).filter(m => m.chainId !== networkId), m => m.id),
6418
- // add the ones for our network
6419
- lodashEs.keyBy(newMiniMetadatas, m => m.id));
6420
- this.#storage.next(lodashEs.assign({}, storage, {
6421
- miniMetadatas
6422
- }));
6394
+ const miniMetadataIds = BALANCE_MODULES.filter(mod => mod.platform === "polkadot").map(mod => deriveMiniMetadataId({
6395
+ chainId: networkId,
6396
+ specVersion,
6397
+ source: mod.type
6398
+ }));
6399
+ return rxjs.combineLatest({
6400
+ defaultMiniMetadatas: this.getDefaultMiniMetadatas$(miniMetadataIds),
6401
+ storedMiniMetadatas: this.getStoredMiniMetadatas$(miniMetadataIds)
6402
+ }).pipe(rxjs.switchMap(({
6403
+ storedMiniMetadatas,
6404
+ defaultMiniMetadatas
6405
+ }) => {
6406
+ if (defaultMiniMetadatas) return rxjs.of(defaultMiniMetadatas);
6407
+ if (storedMiniMetadatas) return rxjs.of(storedMiniMetadatas);
6408
+ if (!this.#chainConnectors.substrate) return rxjs.of([]);
6409
+ return rxjs.from(getMiniMetadatas(this.#chainConnectors.substrate, this.#chaindataProvider, networkId, specVersion)).pipe(
6410
+ // and persist in storage for later reuse
6411
+ rxjs.tap(newMiniMetadatas => {
6412
+ if (!newMiniMetadatas.length) return;
6413
+ const storage = this.#storage.getValue();
6414
+ const miniMetadatas = lodashEs.assign(
6415
+ // keep minimetadatas of other networks
6416
+ lodashEs.keyBy(lodashEs.values(storage.miniMetadatas).filter(m => m.chainId !== networkId), m => m.id),
6417
+ // add the ones for our network
6418
+ lodashEs.keyBy(newMiniMetadatas, m => m.id));
6419
+ this.#storage.next(lodashEs.assign({}, storage, {
6420
+ miniMetadatas
6423
6421
  }));
6424
- })).subscribe(subscriber);
6425
- return () => {
6426
- subscription.unsubscribe();
6427
- controller.abort();
6428
- };
6429
- });
6430
- }
6431
- getStoredMiniMetadatas$(networkId, specVersion) {
6432
- return this.storage$.pipe(rxjs.map(storage => storage.miniMetadatas.filter(m => m.chainId === networkId && m.specVersion === specVersion && m.version === chaindataProvider.MINIMETADATA_VERSION)), rxjs.distinctUntilChanged(lodashEs.isEqual));
6433
- }
6434
- getDefaultMiniMetadatas$(networkId, specVersion) {
6435
- return this.#chaindataProvider.miniMetadatas$.pipe(rxjs.map(miniMetadatas => miniMetadatas.filter(m => m.chainId === networkId && m.specVersion === specVersion && m.version === chaindataProvider.MINIMETADATA_VERSION)), rxjs.distinctUntilChanged(lodashEs.isEqual));
6422
+ }));
6423
+ }),
6424
+ // emit only when mini metadata changes, as a change here would restart all subscriptions for the network
6425
+ rxjs.distinctUntilChanged(lodashEs.isEqual));
6426
+ }
6427
+ getStoredMiniMetadatas$(miniMetadataIds) {
6428
+ return this.storedMiniMetadataMapById$.pipe(rxjs.map(mapById => {
6429
+ const miniMetadatas = miniMetadataIds.map(id => mapById[id]);
6430
+ return miniMetadatas.length && miniMetadatas.every(util.isTruthy) ? miniMetadatas : null;
6431
+ }),
6432
+ // source changes very often
6433
+ rxjs.distinctUntilChanged(lodashEs.isEqual));
6434
+ }
6435
+ getDefaultMiniMetadatas$(miniMetadataIds) {
6436
+ return this.#chaindataProvider.miniMetadatasMapById$.pipe(rxjs.map(mapById => {
6437
+ const miniMetadatas = miniMetadataIds.map(id => mapById[id]);
6438
+ return miniMetadatas.length && miniMetadatas.every(util.isTruthy) ? miniMetadatas : null;
6439
+ }));
6436
6440
  }
6437
6441
  getStoredBalances(addressesByToken) {
6438
6442
  const balanceDefs = lodashEs.toPairs(addressesByToken).flatMap(([tokenId, addresses]) => addresses.map(address => [tokenId, address]));
@@ -1,12 +1,12 @@
1
1
  import { EvmErc20TokenSchema, parseTokenId, parseEvmErc20TokenId, evmErc20TokenId, isTokenOfType, TokenBaseSchema, EvmNativeTokenSchema, evmNativeTokenId, EvmUniswapV2TokenSchema, evmUniswapV2TokenId, SubAssetsTokenSchema, subAssetTokenId, MINIMETADATA_VERSION, SubForeignAssetsTokenSchema, subForeignAssetTokenId, SubHydrationTokenSchema, subHydrationTokenId, SubNativeTokenSchema, subNativeTokenId, SubPsp22TokenSchema, subPsp22TokenId, SubTokensTokenSchema, subTokensTokenId, isNetworkDot } from '@talismn/chaindata-provider';
2
2
  export { MINIMETADATA_VERSION } from '@talismn/chaindata-provider';
3
- import { isEthereumAddress, isNotNil, BigMath, isArrayOf, isBigInt, planckToTokens, isAbortError, getSharedObservable } from '@talismn/util';
3
+ import { isEthereumAddress, isNotNil, BigMath, isArrayOf, isBigInt, planckToTokens, isAbortError, getSharedObservable, isTruthy } from '@talismn/util';
4
4
  import { parseAbi, erc20Abi, getContract, ContractFunctionExecutionError, hexToString, erc20Abi_bytes32, encodeFunctionData, withRetry } from 'viem';
5
5
  import { assign, omit, isEqual, keyBy, keys, uniq, fromPairs, values, toPairs } from 'lodash-es';
6
6
  import z from 'zod/v4';
7
7
  import anylogger from 'anylogger';
8
- import { of, Observable, distinctUntilChanged, map, timer, switchMap, from, firstValueFrom, combineLatest, BehaviorSubject, startWith, filter, tap } from 'rxjs';
9
- import { parseMetadataRpc, toHex, unifyMetadata, decAnyMetadata, getDynamicBuilder, getLookupFn, decodeScale, getStorageKeyPrefix, Twox64Concat, compactMetadata, encodeMetadata, papiParse, papiStringify } from '@talismn/scale';
8
+ import { of, Observable, distinctUntilChanged, map, timer, switchMap, from, firstValueFrom, combineLatest, BehaviorSubject, shareReplay, startWith, filter, tap } from 'rxjs';
9
+ import { parseMetadataRpc, toHex, unifyMetadata, decAnyMetadata, getDynamicBuilder, getLookupFn, decodeScale, getStorageKeyPrefix, Twox128, compactMetadata, encodeMetadata, papiParse, papiStringify } from '@talismn/scale';
10
10
  import { newTokenRates } from '@talismn/token-rates';
11
11
  import BigNumber from 'bignumber.js';
12
12
  import { mergeUint8 } from '@polkadot-api/utils';
@@ -2561,7 +2561,7 @@ const deriveMiniMetadataId = ({
2561
2561
  source,
2562
2562
  chainId,
2563
2563
  specVersion
2564
- }) => toHex(Twox64Concat(new TextEncoder().encode(`${source}${chainId}${specVersion}${MINIMETADATA_VERSION}`))).slice(-64);
2564
+ }) => toHex(Twox128(new TextEncoder().encode(`${source}${chainId}${specVersion}${MINIMETADATA_VERSION}`))).slice(-32);
2565
2565
 
2566
2566
  const getMiniMetadata$5 = ({
2567
2567
  networkId,
@@ -3563,11 +3563,11 @@ const fetchStakeInfoByAddress = async (connector, networkId, miniMetadata, addre
3563
3563
 
3564
3564
  // assume dynamic info doesnt change over the course of a browser session
3565
3565
  const dynamicInfoCache = new Map();
3566
- const getCacheKey = (networkId, netuid) => `${networkId}:${netuid}`;
3566
+ const getCacheKey$1 = (networkId, netuid) => `${networkId}:${netuid}`;
3567
3567
  const fetchDynamicInfoByNetuid = async (connector, networkId, miniMetadata, uniqueNetuids) => {
3568
3568
  const fetchInfo = async netuid => {
3569
3569
  if (netuid === SUBTENSOR_ROOT_NETUID) return null;
3570
- const cacheKey = getCacheKey(networkId, netuid);
3570
+ const cacheKey = getCacheKey$1(networkId, netuid);
3571
3571
  if (!dynamicInfoCache.has(cacheKey)) {
3572
3572
  await withRetry(async () => {
3573
3573
  const result = await fetchRuntimeCallResult(connector, networkId, miniMetadata.data, "SubnetInfoRuntimeApi", "get_dynamic_info", [netuid]);
@@ -6183,42 +6183,37 @@ const getSpecVersion = async (chainConnector, networkId) => {
6183
6183
  }
6184
6184
  };
6185
6185
 
6186
- // share requests as all modules will call this at once
6186
+ const getCacheKey = (networkId, specVersion) => `${networkId}:${specVersion}`;
6187
6187
  const CACHE = new Map();
6188
6188
 
6189
6189
  // ensures we dont fetch miniMetadatas on more than 4 chains at once
6190
6190
  const POOL = new PQueue({
6191
6191
  concurrency: 4
6192
6192
  });
6193
- const getMiniMetadatas = async (chainConnector, chaindataProvider, networkId, specVersion, signal) => {
6194
- if (CACHE.has(networkId)) return CACHE.get(networkId);
6195
- if (!signal) log.warn("[miniMetadata] getMiniMetadatas called without signal, this may hang the updates", new Error("No signal provided") // this will show the stack trace so the culprit can fix it
6196
- );
6193
+ const getMiniMetadatas = async (chainConnector, chaindataProvider, networkId, specVersion) => {
6197
6194
  if (specVersion === undefined) specVersion = await getSpecVersion(chainConnector, networkId);
6198
- const pResult = POOL.add(() => fetchMiniMetadatas(chainConnector, chaindataProvider, networkId, specVersion), {
6199
- signal
6200
- });
6201
- CACHE.set(networkId, pResult);
6195
+ const cacheKey = getCacheKey(networkId, specVersion);
6196
+ if (CACHE.has(cacheKey)) return CACHE.get(cacheKey);
6197
+ const pResult = POOL.add(() => fetchMiniMetadatas(chainConnector, chaindataProvider, networkId, specVersion));
6198
+
6199
+ // keep the results in cache (unless call fails) as observables call this function a lot of times
6200
+ CACHE.set(cacheKey, pResult);
6202
6201
  try {
6203
6202
  return await pResult;
6204
6203
  } catch (cause) {
6205
- if (isAbortError(cause)) throw cause;
6204
+ CACHE.delete(cacheKey);
6206
6205
  throw new Error(`Failed to fetch metadataRpc for network ${networkId}`, {
6207
6206
  cause
6208
6207
  });
6209
- } finally {
6210
- CACHE.delete(networkId);
6211
6208
  }
6212
6209
  };
6213
- const fetchMiniMetadatas = async (chainConnector, chaindataProvider, chainId, specVersion, signal) => {
6210
+ const fetchMiniMetadatas = async (chainConnector, chaindataProvider, chainId, specVersion) => {
6214
6211
  const start = performance.now();
6215
6212
  log.info("[miniMetadata] fetching minimetadatas for %s", chainId);
6216
6213
  try {
6217
6214
  const network = await chaindataProvider.getNetworkById(chainId, "polkadot");
6218
6215
  if (!network) throw new Error(`Network ${chainId} not found in chaindataProvider`);
6219
- signal?.throwIfAborted();
6220
6216
  const metadataRpc = await getMetadataRpc(chainConnector, chainId);
6221
- signal?.throwIfAborted();
6222
6217
  return Promise.all(BALANCE_MODULES.filter(m => m.platform === "polkadot").map(mod => mod.getMiniMetadata({
6223
6218
  networkId: chainId,
6224
6219
  metadataRpc,
@@ -6255,6 +6250,9 @@ class BalancesProvider {
6255
6250
  miniMetadatas: values(miniMetadatas).filter(isNotNil)
6256
6251
  })));
6257
6252
  }
6253
+ get storedMiniMetadataMapById$() {
6254
+ return this.#storage.pipe(map(storage => keyBy(storage.miniMetadatas, m => m.id)), distinctUntilChanged(isEqual), shareReplay(1));
6255
+ }
6258
6256
 
6259
6257
  // this is the only public method
6260
6258
  getBalances$(addressesByTokenId) {
@@ -6384,46 +6382,52 @@ class BalancesProvider {
6384
6382
  return this.#chaindataProvider.getNetworkById$(networkId).pipe(switchMap(network => isNetworkDot(network) && this.#chainConnectors.substrate ? from(getSpecVersion(this.#chainConnectors.substrate, networkId)).pipe(switchMap(specVersion => this.getMiniMetadatas$(networkId, specVersion))) : of([])));
6385
6383
  }
6386
6384
  getMiniMetadatas$(networkId, specVersion) {
6387
- return new Observable(subscriber => {
6388
- const controller = new AbortController();
6389
- const subscription = combineLatest({
6390
- defaultMiniMetadatas: this.getDefaultMiniMetadatas$(networkId, specVersion),
6391
- storedMiniMetadatas: this.getStoredMiniMetadatas$(networkId, specVersion)
6392
- }).pipe(switchMap(({
6393
- storedMiniMetadatas,
6394
- defaultMiniMetadatas
6395
- }) => {
6396
- if (defaultMiniMetadatas.length) return of(defaultMiniMetadatas);
6397
- if (storedMiniMetadatas.length) return of(storedMiniMetadatas);
6398
- if (!this.#chainConnectors.substrate) return of([]);
6399
- return from(
6400
- // fetch them from the chain
6401
- getMiniMetadatas(this.#chainConnectors.substrate, this.#chaindataProvider, networkId, specVersion, controller.signal)).pipe(
6402
- // and persist in storage for later reuse
6403
- tap(newMiniMetadatas => {
6404
- if (!newMiniMetadatas.length) return;
6405
- const storage = this.#storage.getValue();
6406
- const miniMetadatas = assign(
6407
- // keep minimetadatas of other networks
6408
- keyBy(values(storage.miniMetadatas).filter(m => m.chainId !== networkId), m => m.id),
6409
- // add the ones for our network
6410
- keyBy(newMiniMetadatas, m => m.id));
6411
- this.#storage.next(assign({}, storage, {
6412
- miniMetadatas
6413
- }));
6385
+ const miniMetadataIds = BALANCE_MODULES.filter(mod => mod.platform === "polkadot").map(mod => deriveMiniMetadataId({
6386
+ chainId: networkId,
6387
+ specVersion,
6388
+ source: mod.type
6389
+ }));
6390
+ return combineLatest({
6391
+ defaultMiniMetadatas: this.getDefaultMiniMetadatas$(miniMetadataIds),
6392
+ storedMiniMetadatas: this.getStoredMiniMetadatas$(miniMetadataIds)
6393
+ }).pipe(switchMap(({
6394
+ storedMiniMetadatas,
6395
+ defaultMiniMetadatas
6396
+ }) => {
6397
+ if (defaultMiniMetadatas) return of(defaultMiniMetadatas);
6398
+ if (storedMiniMetadatas) return of(storedMiniMetadatas);
6399
+ if (!this.#chainConnectors.substrate) return of([]);
6400
+ return from(getMiniMetadatas(this.#chainConnectors.substrate, this.#chaindataProvider, networkId, specVersion)).pipe(
6401
+ // and persist in storage for later reuse
6402
+ tap(newMiniMetadatas => {
6403
+ if (!newMiniMetadatas.length) return;
6404
+ const storage = this.#storage.getValue();
6405
+ const miniMetadatas = assign(
6406
+ // keep minimetadatas of other networks
6407
+ keyBy(values(storage.miniMetadatas).filter(m => m.chainId !== networkId), m => m.id),
6408
+ // add the ones for our network
6409
+ keyBy(newMiniMetadatas, m => m.id));
6410
+ this.#storage.next(assign({}, storage, {
6411
+ miniMetadatas
6414
6412
  }));
6415
- })).subscribe(subscriber);
6416
- return () => {
6417
- subscription.unsubscribe();
6418
- controller.abort();
6419
- };
6420
- });
6421
- }
6422
- getStoredMiniMetadatas$(networkId, specVersion) {
6423
- return this.storage$.pipe(map(storage => storage.miniMetadatas.filter(m => m.chainId === networkId && m.specVersion === specVersion && m.version === MINIMETADATA_VERSION)), distinctUntilChanged(isEqual));
6424
- }
6425
- getDefaultMiniMetadatas$(networkId, specVersion) {
6426
- return this.#chaindataProvider.miniMetadatas$.pipe(map(miniMetadatas => miniMetadatas.filter(m => m.chainId === networkId && m.specVersion === specVersion && m.version === MINIMETADATA_VERSION)), distinctUntilChanged(isEqual));
6413
+ }));
6414
+ }),
6415
+ // emit only when mini metadata changes, as a change here would restart all subscriptions for the network
6416
+ distinctUntilChanged(isEqual));
6417
+ }
6418
+ getStoredMiniMetadatas$(miniMetadataIds) {
6419
+ return this.storedMiniMetadataMapById$.pipe(map(mapById => {
6420
+ const miniMetadatas = miniMetadataIds.map(id => mapById[id]);
6421
+ return miniMetadatas.length && miniMetadatas.every(isTruthy) ? miniMetadatas : null;
6422
+ }),
6423
+ // source changes very often
6424
+ distinctUntilChanged(isEqual));
6425
+ }
6426
+ getDefaultMiniMetadatas$(miniMetadataIds) {
6427
+ return this.#chaindataProvider.miniMetadatasMapById$.pipe(map(mapById => {
6428
+ const miniMetadatas = miniMetadataIds.map(id => mapById[id]);
6429
+ return miniMetadatas.length && miniMetadatas.every(isTruthy) ? miniMetadatas : null;
6430
+ }));
6427
6431
  }
6428
6432
  getStoredBalances(addressesByToken) {
6429
6433
  const balanceDefs = toPairs(addressesByToken).flatMap(([tokenId, addresses]) => addresses.map(address => [tokenId, address]));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@talismn/balances",
3
- "version": "0.0.0-pr2075-20250710071608",
3
+ "version": "0.0.0-pr2075-20250710094113",
4
4
  "author": "Talisman",
5
5
  "homepage": "https://talisman.xyz",
6
6
  "license": "GPL-3.0-or-later",
@@ -34,13 +34,13 @@
34
34
  "scale-ts": "^1.6.1",
35
35
  "viem": "^2.27.3",
36
36
  "zod": "^3.25.62",
37
- "@talismn/chain-connector-evm": "0.0.0-pr2075-20250710071608",
38
- "@talismn/chaindata-provider": "0.0.0-pr2075-20250710071608",
39
- "@talismn/chain-connector": "0.0.0-pr2075-20250710071608",
40
- "@talismn/sapi": "0.0.0-pr2075-20250710071608",
41
- "@talismn/scale": "0.0.0-pr2075-20250710071608",
42
- "@talismn/token-rates": "0.0.0-pr2075-20250710071608",
43
- "@talismn/util": "0.0.0-pr2075-20250710071608"
37
+ "@talismn/chain-connector-evm": "0.0.0-pr2075-20250710094113",
38
+ "@talismn/chain-connector": "0.0.0-pr2075-20250710094113",
39
+ "@talismn/chaindata-provider": "0.0.0-pr2075-20250710094113",
40
+ "@talismn/sapi": "0.0.0-pr2075-20250710094113",
41
+ "@talismn/scale": "0.0.0-pr2075-20250710094113",
42
+ "@talismn/util": "0.0.0-pr2075-20250710094113",
43
+ "@talismn/token-rates": "0.0.0-pr2075-20250710094113"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@polkadot/api-contract": "16.1.2",