@talismn/balances 0.0.0-pr2075-20250708110002 → 0.0.0-pr2075-20250708143919
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/declarations/src/BalancesProvider.d.ts +5 -1
- package/dist/declarations/src/modules/IBalanceModule.d.ts +1 -1
- package/dist/declarations/src/modules/SubstrateNativeModule/util/sortChains.d.ts +1 -1
- package/dist/declarations/src/modules/shared/types.d.ts +1 -4
- package/dist/declarations/src/modules/substrate-native/bittensor/getSubtensorStakingBalances.d.ts +3 -2
- package/dist/declarations/src/modules/substrate-native/queries/buildBaseQueries.d.ts +3 -5
- package/dist/declarations/src/modules/substrate-native/queries/buildNomPoolQueries.d.ts +3 -5
- package/dist/declarations/src/modules/util/rpcQueryPack.d.ts +10 -0
- package/dist/talismn-balances.cjs.dev.js +246 -257
- package/dist/talismn-balances.cjs.prod.js +246 -257
- package/dist/talismn-balances.esm.js +248 -259
- package/package.json +10 -10
- package/dist/declarations/src/modules/util/RpcStateQueriesHelper.d.ts +0 -12
@@ -11,9 +11,9 @@ 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,
|
14
|
+
import { Observable, distinctUntilChanged, of, map, timer, switchMap, from, firstValueFrom, combineLatest, scan, share, switchAll, mergeMap, toArray, interval, startWith, exhaustMap, BehaviorSubject, debounceTime, takeUntil, withLatestFrom, concatMap, filter, tap } from 'rxjs';
|
15
15
|
import isEqual$1 from 'lodash/isEqual';
|
16
|
-
import { unifyMetadata, decAnyMetadata, getDynamicBuilder, getLookupFn, decodeScale, parseMetadataRpc, getStorageKeyPrefix, compactMetadata, encodeMetadata, papiParse, papiStringify,
|
16
|
+
import { unifyMetadata, decAnyMetadata, getDynamicBuilder, getLookupFn, decodeScale, parseMetadataRpc, getStorageKeyPrefix, compactMetadata, encodeMetadata, toHex, papiParse, papiStringify, getMetadataVersion, encodeStateKey } from '@talismn/scale';
|
17
17
|
import { Metadata, TypeRegistry } from '@polkadot/types';
|
18
18
|
import groupBy from 'lodash/groupBy';
|
19
19
|
import { mergeUint8, toHex as toHex$1 } from '@polkadot-api/utils';
|
@@ -1766,7 +1766,7 @@ const getTransferCallData$8 = ({
|
|
1766
1766
|
};
|
1767
1767
|
};
|
1768
1768
|
|
1769
|
-
const SUBSCRIPTION_INTERVAL$
|
1769
|
+
const SUBSCRIPTION_INTERVAL$6 = 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$
|
1787
|
+
setTimeout(poll, SUBSCRIPTION_INTERVAL$6);
|
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$
|
1983
|
+
const SUBSCRIPTION_INTERVAL$5 = 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$
|
2001
|
+
setTimeout(poll, SUBSCRIPTION_INTERVAL$5);
|
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$
|
2316
|
+
const SUBSCRIPTION_INTERVAL$4 = 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$
|
2334
|
+
setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
|
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(
|
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 => ({
|
@@ -3496,7 +3496,7 @@ const fetchBalances$6 = async ({
|
|
3496
3496
|
}))
|
3497
3497
|
};
|
3498
3498
|
}
|
3499
|
-
const queries = buildQueries$
|
3499
|
+
const queries = buildQueries$7(networkId, balanceDefs, miniMetadata);
|
3500
3500
|
const balances = await new RpcStateQueryHelper(connector, queries).fetch();
|
3501
3501
|
return balanceDefs.reduce((acc, def) => {
|
3502
3502
|
const balance = balances.find(b => b?.address === def.address && b?.tokenId === def.token.id);
|
@@ -3524,7 +3524,7 @@ const fetchBalances$6 = async ({
|
|
3524
3524
|
errors: []
|
3525
3525
|
});
|
3526
3526
|
};
|
3527
|
-
const buildQueries$
|
3527
|
+
const buildQueries$7 = (networkId, balanceDefs, miniMetadata) => {
|
3528
3528
|
const networkStorageCoders = buildNetworkStorageCoders(networkId, miniMetadata, {
|
3529
3529
|
storage: ["Assets", "Account"]
|
3530
3530
|
});
|
@@ -3533,9 +3533,9 @@ const buildQueries$6 = (networkId, balanceDefs, miniMetadata) => {
|
|
3533
3533
|
address
|
3534
3534
|
}) => {
|
3535
3535
|
const scaleCoder = networkStorageCoders?.storage;
|
3536
|
-
const stateKey = tryEncode$
|
3536
|
+
const stateKey = tryEncode$2(scaleCoder, Number(token.assetId), address) ??
|
3537
3537
|
// Asset Hub
|
3538
|
-
tryEncode$
|
3538
|
+
tryEncode$2(scaleCoder, BigInt(token.assetId), address); // Astar
|
3539
3539
|
|
3540
3540
|
if (!stateKey) {
|
3541
3541
|
log.warn(`Invalid assetId / address in ${networkId} storage query ${token.assetId} / ${address}`);
|
@@ -3591,7 +3591,7 @@ const buildQueries$6 = (networkId, balanceDefs, miniMetadata) => {
|
|
3591
3591
|
};
|
3592
3592
|
}).filter(isNotNil);
|
3593
3593
|
};
|
3594
|
-
const tryEncode$
|
3594
|
+
const tryEncode$2 = (scaleCoder, ...args) => {
|
3595
3595
|
try {
|
3596
3596
|
return scaleCoder?.keys?.enc?.(...args);
|
3597
3597
|
} catch {
|
@@ -3834,46 +3834,163 @@ const getTransferAllEncodedArgs$2 = (assetId, to, codec) => {
|
|
3834
3834
|
})]);
|
3835
3835
|
};
|
3836
3836
|
|
3837
|
-
const
|
3837
|
+
const fetchRuntimeCallResult = async (connector, networkId, metadataRpc, apiName, method, args) => {
|
3838
|
+
const {
|
3839
|
+
builder
|
3840
|
+
} = parseMetadataRpc(metadataRpc);
|
3841
|
+
const call = builder.buildRuntimeCall(apiName, method);
|
3842
|
+
const hex = await connector.send(networkId, "state_call", [`${apiName}_${method}`, toHex(call.args.enc(args))]);
|
3843
|
+
return call.value.dec(hex);
|
3844
|
+
};
|
3845
|
+
|
3846
|
+
const tryGetConstantValue = (metadataRpc, pallet, constant) => {
|
3847
|
+
const {
|
3848
|
+
unifiedMetadata,
|
3849
|
+
builder
|
3850
|
+
} = parseMetadataRpc(metadataRpc);
|
3851
|
+
const encodedValue = unifiedMetadata.pallets.find(({
|
3852
|
+
name
|
3853
|
+
}) => name === pallet)?.constants.find(({
|
3854
|
+
name
|
3855
|
+
}) => name === constant)?.value;
|
3856
|
+
if (!encodedValue) return null;
|
3857
|
+
const codec = builder.buildConstant(pallet, constant);
|
3858
|
+
return codec.dec(encodedValue);
|
3859
|
+
};
|
3860
|
+
|
3861
|
+
const fetchRpcQueryPack = async (connector, networkId, queries) => {
|
3862
|
+
const allStateKeys = queries.flatMap(({
|
3863
|
+
stateKeys
|
3864
|
+
}) => stateKeys).filter(isNotNil);
|
3865
|
+
|
3866
|
+
// doing a query without keys would throw an error => return early
|
3867
|
+
if (!allStateKeys.length) return queries.map(({
|
3868
|
+
stateKeys,
|
3869
|
+
decodeResult
|
3870
|
+
}) => decodeResult(stateKeys.map(() => null)));
|
3871
|
+
const [result] = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
|
3872
|
+
return decodeRpcQueryPack(queries, result);
|
3873
|
+
};
|
3874
|
+
const getRpcQueryPack$ = (connector, networkId, queries, timeout = false) => {
|
3875
|
+
const allStateKeys = queries.flatMap(({
|
3876
|
+
stateKeys
|
3877
|
+
}) => stateKeys).filter(isNotNil);
|
3878
|
+
|
3879
|
+
// doing a query without keys would throw an error => return early
|
3880
|
+
if (!allStateKeys.length) return of(queries.map(({
|
3881
|
+
stateKeys,
|
3882
|
+
decodeResult
|
3883
|
+
}) => decodeResult(stateKeys.map(() => null))));
|
3884
|
+
return new Observable(subscriber => {
|
3885
|
+
const promUnsub = connector.subscribe(networkId, "state_subscribeStorage", "state_storage", [allStateKeys], (error, result) => {
|
3886
|
+
if (error) subscriber.error(error);else subscriber.next(decodeRpcQueryPack(queries, result));
|
3887
|
+
}, timeout);
|
3888
|
+
return () => {
|
3889
|
+
promUnsub.then(unsub => unsub("state_unsubscribeStorage"));
|
3890
|
+
};
|
3891
|
+
});
|
3892
|
+
};
|
3893
|
+
const decodeRpcQueryPack = (queries, result) => {
|
3894
|
+
return queries.reduce((acc, {
|
3895
|
+
stateKeys,
|
3896
|
+
decodeResult
|
3897
|
+
}) => {
|
3898
|
+
const changes = stateKeys.map(stateKey => {
|
3899
|
+
if (!stateKey) return null;
|
3900
|
+
const change = result.changes.find(([key]) => key === stateKey);
|
3901
|
+
if (!change) return null;
|
3902
|
+
return change[1];
|
3903
|
+
});
|
3904
|
+
acc.push(decodeResult(changes));
|
3905
|
+
return acc;
|
3906
|
+
}, []);
|
3907
|
+
};
|
3908
|
+
|
3838
3909
|
const subscribeBalances$5 = ({
|
3839
3910
|
networkId,
|
3840
3911
|
tokensWithAddresses,
|
3841
3912
|
connector,
|
3842
3913
|
miniMetadata
|
3843
3914
|
}) => {
|
3844
|
-
|
3845
|
-
|
3915
|
+
const balanceDefs = getBalanceDefs(tokensWithAddresses);
|
3916
|
+
const queries = buildQueries$6(networkId, balanceDefs, miniMetadata);
|
3917
|
+
return getRpcQueryPack$(connector, networkId, queries).pipe(map(balances => ({
|
3918
|
+
success: balances,
|
3919
|
+
errors: []
|
3920
|
+
})));
|
3921
|
+
};
|
3922
|
+
const buildQueries$6 = (networkId, balanceDefs, miniMetadata) => {
|
3923
|
+
const networkStorageCoders = buildNetworkStorageCoders(networkId, miniMetadata, {
|
3924
|
+
storage: ["Assets", "Account"]
|
3925
|
+
});
|
3926
|
+
return balanceDefs.map(({
|
3927
|
+
token,
|
3928
|
+
address
|
3929
|
+
}) => {
|
3930
|
+
const scaleCoder = networkStorageCoders?.storage;
|
3931
|
+
const stateKey = tryEncode$1(scaleCoder, Number(token.assetId), address) ??
|
3932
|
+
// Asset Hub
|
3933
|
+
tryEncode$1(scaleCoder, BigInt(token.assetId), address); // Astar
|
3846
3934
|
|
3847
|
-
|
3848
|
-
|
3849
|
-
|
3850
|
-
|
3851
|
-
|
3852
|
-
|
3853
|
-
|
3854
|
-
|
3855
|
-
|
3856
|
-
|
3857
|
-
|
3858
|
-
|
3859
|
-
|
3860
|
-
|
3861
|
-
|
3862
|
-
|
3863
|
-
|
3864
|
-
|
3865
|
-
|
3866
|
-
|
3867
|
-
|
3868
|
-
|
3869
|
-
|
3870
|
-
|
3935
|
+
if (!stateKey) {
|
3936
|
+
log.warn(`Invalid assetId / address in ${networkId} storage query ${token.assetId} / ${address}`);
|
3937
|
+
return null;
|
3938
|
+
} else log.log(`VALID assetId / address in ${networkId} storage query ${token.assetId} / ${address}`);
|
3939
|
+
const decodeResult = changes => {
|
3940
|
+
/** NOTE: This type is only a hint for typescript, the chain can actually return whatever it wants to */
|
3941
|
+
|
3942
|
+
const decoded = decodeScale(scaleCoder, changes[0], `Failed to decode substrate-assets balance on chain ${networkId}`) ?? {
|
3943
|
+
balance: 0n,
|
3944
|
+
status: {
|
3945
|
+
type: "Liquid"
|
3946
|
+
}};
|
3947
|
+
const isFrozen = decoded?.status?.type === "Frozen";
|
3948
|
+
const amount = (decoded?.balance ?? 0n).toString();
|
3949
|
+
|
3950
|
+
// due to the following balance calculations, which are made in the `Balance` type:
|
3951
|
+
//
|
3952
|
+
// total balance = (free balance) + (reserved balance)
|
3953
|
+
// transferable balance = (free balance) - (frozen balance)
|
3954
|
+
//
|
3955
|
+
// when `isFrozen` is true we need to set **both** the `free` and `frozen` amounts
|
3956
|
+
// of this balance to the value we received from the RPC.
|
3957
|
+
//
|
3958
|
+
// if we only set the `frozen` amount, then the `total` calculation will be incorrect!
|
3959
|
+
const free = amount;
|
3960
|
+
const frozen = token.isFrozen || isFrozen ? amount : "0";
|
3961
|
+
|
3962
|
+
// include balance values even if zero, so that newly-zero values overwrite old values
|
3963
|
+
const balanceValues = [{
|
3964
|
+
type: "free",
|
3965
|
+
label: "free",
|
3966
|
+
amount: free.toString()
|
3967
|
+
}, {
|
3968
|
+
type: "locked",
|
3969
|
+
label: "frozen",
|
3970
|
+
amount: frozen.toString()
|
3971
|
+
}];
|
3972
|
+
const balance = {
|
3973
|
+
source: "substrate-assets",
|
3974
|
+
status: "live",
|
3975
|
+
address,
|
3976
|
+
networkId,
|
3977
|
+
tokenId: token.id,
|
3978
|
+
values: balanceValues
|
3979
|
+
};
|
3980
|
+
return balance;
|
3871
3981
|
};
|
3872
|
-
|
3873
|
-
|
3874
|
-
|
3982
|
+
return {
|
3983
|
+
stateKeys: [stateKey],
|
3984
|
+
decodeResult
|
3875
3985
|
};
|
3876
|
-
}).
|
3986
|
+
}).filter(isNotNil);
|
3987
|
+
};
|
3988
|
+
const tryEncode$1 = (scaleCoder, ...args) => {
|
3989
|
+
try {
|
3990
|
+
return scaleCoder?.keys?.enc?.(...args);
|
3991
|
+
} catch {
|
3992
|
+
return null;
|
3993
|
+
}
|
3877
3994
|
};
|
3878
3995
|
|
3879
3996
|
const SubAssetsBalanceModule = {
|
@@ -3903,7 +4020,7 @@ const fetchBalances$5 = async ({
|
|
3903
4020
|
}) => {
|
3904
4021
|
const balanceDefs = getBalanceDefs(tokensWithAddresses);
|
3905
4022
|
if (!miniMetadata?.data) {
|
3906
|
-
log.warn(
|
4023
|
+
log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$4} balances on ${networkId}.`);
|
3907
4024
|
return {
|
3908
4025
|
success: [],
|
3909
4026
|
errors: balanceDefs.map(def => ({
|
@@ -4232,7 +4349,7 @@ const getTransferAllEncodedArgs$1 = (onChainId, to, codec) => {
|
|
4232
4349
|
})]);
|
4233
4350
|
};
|
4234
4351
|
|
4235
|
-
const SUBSCRIPTION_INTERVAL$
|
4352
|
+
const SUBSCRIPTION_INTERVAL$3 = 6_000;
|
4236
4353
|
const subscribeBalances$4 = ({
|
4237
4354
|
networkId,
|
4238
4355
|
tokensWithAddresses,
|
@@ -4255,7 +4372,7 @@ const subscribeBalances$4 = ({
|
|
4255
4372
|
});
|
4256
4373
|
if (abortController.signal.aborted) return;
|
4257
4374
|
subscriber.next(balances);
|
4258
|
-
setTimeout(poll, SUBSCRIPTION_INTERVAL$
|
4375
|
+
setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
|
4259
4376
|
} catch (error) {
|
4260
4377
|
log.error("Error", {
|
4261
4378
|
module: MODULE_TYPE$4,
|
@@ -4299,30 +4416,6 @@ const SubHydrationTokenConfigSchema = z.strictObject({
|
|
4299
4416
|
const MODULE_TYPE$3 = SubHydrationTokenSchema.shape.type.value;
|
4300
4417
|
const PLATFORM$3 = SubHydrationTokenSchema.shape.platform.value;
|
4301
4418
|
|
4302
|
-
const fetchRuntimeCallResult = async (connector, networkId, metadataRpc, apiName, method, args) => {
|
4303
|
-
const {
|
4304
|
-
builder
|
4305
|
-
} = parseMetadataRpc(metadataRpc);
|
4306
|
-
const call = builder.buildRuntimeCall(apiName, method);
|
4307
|
-
const hex = await connector.send(networkId, "state_call", [`${apiName}_${method}`, toHex(call.args.enc(args))]);
|
4308
|
-
return call.value.dec(hex);
|
4309
|
-
};
|
4310
|
-
|
4311
|
-
const tryGetConstantValue = (metadataRpc, pallet, constant) => {
|
4312
|
-
const {
|
4313
|
-
unifiedMetadata,
|
4314
|
-
builder
|
4315
|
-
} = parseMetadataRpc(metadataRpc);
|
4316
|
-
const encodedValue = unifiedMetadata.pallets.find(({
|
4317
|
-
name
|
4318
|
-
}) => name === pallet)?.constants.find(({
|
4319
|
-
name
|
4320
|
-
}) => name === constant)?.value;
|
4321
|
-
if (!encodedValue) return null;
|
4322
|
-
const codec = builder.buildConstant(pallet, constant);
|
4323
|
-
return codec.dec(encodedValue);
|
4324
|
-
};
|
4325
|
-
|
4326
4419
|
const fetchBalances$4 = async ({
|
4327
4420
|
networkId,
|
4328
4421
|
tokensWithAddresses,
|
@@ -4331,7 +4424,7 @@ const fetchBalances$4 = async ({
|
|
4331
4424
|
}) => {
|
4332
4425
|
const balanceDefs = getBalanceDefs(tokensWithAddresses);
|
4333
4426
|
if (!miniMetadata?.data) {
|
4334
|
-
log.warn(
|
4427
|
+
log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$3} balances on ${networkId}.`);
|
4335
4428
|
return {
|
4336
4429
|
success: [],
|
4337
4430
|
errors: balanceDefs.map(def => ({
|
@@ -4578,7 +4671,7 @@ const getTransferCallData$3 = ({
|
|
4578
4671
|
};
|
4579
4672
|
};
|
4580
4673
|
|
4581
|
-
const SUBSCRIPTION_INTERVAL$
|
4674
|
+
const SUBSCRIPTION_INTERVAL$2 = 6_000;
|
4582
4675
|
const subscribeBalances$3 = ({
|
4583
4676
|
networkId,
|
4584
4677
|
tokensWithAddresses,
|
@@ -4601,7 +4694,7 @@ const subscribeBalances$3 = ({
|
|
4601
4694
|
});
|
4602
4695
|
if (abortController.signal.aborted) return;
|
4603
4696
|
subscriber.next(balances);
|
4604
|
-
setTimeout(poll, SUBSCRIPTION_INTERVAL$
|
4697
|
+
setTimeout(poll, SUBSCRIPTION_INTERVAL$2);
|
4605
4698
|
} catch (error) {
|
4606
4699
|
log.error("Error", {
|
4607
4700
|
module: MODULE_TYPE$3,
|
@@ -4633,140 +4726,6 @@ const SubHydrationBalanceModule = {
|
|
4633
4726
|
const MODULE_TYPE$2 = SubNativeTokenSchema.shape.type.value;
|
4634
4727
|
const PLATFORM$2 = SubNativeTokenSchema.shape.platform.value;
|
4635
4728
|
|
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) => {
|
4641
|
-
const allStateKeys = queries.flatMap(({
|
4642
|
-
stateKeys
|
4643
|
-
}) => stateKeys).filter(isNotNil);
|
4644
|
-
|
4645
|
-
// doing a query with only null keys would throw an error => return early
|
4646
|
-
if (!allStateKeys.length) return queries.map(({
|
4647
|
-
stateKeys,
|
4648
|
-
decodeResult
|
4649
|
-
}) => decodeResult(stateKeys.map(() => null)));
|
4650
|
-
const response = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
|
4651
|
-
const results = queries.reduce((acc, {
|
4652
|
-
stateKeys,
|
4653
|
-
decodeResult
|
4654
|
-
}) => {
|
4655
|
-
const changes = stateKeys.map(stateKey => {
|
4656
|
-
if (!stateKey) return null;
|
4657
|
-
const change = response[0].changes.find(([key]) => key === stateKey);
|
4658
|
-
if (!change) return null;
|
4659
|
-
return change[1];
|
4660
|
-
});
|
4661
|
-
acc.push(decodeResult(changes));
|
4662
|
-
return acc;
|
4663
|
-
}, []);
|
4664
|
-
return results;
|
4665
|
-
};
|
4666
|
-
|
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
4729
|
const SUBTENSOR_ROOT_NETUID$1 = 0;
|
4771
4730
|
const SUBTENSOR_MIN_STAKE_AMOUNT_PLANK$1 = 1000000n;
|
4772
4731
|
const TAO_DECIMALS$1 = 9n;
|
@@ -5486,7 +5445,7 @@ const fetchBalances$3 = async ({
|
|
5486
5445
|
}) => {
|
5487
5446
|
const balanceDefs = getBalanceDefs(tokensWithAddresses);
|
5488
5447
|
if (!miniMetadata?.data) {
|
5489
|
-
log.warn(
|
5448
|
+
log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE$2} balances on ${networkId}.`);
|
5490
5449
|
return {
|
5491
5450
|
success: [],
|
5492
5451
|
errors: balanceDefs.map(def => ({
|
@@ -5518,12 +5477,12 @@ const fetchBalances$3 = async ({
|
|
5518
5477
|
}))
|
5519
5478
|
};
|
5520
5479
|
}
|
5521
|
-
const
|
5522
|
-
const partialBalances = await
|
5480
|
+
const baseQueries = buildBaseQueries(networkId, balanceDefs, miniMetadata);
|
5481
|
+
const partialBalances = await fetchRpcQueryPack(connector, networkId, baseQueries);
|
5523
5482
|
|
5524
5483
|
// now for each balance that includes nomPoolStaking, we need to fetch the metadata for the pool
|
5525
5484
|
const nomPoolQueries = buildNomPoolQueries(networkId, partialBalances, miniMetadata);
|
5526
|
-
const balances = await
|
5485
|
+
const balances = await fetchRpcQueryPack(connector, networkId, nomPoolQueries);
|
5527
5486
|
|
5528
5487
|
// TODO ⚠️ dedupe locks
|
5529
5488
|
|
@@ -5759,46 +5718,32 @@ const getTransferAllEncodedArgs = (to, codec) => {
|
|
5759
5718
|
})]);
|
5760
5719
|
};
|
5761
5720
|
|
5762
|
-
const SUBSCRIPTION_INTERVAL$2 = 6_000;
|
5763
5721
|
const subscribeBalances$2 = ({
|
5764
5722
|
networkId,
|
5765
5723
|
tokensWithAddresses,
|
5766
5724
|
connector,
|
5767
5725
|
miniMetadata
|
5768
5726
|
}) => {
|
5769
|
-
|
5770
|
-
|
5771
|
-
|
5772
|
-
|
5773
|
-
//
|
5774
|
-
const
|
5775
|
-
|
5776
|
-
|
5777
|
-
|
5778
|
-
|
5779
|
-
|
5780
|
-
|
5781
|
-
|
5782
|
-
|
5783
|
-
|
5784
|
-
|
5785
|
-
|
5786
|
-
|
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();
|
5727
|
+
// could be use as shared observable key if we decide to cache the sub
|
5728
|
+
const balanceDefs = getBalanceDefs(tokensWithAddresses);
|
5729
|
+
const baseQueries = buildBaseQueries(networkId, balanceDefs, miniMetadata);
|
5730
|
+
const baseBalances$ = getRpcQueryPack$(connector, networkId, baseQueries).pipe(switchMap(partialBalances => {
|
5731
|
+
// now for each balance that includes nomPoolStaking, we need to fetch the metadata for the pool
|
5732
|
+
const nomPoolQueries = buildNomPoolQueries(networkId, partialBalances, miniMetadata);
|
5733
|
+
return getRpcQueryPack$(connector, networkId, nomPoolQueries);
|
5734
|
+
}));
|
5735
|
+
const subtensorBalancesByAddress$ = getSubtensorStakingBalances$(connector, networkId, balanceDefs, miniMetadata);
|
5736
|
+
return combineLatest([baseBalances$, subtensorBalancesByAddress$]).pipe(map(([baseBalances, subtensorBalancesByAddress]) => {
|
5737
|
+
// add subtensor balances to base balances
|
5738
|
+
for (const [address, subtensorBalances] of toPairs(subtensorBalancesByAddress)) {
|
5739
|
+
const balance = baseBalances.find(b => b.address === address);
|
5740
|
+
if (balance?.values) balance.values.push(...subtensorBalances);
|
5741
|
+
}
|
5742
|
+
return {
|
5743
|
+
success: baseBalances,
|
5744
|
+
errors: []
|
5800
5745
|
};
|
5801
|
-
})
|
5746
|
+
}));
|
5802
5747
|
};
|
5803
5748
|
|
5804
5749
|
const SubNativeBalanceModule = {
|
@@ -7238,7 +7183,7 @@ const fetchBalances$1 = async ({
|
|
7238
7183
|
}) => {
|
7239
7184
|
const balanceDefs = getBalanceDefs(tokensWithAddresses);
|
7240
7185
|
if (!miniMetadata?.data) {
|
7241
|
-
log.warn(
|
7186
|
+
log.warn(`MiniMetadata is required for fetching ${MODULE_TYPE} balances on ${networkId}.`);
|
7242
7187
|
return {
|
7243
7188
|
success: [],
|
7244
7189
|
errors: balanceDefs.map(def => ({
|
@@ -10458,9 +10403,17 @@ class BalancesProvider {
|
|
10458
10403
|
miniMetadatas: values(miniMetadatas).filter(isNotNil)
|
10459
10404
|
})));
|
10460
10405
|
}
|
10461
|
-
|
10462
|
-
|
10463
|
-
|
10406
|
+
|
10407
|
+
// this is the only public method
|
10408
|
+
getBalances$(addressesByTokenId) {
|
10409
|
+
// split by network
|
10410
|
+
const addressesByTokenIdByNetworkId = toPairs(addressesByTokenId).reduce((acc, [tokenId, addresses]) => {
|
10411
|
+
const networkId = parseTokenId(tokenId).networkId;
|
10412
|
+
if (!acc[networkId]) acc[networkId] = {};
|
10413
|
+
acc[networkId][tokenId] = addresses;
|
10414
|
+
return acc;
|
10415
|
+
}, {});
|
10416
|
+
return combineLatest(toPairs(addressesByTokenIdByNetworkId).map(([networkId]) => this.getNetworkBalances$(networkId, addressesByTokenIdByNetworkId[networkId]))).pipe(map(results => {
|
10464
10417
|
return {
|
10465
10418
|
status: results.some(({
|
10466
10419
|
status
|
@@ -10469,9 +10422,17 @@ class BalancesProvider {
|
|
10469
10422
|
};
|
10470
10423
|
}), startWith({
|
10471
10424
|
status: "initialising",
|
10472
|
-
balances: this.getStoredBalances(
|
10425
|
+
balances: this.getStoredBalances(addressesByTokenId)
|
10473
10426
|
}), distinctUntilChanged(isEqual));
|
10474
10427
|
}
|
10428
|
+
fetchBalances(addressesByTokenId) {
|
10429
|
+
// TODO: better
|
10430
|
+
return firstValueFrom(this.getBalances$(addressesByTokenId).pipe(filter(({
|
10431
|
+
status
|
10432
|
+
}) => status === "live"), map(({
|
10433
|
+
balances
|
10434
|
+
}) => balances)));
|
10435
|
+
}
|
10475
10436
|
getNetworkBalances$(networkId, addressesByTokenId) {
|
10476
10437
|
const network$ = this.#chaindataProvider.getNetworkById$(networkId);
|
10477
10438
|
const tokensMapById$ = this.#chaindataProvider.getTokensMapById$();
|
@@ -10543,7 +10504,42 @@ class BalancesProvider {
|
|
10543
10504
|
}));
|
10544
10505
|
}
|
10545
10506
|
getNetworkMiniMetadatas$(networkId) {
|
10546
|
-
return this.#chaindataProvider.getNetworkById$(networkId).pipe(switchMap(network => isNetworkDot(network) && this.#chainConnectors.substrate ? from(
|
10507
|
+
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([])));
|
10508
|
+
}
|
10509
|
+
getMiniMetadatas$(networkId, specVersion) {
|
10510
|
+
return combineLatest({
|
10511
|
+
defaultMiniMetadatas: this.getDefaultMiniMetadatas$(networkId, specVersion),
|
10512
|
+
storedMiniMetadatas: this.getStoredMiniMetadatas$(networkId, specVersion)
|
10513
|
+
}).pipe(switchMap(({
|
10514
|
+
storedMiniMetadatas,
|
10515
|
+
defaultMiniMetadatas
|
10516
|
+
}) => {
|
10517
|
+
if (defaultMiniMetadatas.length) return of(defaultMiniMetadatas);
|
10518
|
+
if (storedMiniMetadatas.length) return of(storedMiniMetadatas);
|
10519
|
+
if (!this.#chainConnectors.substrate) return of([]);
|
10520
|
+
return from(
|
10521
|
+
// fetch them from the chain
|
10522
|
+
getMiniMetadatas(this.#chainConnectors.substrate, this.#chaindataProvider, networkId)).pipe(
|
10523
|
+
// and persist in storage for later reuse
|
10524
|
+
tap(newMiniMetadatas => {
|
10525
|
+
if (!newMiniMetadatas.length) return;
|
10526
|
+
const storage = this.#storage.getValue();
|
10527
|
+
const miniMetadatas = assign(
|
10528
|
+
// keep minimetadatas of other networks
|
10529
|
+
keyBy(values(storage.miniMetadatas).filter(m => m.chainId !== networkId), m => m.id),
|
10530
|
+
// add the ones for our network
|
10531
|
+
keyBy(newMiniMetadatas, m => m.id));
|
10532
|
+
this.#storage.next(assign({}, storage, {
|
10533
|
+
miniMetadatas
|
10534
|
+
}));
|
10535
|
+
}));
|
10536
|
+
}));
|
10537
|
+
}
|
10538
|
+
getStoredMiniMetadatas$(networkId, specVersion) {
|
10539
|
+
return this.storage$.pipe(map(storage => storage.miniMetadatas.filter(m => m.chainId === networkId && m.specVersion === specVersion && m.version === MINIMETADATA_VERSION)), distinctUntilChanged(isEqual));
|
10540
|
+
}
|
10541
|
+
getDefaultMiniMetadatas$(networkId, specVersion) {
|
10542
|
+
return this.#chaindataProvider.miniMetadatas$.pipe(map(miniMetadatas => miniMetadatas.filter(m => m.chainId === networkId && m.specVersion === specVersion && m.version === MINIMETADATA_VERSION)), distinctUntilChanged(isEqual));
|
10547
10543
|
}
|
10548
10544
|
getStoredBalances(addressesByToken) {
|
10549
10545
|
const balanceDefs = toPairs(addressesByToken).flatMap(([tokenId, addresses]) => addresses.map(address => [tokenId, address]));
|
@@ -10554,11 +10550,4 @@ class BalancesProvider {
|
|
10554
10550
|
}
|
10555
10551
|
}
|
10556
10552
|
|
10557
|
-
// const getStoredBalances = (
|
10558
|
-
// storedBalances: Record<string, IBalance>,
|
10559
|
-
// addressesByToken: Record<TokenId, Address[]>,
|
10560
|
-
// ): IBalance[] => {
|
10561
|
-
|
10562
|
-
// }
|
10563
|
-
|
10564
10553
|
export { BALANCE_MODULES, Balance, BalanceFormatter, BalanceValueGetter, Balances, BalancesProvider, Change24hCurrencyFormatter, DefaultBalanceModule, EvmErc20BalanceModule, EvmErc20TokenConfigSchema, EvmNativeBalanceModule, EvmNativeTokenConfigSchema, EvmUniswapV2BalanceModule, EvmUniswapV2TokenConfigSchema, FiatSumBalancesFormatter, ONE_ALPHA_TOKEN$1 as ONE_ALPHA_TOKEN, PlanckSumBalancesFormatter, RpcStateQueryHelper, SCALE_FACTOR$1 as SCALE_FACTOR, SUBTENSOR_MIN_STAKE_AMOUNT_PLANK$1 as SUBTENSOR_MIN_STAKE_AMOUNT_PLANK, SUBTENSOR_ROOT_NETUID$1 as SUBTENSOR_ROOT_NETUID, SubAssetsBalanceModule, SubAssetsTokenConfigSchema, SubForeignAssetsBalanceModule, SubForeignAssetsTokenConfigSchema, SubHydrationBalanceModule, SubHydrationTokenConfigSchema, SubNativeBalanceModule, SubNativeMiniMetadataExtraSchema, SubNativeModuleConfigSchema, SubNativeTokenConfigSchema, SubPsp22BalanceModule, SubPsp22TokenConfigSchema, SubTokensBalanceModule, SubTokensMiniMetadataExtraSchema, SubTokensModuleConfigSchema, SubTokensTokenConfigSchema, SumBalancesFormatter, TalismanBalancesDatabase, abiMulticall, balances, buildNetworkStorageCoders, buildStorageCoders, calculateAlphaPrice$1 as calculateAlphaPrice, calculateTaoAmountFromAlpha$1 as calculateTaoAmountFromAlpha, calculateTaoFromDynamicInfo$1 as calculateTaoFromDynamicInfo, compress, configureStore, db, decodeOutput, decompress, defaultBalanceModules, deriveMiniMetadataId, detectTransferMethod, erc20BalancesAggregatorAbi, excludeFromFeePayableLocks, excludeFromTransferableAmount, filterBaseLocks, filterMirrorTokens, getBalanceId, getLockTitle, getLockedType$1 as getLockedType, getUniqueChainIds, getValueId, includeInTotalExtraAmount, makeContractCaller, uniswapV2PairAbi };
|