@talismn/balances 0.0.0-pr2043-20250619170346 → 0.0.0-pr2043-20250620074243
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/BalanceModule.d.ts +14 -7
- package/dist/declarations/src/modules/EvmErc20Module.d.ts +18 -11
- package/dist/declarations/src/modules/EvmNativeModule.d.ts +17 -4
- package/dist/declarations/src/modules/EvmUniswapV2Module.d.ts +26 -17
- package/dist/declarations/src/modules/SubstrateAssetsModule.d.ts +19 -8
- package/dist/declarations/src/modules/SubstrateForeignAssetsModule.d.ts +19 -8
- package/dist/declarations/src/modules/SubstrateNativeModule/index.d.ts +14 -1
- package/dist/declarations/src/modules/SubstrateNativeModule/types.d.ts +2 -4
- package/dist/declarations/src/modules/SubstratePsp22Module.d.ts +19 -11
- package/dist/declarations/src/modules/SubstrateTokensModule.d.ts +18 -11
- package/dist/declarations/src/modules/index.d.ts +110 -8
- package/dist/declarations/src/modules/util/InferBalanceModuleTypes.d.ts +5 -3
- package/dist/declarations/src/types/balances.d.ts +18 -2
- package/dist/declarations/src/types/tokens.d.ts +11 -0
- package/dist/talismn-balances.cjs.dev.js +239 -339
- package/dist/talismn-balances.cjs.prod.js +239 -339
- package/dist/talismn-balances.esm.js +236 -343
- package/package.json +7 -7
- package/dist/declarations/src/modules/SubstrateNativeModule/subscribeCrowdloans.d.ts +0 -5
- package/dist/declarations/src/modules/SubstrateNativeModule/util/crowdloanFundContributionsChildKey.d.ts +0 -4
@@ -16,17 +16,16 @@ var txwrapperCore = require('@substrate/txwrapper-core');
|
|
16
16
|
var scale = require('@talismn/scale');
|
17
17
|
var camelCase = require('lodash/camelCase');
|
18
18
|
var PQueue = require('p-queue');
|
19
|
+
var z = require('zod/v4');
|
19
20
|
var sapi = require('@talismn/sapi');
|
20
21
|
var types = require('@polkadot/types');
|
21
22
|
var groupBy = require('lodash/groupBy');
|
22
23
|
var utils = require('@polkadot-api/utils');
|
23
24
|
var polkadotApi = require('polkadot-api');
|
24
|
-
var PromisePool = require('@supercharge/promise-pool');
|
25
25
|
var chainConnector = require('@talismn/chain-connector');
|
26
26
|
var rxjs = require('rxjs');
|
27
27
|
var scaleTs = require('scale-ts');
|
28
28
|
var upperFirst = require('lodash/upperFirst');
|
29
|
-
var z = require('zod/v4');
|
30
29
|
var apiContract = require('@polkadot/api-contract');
|
31
30
|
|
32
31
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
@@ -37,10 +36,9 @@ var pako__default = /*#__PURE__*/_interopDefault(pako);
|
|
37
36
|
var isEqual__default = /*#__PURE__*/_interopDefault(isEqual);
|
38
37
|
var camelCase__default = /*#__PURE__*/_interopDefault(camelCase);
|
39
38
|
var PQueue__default = /*#__PURE__*/_interopDefault(PQueue);
|
39
|
+
var z__default = /*#__PURE__*/_interopDefault(z);
|
40
40
|
var groupBy__default = /*#__PURE__*/_interopDefault(groupBy);
|
41
|
-
var PromisePool__default = /*#__PURE__*/_interopDefault(PromisePool);
|
42
41
|
var upperFirst__default = /*#__PURE__*/_interopDefault(upperFirst);
|
43
|
-
var z__default = /*#__PURE__*/_interopDefault(z);
|
44
42
|
|
45
43
|
// Record<string, unknown> | undefined
|
46
44
|
|
@@ -128,7 +126,7 @@ class EvmTokenFetcher {
|
|
128
126
|
|
129
127
|
var pkg = {
|
130
128
|
name: "@talismn/balances",
|
131
|
-
version: "0.0.0-pr2043-
|
129
|
+
version: "0.0.0-pr2043-20250620074243"};
|
132
130
|
|
133
131
|
var log = anylogger__default.default(pkg.name);
|
134
132
|
|
@@ -1032,6 +1030,10 @@ class TalismanBalancesDatabase extends dexie.Dexie {
|
|
1032
1030
|
}
|
1033
1031
|
const db = new TalismanBalancesDatabase();
|
1034
1032
|
|
1033
|
+
const TokenConfigBaseSchema = chaindataProvider.TokenBaseSchema.partial().omit({
|
1034
|
+
id: true
|
1035
|
+
});
|
1036
|
+
|
1035
1037
|
const erc20Abi = [{
|
1036
1038
|
constant: true,
|
1037
1039
|
inputs: [],
|
@@ -1263,6 +1265,20 @@ const erc20Abi = [{
|
|
1263
1265
|
const erc20BalancesAggregatorAbi = viem.parseAbi(["struct AccountToken {address account; address token;}", "function balances(AccountToken[] memory accountTokens) public view returns (uint256[] memory)"]);
|
1264
1266
|
|
1265
1267
|
const moduleType$7 = "evm-erc20";
|
1268
|
+
// {
|
1269
|
+
// tokens?: Array<
|
1270
|
+
// {
|
1271
|
+
// symbol?: string
|
1272
|
+
// decimals?: number
|
1273
|
+
// name?: string
|
1274
|
+
// contractAddress?: `0x${string}`
|
1275
|
+
// } & BalancesConfigTokenParams
|
1276
|
+
// >
|
1277
|
+
// }
|
1278
|
+
|
1279
|
+
const EvmErc20TokenConfigSchema = TokenConfigBaseSchema.extend({
|
1280
|
+
contractAddress: chaindataProvider.EvmErc20TokenSchema.shape.contractAddress
|
1281
|
+
});
|
1266
1282
|
const EvmErc20Module = hydrate => {
|
1267
1283
|
const {
|
1268
1284
|
chainConnectors,
|
@@ -1308,11 +1324,11 @@ const EvmErc20Module = hydrate => {
|
|
1308
1324
|
* This method is currently executed on [a squid](https://github.com/TalismanSociety/chaindata-squid/blob/0ee02818bf5caa7362e3f3664e55ef05ec8df078/src/steps/updateEvmNetworksFromGithub.ts#L338-L343).
|
1309
1325
|
* In a future version of the balance libraries, we may build some kind of async scheduling system which will keep the list of tokens for each chain up to date without relying on a squid.
|
1310
1326
|
*/
|
1311
|
-
async fetchEvmChainTokens(chainId, _chainMeta, moduleConfig) {
|
1327
|
+
async fetchEvmChainTokens(chainId, _chainMeta, moduleConfig, tokens) {
|
1312
1328
|
//const { isTestnet } = chainMeta
|
1313
1329
|
|
1314
1330
|
const chainTokens = {};
|
1315
|
-
for (const tokenConfig of
|
1331
|
+
for (const tokenConfig of tokens ?? []) {
|
1316
1332
|
const {
|
1317
1333
|
contractAddress,
|
1318
1334
|
symbol: contractSymbol,
|
@@ -1596,6 +1612,7 @@ function groupAddressesByTokenByEvmNetwork$1(addressesByToken, tokens) {
|
|
1596
1612
|
const abiMulticall = viem.parseAbi(["struct Call { address target; bytes callData; }", "struct Call3 { address target; bool allowFailure; bytes callData; }", "struct Call3Value { address target; bool allowFailure; uint256 value; bytes callData; }", "struct Result { bool success; bytes returnData; }", "function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData)", "function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData)", "function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData)", "function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData)", "function getBasefee() view returns (uint256 basefee)", "function getBlockHash(uint256 blockNumber) view returns (bytes32 blockHash)", "function getBlockNumber() view returns (uint256 blockNumber)", "function getChainId() view returns (uint256 chainid)", "function getCurrentBlockCoinbase() view returns (address coinbase)", "function getCurrentBlockDifficulty() view returns (uint256 difficulty)", "function getCurrentBlockGasLimit() view returns (uint256 gaslimit)", "function getCurrentBlockTimestamp() view returns (uint256 timestamp)", "function getEthBalance(address addr) view returns (uint256 balance)", "function getLastBlockHash() view returns (bytes32 blockHash)", "function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData)", "function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData)"]);
|
1597
1613
|
|
1598
1614
|
const moduleType$6 = "evm-native";
|
1615
|
+
const EvmNativeTokenConfigSchema = TokenConfigBaseSchema;
|
1599
1616
|
const EvmNativeModule = hydrate => {
|
1600
1617
|
const {
|
1601
1618
|
chainConnectors,
|
@@ -1623,29 +1640,34 @@ const EvmNativeModule = hydrate => {
|
|
1623
1640
|
* This method is currently executed on [a squid](https://github.com/TalismanSociety/chaindata-squid/blob/0ee02818bf5caa7362e3f3664e55ef05ec8df078/src/steps/updateEvmNetworksFromGithub.ts#L338-L343).
|
1624
1641
|
* In a future version of the balance libraries, we may build some kind of async scheduling system which will keep the list of tokens for each chain up to date without relying on a squid.
|
1625
1642
|
*/
|
1626
|
-
async fetchEvmChainTokens(
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
const
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1643
|
+
async fetchEvmChainTokens() {
|
1644
|
+
// networkId, chainMeta, moduleConfig, tokens
|
1645
|
+
// TODO ? seems unneeded, this info is set on the EthNetworkConfig["nativeCurrency"] field
|
1646
|
+
return {};
|
1647
|
+
|
1648
|
+
// const symbol = moduleConfig?.symbol ?? "ETH"
|
1649
|
+
// const decimals = typeof moduleConfig?.decimals === "number" ? moduleConfig.decimals : 18
|
1650
|
+
// const name = moduleConfig?.name ?? symbol
|
1651
|
+
|
1652
|
+
// const id = evmNativeTokenId(networkId)
|
1653
|
+
// const nativeToken: EvmNativeToken = {
|
1654
|
+
// platform: "ethereum",
|
1655
|
+
// id,
|
1656
|
+
// type: "evm-native",
|
1657
|
+
// isDefault: true,
|
1658
|
+
// symbol,
|
1659
|
+
// decimals,
|
1660
|
+
// name,
|
1661
|
+
// logo: moduleConfig?.logo,
|
1662
|
+
// networkId,
|
1663
|
+
// }
|
1664
|
+
|
1665
|
+
// if (moduleConfig?.symbol) nativeToken.symbol = moduleConfig?.symbol
|
1666
|
+
// if (moduleConfig?.coingeckoId) nativeToken.coingeckoId = moduleConfig?.coingeckoId
|
1667
|
+
// if (moduleConfig?.mirrorOf) nativeToken.mirrorOf = moduleConfig?.mirrorOf
|
1668
|
+
// if (moduleConfig?.noDiscovery) nativeToken.noDiscovery = moduleConfig?.noDiscovery
|
1669
|
+
|
1670
|
+
// return { [nativeToken.id]: nativeToken }
|
1649
1671
|
},
|
1650
1672
|
async subscribeBalances({
|
1651
1673
|
addressesByToken,
|
@@ -2387,6 +2409,36 @@ const uniswapV2PairAbi = [{
|
|
2387
2409
|
}];
|
2388
2410
|
|
2389
2411
|
const moduleType$5 = "evm-uniswapv2";
|
2412
|
+
const EvmUniswapV2TokenConfigSchema = TokenConfigBaseSchema.extend({
|
2413
|
+
contractAddress: chaindataProvider.EvmUniswapV2TokenSchema.shape.contractAddress,
|
2414
|
+
// the ones below are unused and prone to error, feels better to always fetch these from chain
|
2415
|
+
symbol0: chaindataProvider.EvmUniswapV2TokenSchema.shape.symbol0.optional(),
|
2416
|
+
symbol1: chaindataProvider.EvmUniswapV2TokenSchema.shape.symbol1.optional(),
|
2417
|
+
decimals0: chaindataProvider.EvmUniswapV2TokenSchema.shape.decimals0.optional(),
|
2418
|
+
decimals1: chaindataProvider.EvmUniswapV2TokenSchema.shape.decimals1.optional(),
|
2419
|
+
tokenAddress0: chaindataProvider.EvmUniswapV2TokenSchema.shape.tokenAddress0.optional(),
|
2420
|
+
tokenAddress1: chaindataProvider.EvmUniswapV2TokenSchema.shape.tokenAddress1.optional(),
|
2421
|
+
coingeckoId0: chaindataProvider.EvmUniswapV2TokenSchema.shape.coingeckoId0.optional(),
|
2422
|
+
coingeckoId1: chaindataProvider.EvmUniswapV2TokenSchema.shape.coingeckoId1.optional()
|
2423
|
+
});
|
2424
|
+
|
2425
|
+
// {
|
2426
|
+
// pools?: Array<
|
2427
|
+
// {
|
2428
|
+
// contractAddress?: `0x${string}`
|
2429
|
+
// decimals?: number
|
2430
|
+
// symbol0?: string
|
2431
|
+
// symbol1?: string
|
2432
|
+
// decimals0?: number
|
2433
|
+
// decimals1?: number
|
2434
|
+
// tokenAddress0?: `0x${string}`
|
2435
|
+
// tokenAddress1?: `0x${string}`
|
2436
|
+
// coingeckoId0?: string
|
2437
|
+
// coingeckoId1?: string
|
2438
|
+
// } & BalancesConfigTokenParams
|
2439
|
+
// >
|
2440
|
+
// }
|
2441
|
+
|
2390
2442
|
const EvmUniswapV2Module = hydrate => {
|
2391
2443
|
const {
|
2392
2444
|
chainConnectors,
|
@@ -2402,9 +2454,9 @@ const EvmUniswapV2Module = hydrate => {
|
|
2402
2454
|
extra: null
|
2403
2455
|
};
|
2404
2456
|
},
|
2405
|
-
async fetchEvmChainTokens(chainId, _chainMeta, moduleConfig) {
|
2457
|
+
async fetchEvmChainTokens(chainId, _chainMeta, moduleConfig, pools) {
|
2406
2458
|
const tokens = {};
|
2407
|
-
for (const tokenConfig of
|
2459
|
+
for (const tokenConfig of pools ?? []) {
|
2408
2460
|
const {
|
2409
2461
|
contractAddress,
|
2410
2462
|
decimals,
|
@@ -2694,7 +2746,9 @@ const getSpecVersion = async (chainConnector, networkId) => {
|
|
2694
2746
|
const CACHE$1 = new Map();
|
2695
2747
|
const getMetadataRpc = async (chainConnector, networkId) => {
|
2696
2748
|
if (CACHE$1.has(networkId)) return CACHE$1.get(networkId);
|
2697
|
-
const pResult = sapi.fetchBestMetadata((
|
2749
|
+
const pResult = sapi.fetchBestMetadata((method, params, isCacheable) => chainConnector.send(networkId, method, params, isCacheable, {
|
2750
|
+
expectErrors: true
|
2751
|
+
}), true // allow fallback to 14 as modules dont use any v15 or v16 specifics yet
|
2698
2752
|
);
|
2699
2753
|
CACHE$1.set(networkId, pResult);
|
2700
2754
|
try {
|
@@ -2718,6 +2772,8 @@ const POOL = new PQueue__default.default({
|
|
2718
2772
|
});
|
2719
2773
|
const getMiniMetadatas = async (chainConnector, chaindataProvider, networkId, specVersion, signal) => {
|
2720
2774
|
if (CACHE.has(networkId)) return CACHE.get(networkId);
|
2775
|
+
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
|
2776
|
+
);
|
2721
2777
|
const pResult = POOL.add(() => fetchMiniMetadatas(chainConnector, chaindataProvider, networkId, specVersion), {
|
2722
2778
|
signal
|
2723
2779
|
});
|
@@ -2733,9 +2789,10 @@ const getMiniMetadatas = async (chainConnector, chaindataProvider, networkId, sp
|
|
2733
2789
|
CACHE.delete(networkId);
|
2734
2790
|
}
|
2735
2791
|
};
|
2792
|
+
const DotBalanceModuleTypeSchema = z__default.default.keyof(chaindataProvider.DotNetworkBalancesConfigSchema);
|
2736
2793
|
const fetchMiniMetadatas = async (chainConnector, chaindataProvider, chainId, specVersion, signal) => {
|
2737
2794
|
const start = performance.now();
|
2738
|
-
log.
|
2795
|
+
log.info("[miniMetadata] fetching minimetadatas for %s", chainId);
|
2739
2796
|
try {
|
2740
2797
|
const metadataRpc = await getMetadataRpc(chainConnector, chainId);
|
2741
2798
|
signal?.throwIfAborted();
|
@@ -2746,10 +2803,14 @@ const fetchMiniMetadatas = async (chainConnector, chaindataProvider, chainId, sp
|
|
2746
2803
|
const modules = defaultBalanceModules.map(mod => mod({
|
2747
2804
|
chainConnectors,
|
2748
2805
|
chaindataProvider
|
2749
|
-
})).filter(mod => mod.type.
|
2806
|
+
})).filter(mod => DotBalanceModuleTypeSchema.safeParse(mod.type).success);
|
2750
2807
|
return Promise.all(modules.map(async mod => {
|
2751
2808
|
const source = mod.type;
|
2752
|
-
const
|
2809
|
+
const chain = await chaindataProvider.chainById(chainId);
|
2810
|
+
const balancesConfig = chain?.balancesConfig?.[mod.type];
|
2811
|
+
const chainMeta = await mod.fetchSubstrateChainMeta(chainId, balancesConfig,
|
2812
|
+
// TODO fix typings
|
2813
|
+
metadataRpc);
|
2753
2814
|
return {
|
2754
2815
|
id: deriveMiniMetadataId({
|
2755
2816
|
source,
|
@@ -3075,10 +3136,23 @@ const decompress = data => {
|
|
3075
3136
|
};
|
3076
3137
|
|
3077
3138
|
const moduleType$4 = "substrate-assets";
|
3139
|
+
const SubAssetsTokenConfigSchema = TokenConfigBaseSchema.extend({
|
3140
|
+
assetId: chaindataProvider.SubAssetsTokenSchema.shape.assetId,
|
3141
|
+
existentialDeposit: chaindataProvider.SubAssetsTokenSchema.shape.existentialDeposit
|
3142
|
+
});
|
3078
3143
|
const UNSUPPORTED_CHAIN_META$3 = {
|
3079
3144
|
miniMetadata: null,
|
3080
3145
|
extra: null
|
3081
3146
|
};
|
3147
|
+
|
3148
|
+
// {
|
3149
|
+
// tokens?: Array<
|
3150
|
+
// {
|
3151
|
+
// assetId: number | string
|
3152
|
+
// } & BalancesConfigTokenParams
|
3153
|
+
// >
|
3154
|
+
// }
|
3155
|
+
|
3082
3156
|
const SubAssetsModule = hydrate => {
|
3083
3157
|
const {
|
3084
3158
|
chainConnectors,
|
@@ -3102,8 +3176,8 @@ const SubAssetsModule = hydrate => {
|
|
3102
3176
|
extra: null
|
3103
3177
|
};
|
3104
3178
|
},
|
3105
|
-
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig) {
|
3106
|
-
if (
|
3179
|
+
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig, tokens) {
|
3180
|
+
if (!tokens?.length) return {};
|
3107
3181
|
const {
|
3108
3182
|
miniMetadata
|
3109
3183
|
} = chainMeta;
|
@@ -3112,8 +3186,8 @@ const SubAssetsModule = hydrate => {
|
|
3112
3186
|
const scaleBuilder = scale.getDynamicBuilder(scale.getLookupFn(metadata));
|
3113
3187
|
const assetCoder = scaleBuilder.buildStorage("Assets", "Asset");
|
3114
3188
|
const metadataCoder = scaleBuilder.buildStorage("Assets", "Metadata");
|
3115
|
-
const
|
3116
|
-
for (const tokenConfig of
|
3189
|
+
const tokenList = {};
|
3190
|
+
for (const tokenConfig of tokens ?? []) {
|
3117
3191
|
try {
|
3118
3192
|
const assetId = String(tokenConfig.assetId);
|
3119
3193
|
const assetStateKey = tryEncode(assetCoder, BigInt(assetId)) ?? tryEncode(assetCoder, assetId);
|
@@ -3145,13 +3219,13 @@ const SubAssetsModule = hydrate => {
|
|
3145
3219
|
}
|
3146
3220
|
if (tokenConfig?.coingeckoId) token.coingeckoId = tokenConfig?.coingeckoId;
|
3147
3221
|
if (tokenConfig?.mirrorOf) token.mirrorOf = tokenConfig?.mirrorOf;
|
3148
|
-
|
3222
|
+
tokenList[token.id] = token;
|
3149
3223
|
} catch (error) {
|
3150
3224
|
log.error(`Failed to build substrate-assets token ${tokenConfig.assetId} (${tokenConfig.symbol}) on ${chainId}`, error);
|
3151
3225
|
continue;
|
3152
3226
|
}
|
3153
3227
|
}
|
3154
|
-
return
|
3228
|
+
return tokenList;
|
3155
3229
|
},
|
3156
3230
|
// TODO: Don't create empty subscriptions
|
3157
3231
|
async subscribeBalances({
|
@@ -3181,10 +3255,10 @@ const SubAssetsModule = hydrate => {
|
|
3181
3255
|
}
|
3182
3256
|
}));
|
3183
3257
|
return () => {
|
3184
|
-
controller.abort();
|
3185
3258
|
pUnsubs.then(unsubs => {
|
3186
3259
|
unsubs.forEach(unsubscribe => unsubscribe());
|
3187
3260
|
});
|
3261
|
+
controller.abort();
|
3188
3262
|
};
|
3189
3263
|
},
|
3190
3264
|
async fetchBalances(addressesByToken) {
|
@@ -3368,6 +3442,19 @@ const UNSUPPORTED_CHAIN_META$2 = {
|
|
3368
3442
|
miniMetadata: null,
|
3369
3443
|
extra: null
|
3370
3444
|
};
|
3445
|
+
const SubForeignAssetsTokenConfigSchema = TokenConfigBaseSchema.extend({
|
3446
|
+
onChainId: chaindataProvider.SubForeignAssetsTokenSchema.shape.onChainId,
|
3447
|
+
existentialDeposit: chaindataProvider.SubForeignAssetsTokenSchema.shape.existentialDeposit
|
3448
|
+
});
|
3449
|
+
|
3450
|
+
// {
|
3451
|
+
// tokens?: Array<
|
3452
|
+
// {
|
3453
|
+
// onChainId: string
|
3454
|
+
// } & BalancesConfigTokenParams
|
3455
|
+
// >
|
3456
|
+
// }
|
3457
|
+
|
3371
3458
|
const SubForeignAssetsModule = hydrate => {
|
3372
3459
|
const {
|
3373
3460
|
chainConnectors,
|
@@ -3392,8 +3479,8 @@ const SubForeignAssetsModule = hydrate => {
|
|
3392
3479
|
extra: null
|
3393
3480
|
};
|
3394
3481
|
},
|
3395
|
-
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig) {
|
3396
|
-
if (
|
3482
|
+
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig, tokens) {
|
3483
|
+
if (!tokens?.length) return {};
|
3397
3484
|
const {
|
3398
3485
|
miniMetadata
|
3399
3486
|
} = chainMeta;
|
@@ -3403,8 +3490,8 @@ const SubForeignAssetsModule = hydrate => {
|
|
3403
3490
|
const scaleBuilder = scale.getDynamicBuilder(scale.getLookupFn(unifiedMetadata));
|
3404
3491
|
const assetCoder = scaleBuilder.buildStorage("ForeignAssets", "Asset");
|
3405
3492
|
const metadataCoder = scaleBuilder.buildStorage("ForeignAssets", "Metadata");
|
3406
|
-
const
|
3407
|
-
for (const tokenConfig of
|
3493
|
+
const tokenList = {};
|
3494
|
+
for (const tokenConfig of tokens ?? []) {
|
3408
3495
|
try {
|
3409
3496
|
const onChainId = (() => {
|
3410
3497
|
try {
|
@@ -3439,13 +3526,13 @@ const SubForeignAssetsModule = hydrate => {
|
|
3439
3526
|
};
|
3440
3527
|
if (tokenConfig?.coingeckoId) token.coingeckoId = tokenConfig?.coingeckoId;
|
3441
3528
|
if (tokenConfig?.mirrorOf) token.mirrorOf = tokenConfig?.mirrorOf;
|
3442
|
-
|
3529
|
+
tokenList[token.id] = token;
|
3443
3530
|
} catch (error) {
|
3444
3531
|
log.error(`Failed to build substrate-foreignassets token ${tokenConfig.onChainId} (${tokenConfig.symbol}) on ${chainId}`, error?.message ?? error);
|
3445
3532
|
continue;
|
3446
3533
|
}
|
3447
3534
|
}
|
3448
|
-
return
|
3535
|
+
return tokenList;
|
3449
3536
|
},
|
3450
3537
|
// TODO: Don't create empty subscriptions
|
3451
3538
|
async subscribeBalances({
|
@@ -3474,10 +3561,10 @@ const SubForeignAssetsModule = hydrate => {
|
|
3474
3561
|
}
|
3475
3562
|
}));
|
3476
3563
|
return () => {
|
3477
|
-
controller.abort();
|
3478
3564
|
pUnsubs.then(unsubs => {
|
3479
3565
|
unsubs.forEach(unsubscribe => unsubscribe());
|
3480
3566
|
});
|
3567
|
+
controller.abort();
|
3481
3568
|
};
|
3482
3569
|
},
|
3483
3570
|
async fetchBalances(addressesByToken) {
|
@@ -3664,263 +3751,6 @@ const asObservable = handler => (...args) => new rxjs.Observable(subscriber => {
|
|
3664
3751
|
return unsubscribe;
|
3665
3752
|
});
|
3666
3753
|
|
3667
|
-
/**
|
3668
|
-
* Crowdloan contributions are stored in the `childstate` key returned by this function.
|
3669
|
-
*/
|
3670
|
-
const crowdloanFundContributionsChildKey = fundIndex => util$1.u8aToHex(util$1.u8aConcat(":child_storage:default:", utilCrypto.blake2AsU8a(util$1.u8aConcat("crowdloan", scaleTs.u32.enc(fundIndex)))));
|
3671
|
-
|
3672
|
-
// TODO make this method chain-specific
|
3673
|
-
async function subscribeCrowdloans(chaindataProvider$1, chainConnector, addressesByToken, callback, signal) {
|
3674
|
-
const allChains = await chaindataProvider$1.chainsById();
|
3675
|
-
const tokens = await chaindataProvider$1.tokensById();
|
3676
|
-
|
3677
|
-
// there should be only one network here when subscribing to balances, we've split it up by network at the top level
|
3678
|
-
const networkIds = lodash.keys(addressesByToken).map(tokenId => chaindataProvider.parseTokenId(tokenId).networkId);
|
3679
|
-
const miniMetadatas = new Map();
|
3680
|
-
for (const networkId of networkIds) miniMetadatas.set(networkId, await getMiniMetadata(chaindataProvider$1, chainConnector, networkId, "substrate-native"));
|
3681
|
-
const crowdloanTokenIds = Object.entries(tokens).filter(([, token]) => {
|
3682
|
-
// ignore non-native tokens
|
3683
|
-
if (token.type !== "substrate-native") return;
|
3684
|
-
// ignore tokens on chains with no crowdloans pallet
|
3685
|
-
const miniMetadata = miniMetadatas.get(token.networkId);
|
3686
|
-
return typeof miniMetadata?.extra?.crowdloanPalletId === "string";
|
3687
|
-
}).map(([tokenId]) => tokenId);
|
3688
|
-
|
3689
|
-
// crowdloan contributions can only be done by the native token on chains with the crowdloan pallet
|
3690
|
-
const addressesByCrowdloanToken = Object.fromEntries(Object.entries(addressesByToken)
|
3691
|
-
// remove ethereum addresses
|
3692
|
-
.map(([tokenId, addresses]) => [tokenId, addresses.filter(address => !util.isEthereumAddress(address))])
|
3693
|
-
// remove tokens which aren't crowdloan tokens
|
3694
|
-
.filter(([tokenId]) => crowdloanTokenIds.includes(tokenId)));
|
3695
|
-
const uniqueChainIds = getUniqueChainIds(addressesByCrowdloanToken, tokens);
|
3696
|
-
const chains = Object.fromEntries(Object.entries(allChains).filter(([chainId]) => uniqueChainIds.includes(chainId)));
|
3697
|
-
const chainStorageCoders = buildStorageCoders({
|
3698
|
-
chainIds: uniqueChainIds,
|
3699
|
-
chains,
|
3700
|
-
miniMetadatas,
|
3701
|
-
coders: {
|
3702
|
-
parachains: ["Paras", "Parachains"],
|
3703
|
-
funds: ["Crowdloan", "Funds"]
|
3704
|
-
}
|
3705
|
-
});
|
3706
|
-
const tokenSubscriptions = [];
|
3707
|
-
for (const [tokenId, addresses] of Object.entries(addressesByCrowdloanToken)) {
|
3708
|
-
const token = tokens[tokenId];
|
3709
|
-
if (!token) {
|
3710
|
-
log.warn(`Token ${tokenId} not found`);
|
3711
|
-
continue;
|
3712
|
-
}
|
3713
|
-
if (token.type !== "substrate-native") {
|
3714
|
-
log.debug(`This module doesn't handle tokens of type ${token.type}`);
|
3715
|
-
continue;
|
3716
|
-
}
|
3717
|
-
const chainId = token.networkId;
|
3718
|
-
if (!chainId) {
|
3719
|
-
log.warn(`Token ${tokenId} has no chain`);
|
3720
|
-
continue;
|
3721
|
-
}
|
3722
|
-
const chain = chains[chainId];
|
3723
|
-
if (!chain) {
|
3724
|
-
log.warn(`Chain ${chainId} for token ${tokenId} not found`);
|
3725
|
-
continue;
|
3726
|
-
}
|
3727
|
-
const subscribeParaIds = callback => {
|
3728
|
-
const scaleCoder = chainStorageCoders.get(chainId)?.parachains;
|
3729
|
-
const queries = [0].flatMap(() => {
|
3730
|
-
const stateKey = scale.encodeStateKey(scaleCoder);
|
3731
|
-
if (!stateKey) return [];
|
3732
|
-
const decodeResult = change => {
|
3733
|
-
/** NOTE: This type is only a hint for typescript, the chain can actually return whatever it wants to */
|
3734
|
-
|
3735
|
-
const decoded = scale.decodeScale(scaleCoder, change, `Failed to decode parachains on chain ${chainId}`);
|
3736
|
-
const paraIds = decoded ?? [];
|
3737
|
-
return paraIds;
|
3738
|
-
};
|
3739
|
-
return {
|
3740
|
-
chainId,
|
3741
|
-
stateKey,
|
3742
|
-
decodeResult
|
3743
|
-
};
|
3744
|
-
});
|
3745
|
-
const subscription = new RpcStateQueryHelper(chainConnector, queries).subscribe(callback);
|
3746
|
-
return () => subscription.then(unsubscribe => unsubscribe());
|
3747
|
-
};
|
3748
|
-
const subscribeParaFundIndexes = (paraIds, callback) => {
|
3749
|
-
const scaleCoder = chainStorageCoders.get(chainId)?.funds;
|
3750
|
-
const queries = paraIds.flatMap(paraId => {
|
3751
|
-
const stateKey = scale.encodeStateKey(scaleCoder, `Invalid paraId in ${chainId} funds query ${paraId}`, paraId);
|
3752
|
-
if (!stateKey) return [];
|
3753
|
-
const decodeResult = change => {
|
3754
|
-
/** NOTE: This type is only a hint for typescript, the chain can actually return whatever it wants to */
|
3755
|
-
|
3756
|
-
const decoded = scale.decodeScale(scaleCoder, change, `Failed to decode paras on chain ${chainId}`);
|
3757
|
-
const firstPeriod = decoded?.first_period?.toString?.() ?? "";
|
3758
|
-
const lastPeriod = decoded?.last_period?.toString?.() ?? "";
|
3759
|
-
const fundPeriod = `${firstPeriod}-${lastPeriod}`;
|
3760
|
-
const fundIndex = decoded?.fund_index ?? decoded?.trie_index;
|
3761
|
-
return {
|
3762
|
-
paraId,
|
3763
|
-
fundPeriod,
|
3764
|
-
fundIndex
|
3765
|
-
};
|
3766
|
-
};
|
3767
|
-
return {
|
3768
|
-
chainId,
|
3769
|
-
stateKey,
|
3770
|
-
decodeResult
|
3771
|
-
};
|
3772
|
-
});
|
3773
|
-
const subscription = new RpcStateQueryHelper(chainConnector, queries).subscribe(callback);
|
3774
|
-
return () => subscription.then(unsubscribe => unsubscribe());
|
3775
|
-
};
|
3776
|
-
const subscribeFundContributions = (funds, addresses, callback) => {
|
3777
|
-
// TODO: Watch system_events in order to subscribe to changes, then redo the contributions query when changes are detected:
|
3778
|
-
// https://github.com/polkadot-js/api/blob/8fe02a14345b57e6abb8f7f2c2b624cf70c51b23/packages/api-derive/src/crowdloan/ownContributions.ts#L32-L47
|
3779
|
-
//
|
3780
|
-
// For now we just re-fetch all contributions on a timer and then only send them to the subscription callback when they have changed
|
3781
|
-
|
3782
|
-
const queries = funds.map(({
|
3783
|
-
paraId,
|
3784
|
-
fundIndex
|
3785
|
-
}) => ({
|
3786
|
-
paraId,
|
3787
|
-
fundIndex,
|
3788
|
-
addresses,
|
3789
|
-
childKey: crowdloanFundContributionsChildKey(fundIndex),
|
3790
|
-
storageKeys: addresses.map(address => util$1.u8aToHex(util.decodeAnyAddress(address)))
|
3791
|
-
}));
|
3792
|
-
|
3793
|
-
// track whether our caller is still subscribed
|
3794
|
-
let subscriptionActive = true;
|
3795
|
-
let previousContributions = null;
|
3796
|
-
const fetchContributions = async () => {
|
3797
|
-
try {
|
3798
|
-
const results = await Promise.all(queries.map(async ({
|
3799
|
-
paraId,
|
3800
|
-
fundIndex,
|
3801
|
-
addresses,
|
3802
|
-
childKey,
|
3803
|
-
storageKeys
|
3804
|
-
}) => ({
|
3805
|
-
paraId,
|
3806
|
-
fundIndex,
|
3807
|
-
addresses,
|
3808
|
-
result: await chainConnector.send(chainId, "childstate_getStorageEntries", [childKey, storageKeys])
|
3809
|
-
})));
|
3810
|
-
const contributions = results.flatMap(queryResult => {
|
3811
|
-
const {
|
3812
|
-
paraId,
|
3813
|
-
fundIndex,
|
3814
|
-
addresses,
|
3815
|
-
result
|
3816
|
-
} = queryResult;
|
3817
|
-
return (Array.isArray(result) ? result : []).flatMap((encoded, index) => {
|
3818
|
-
const amount = (() => {
|
3819
|
-
try {
|
3820
|
-
return typeof encoded === "string" ? scaleTs.u128.dec(encoded) ?? 0n : 0n;
|
3821
|
-
} catch {
|
3822
|
-
return 0n;
|
3823
|
-
}
|
3824
|
-
})().toString();
|
3825
|
-
return {
|
3826
|
-
paraId,
|
3827
|
-
fundIndex,
|
3828
|
-
address: addresses[index],
|
3829
|
-
amount
|
3830
|
-
};
|
3831
|
-
});
|
3832
|
-
});
|
3833
|
-
|
3834
|
-
// ignore these results if our caller has tried to close this subscription
|
3835
|
-
if (!subscriptionActive) return;
|
3836
|
-
|
3837
|
-
// ignore these results if they're the same as what we previously fetched
|
3838
|
-
if (isEqual__default.default(previousContributions, contributions)) return;
|
3839
|
-
previousContributions = contributions;
|
3840
|
-
callback(null, contributions);
|
3841
|
-
} catch (error) {
|
3842
|
-
callback(error);
|
3843
|
-
}
|
3844
|
-
};
|
3845
|
-
|
3846
|
-
// set up polling for contributions
|
3847
|
-
const crowdloanContributionsPollInterval = 60_000; // 60_000ms === 1 minute
|
3848
|
-
const pollContributions = async () => {
|
3849
|
-
if (!subscriptionActive) return;
|
3850
|
-
try {
|
3851
|
-
await fetchContributions();
|
3852
|
-
} catch (error) {
|
3853
|
-
// log any errors, but don't cancel the poll for contributions when one fetch fails
|
3854
|
-
log.error(error);
|
3855
|
-
}
|
3856
|
-
if (!subscriptionActive) return;
|
3857
|
-
setTimeout(pollContributions, crowdloanContributionsPollInterval);
|
3858
|
-
};
|
3859
|
-
|
3860
|
-
// start polling
|
3861
|
-
pollContributions();
|
3862
|
-
return () => {
|
3863
|
-
// stop polling
|
3864
|
-
subscriptionActive = false;
|
3865
|
-
};
|
3866
|
-
};
|
3867
|
-
const paraIds$ = asObservable(subscribeParaIds)().pipe(rxjs.scan((_, next) => Array.from(new Set(next.flatMap(paraIds => paraIds))), []), rxjs.share());
|
3868
|
-
const fundIndexesByParaId$ = paraIds$.pipe(rxjs.map(paraIds => asObservable(subscribeParaFundIndexes)(paraIds)), rxjs.switchAll(), rxjs.scan((state, next) => {
|
3869
|
-
for (const fund of next) {
|
3870
|
-
const {
|
3871
|
-
paraId,
|
3872
|
-
fundIndex
|
3873
|
-
} = fund;
|
3874
|
-
if (typeof fundIndex === "number") {
|
3875
|
-
state.set(paraId, (state.get(paraId) ?? new Set()).add(fundIndex));
|
3876
|
-
}
|
3877
|
-
}
|
3878
|
-
return state;
|
3879
|
-
}, new Map()));
|
3880
|
-
const contributionsByAddress$ = fundIndexesByParaId$.pipe(rxjs.map(fundIndexesByParaId => Array.from(fundIndexesByParaId).flatMap(([paraId, fundIndexes]) => Array.from(fundIndexes).map(fundIndex => ({
|
3881
|
-
paraId,
|
3882
|
-
fundIndex
|
3883
|
-
})))), rxjs.map(funds => asObservable(subscribeFundContributions)(funds, addresses)), rxjs.switchAll(), rxjs.scan((state, next) => {
|
3884
|
-
for (const contribution of next) {
|
3885
|
-
const {
|
3886
|
-
address
|
3887
|
-
} = contribution;
|
3888
|
-
state.set(address, (state.get(address) ?? new Set()).add(contribution));
|
3889
|
-
}
|
3890
|
-
return state;
|
3891
|
-
}, new Map()));
|
3892
|
-
const subscription = contributionsByAddress$.subscribe({
|
3893
|
-
next: contributionsByAddress => {
|
3894
|
-
const balances = Array.from(contributionsByAddress).map(([address, contributions]) => {
|
3895
|
-
return {
|
3896
|
-
source: "substrate-native",
|
3897
|
-
status: "live",
|
3898
|
-
address,
|
3899
|
-
networkId: chainId,
|
3900
|
-
tokenId,
|
3901
|
-
values: Array.from(contributions).map(({
|
3902
|
-
amount,
|
3903
|
-
paraId
|
3904
|
-
}) => ({
|
3905
|
-
type: "crowdloan",
|
3906
|
-
label: "crowdloan",
|
3907
|
-
source: "crowdloan",
|
3908
|
-
amount: amount,
|
3909
|
-
meta: {
|
3910
|
-
paraId
|
3911
|
-
}
|
3912
|
-
}))
|
3913
|
-
};
|
3914
|
-
});
|
3915
|
-
if (balances.length > 0) callback(null, balances);
|
3916
|
-
},
|
3917
|
-
error: error => callback(error)
|
3918
|
-
});
|
3919
|
-
tokenSubscriptions.push(() => subscription.unsubscribe());
|
3920
|
-
}
|
3921
|
-
return () => tokenSubscriptions.forEach(unsub => unsub());
|
3922
|
-
}
|
3923
|
-
|
3924
3754
|
/**
|
3925
3755
|
* Each nominationPool in the nominationPools pallet has access to some accountIds which have no
|
3926
3756
|
* associated private key. Instead, they are derived from this function.
|
@@ -3952,6 +3782,7 @@ async function subscribeNompoolStaking(chaindataProvider$1, chainConnector, addr
|
|
3952
3782
|
const miniMetadata = await getMiniMetadata(chaindataProvider$1, chainConnector, networkId, "substrate-native");
|
3953
3783
|
miniMetadatas.set(networkId, miniMetadata);
|
3954
3784
|
}
|
3785
|
+
signal?.throwIfAborted();
|
3955
3786
|
const nomPoolTokenIds = Object.entries(tokens).filter(([, token]) => {
|
3956
3787
|
// ignore non-native tokens
|
3957
3788
|
if (token.type !== "substrate-native") return false;
|
@@ -4269,9 +4100,10 @@ async function subscribeSubtensorStaking(chaindataProvider$1, chainConnector, ad
|
|
4269
4100
|
const networkIds = lodash.keys(addressesByToken).map(tokenId => chaindataProvider.parseTokenId(tokenId).networkId);
|
4270
4101
|
const miniMetadatas = new Map();
|
4271
4102
|
for (const networkId of networkIds) {
|
4272
|
-
const miniMetadata = await getMiniMetadata(chaindataProvider$1, chainConnector, networkId, "substrate-native");
|
4103
|
+
const miniMetadata = await getMiniMetadata(chaindataProvider$1, chainConnector, networkId, "substrate-native", signal);
|
4273
4104
|
miniMetadatas.set(networkId, miniMetadata);
|
4274
4105
|
}
|
4106
|
+
signal?.throwIfAborted();
|
4275
4107
|
const subtensorTokenIds = Object.entries(tokens).filter(([, token]) => {
|
4276
4108
|
// ignore non-native tokens
|
4277
4109
|
if (token.type !== "substrate-native") return false;
|
@@ -4477,7 +4309,9 @@ async function subscribeSubtensorStaking(chaindataProvider$1, chainConnector, ad
|
|
4477
4309
|
});
|
4478
4310
|
|
4479
4311
|
// use the abortController to tear the subscription down when we don't need it anymore
|
4480
|
-
abortController.signal.
|
4312
|
+
abortController.signal.addEventListener("abort", () => {
|
4313
|
+
subscription.unsubscribe();
|
4314
|
+
});
|
4481
4315
|
}
|
4482
4316
|
return () => abortController.abort();
|
4483
4317
|
}
|
@@ -4563,6 +4397,10 @@ const getLockTitle = (lock, {
|
|
4563
4397
|
|
4564
4398
|
const moduleType$2 = "substrate-native";
|
4565
4399
|
|
4400
|
+
// {
|
4401
|
+
// disable?: boolean
|
4402
|
+
// } & BalancesConfigTokenParams
|
4403
|
+
|
4566
4404
|
/**
|
4567
4405
|
* Function to merge two 'sub sources' of the same balance together, or
|
4568
4406
|
* two instances of the same balance with different values.
|
@@ -5040,6 +4878,7 @@ const UNSUPPORTED_CHAIN_META$1 = {
|
|
5040
4878
|
miniMetadata: null,
|
5041
4879
|
extra: null
|
5042
4880
|
};
|
4881
|
+
const SubNativeTokenConfigSchema = TokenConfigBaseSchema;
|
5043
4882
|
const SubNativeModule = hydrate => {
|
5044
4883
|
const {
|
5045
4884
|
chainConnectors,
|
@@ -5055,7 +4894,7 @@ const SubNativeModule = hydrate => {
|
|
5055
4894
|
// subscribeBalances was split by network to prevent all subs to wait for all minimetadatas to be ready.
|
5056
4895
|
// however the multichain logic in there is so deep in the function below that i had to keep it as-is, and call it by per-network chunks
|
5057
4896
|
// TODO refactor this be actually network specific
|
5058
|
-
const subscribeChainBalances =
|
4897
|
+
const subscribeChainBalances = (chainId, opts, callback, signal) => {
|
5059
4898
|
const {
|
5060
4899
|
addressesByToken,
|
5061
4900
|
initialBalances
|
@@ -5154,13 +4993,19 @@ const SubNativeModule = hydrate => {
|
|
5154
4993
|
return rxjs.from(queryCache.getQueries(newAddressesByToken)).pipe(rxjs.switchMap(baseQueries => {
|
5155
4994
|
return new rxjs.Observable(subscriber => {
|
5156
4995
|
if (!chainConnectors.substrate) return;
|
5157
|
-
const unsubSubtensorStaking = subscribeSubtensorStaking(chaindataProvider$1, chainConnectors.substrate, newAddressesByToken, handleUpdateForSource("subtensor-staking"));
|
5158
|
-
const unsubNompoolStaking = subscribeNompoolStaking(chaindataProvider$1, chainConnectors.substrate, newAddressesByToken, handleUpdateForSource("nompools-staking"));
|
5159
|
-
const unsubCrowdloans = subscribeCrowdloans(
|
4996
|
+
const unsubSubtensorStaking = subscribeSubtensorStaking(chaindataProvider$1, chainConnectors.substrate, newAddressesByToken, handleUpdateForSource("subtensor-staking"), signal);
|
4997
|
+
const unsubNompoolStaking = subscribeNompoolStaking(chaindataProvider$1, chainConnectors.substrate, newAddressesByToken, handleUpdateForSource("nompools-staking"), signal);
|
4998
|
+
// const unsubCrowdloans = subscribeCrowdloans(
|
4999
|
+
// chaindataProvider,
|
5000
|
+
// chainConnectors.substrate,
|
5001
|
+
// newAddressesByToken,
|
5002
|
+
// handleUpdateForSource("crowdloan"),
|
5003
|
+
// signal,
|
5004
|
+
// )
|
5160
5005
|
const unsubBase = subscribeBase(baseQueries, chainConnectors.substrate, handleUpdateForSource("base"));
|
5161
5006
|
subscriber.add(async () => (await unsubSubtensorStaking)());
|
5162
5007
|
subscriber.add(async () => (await unsubNompoolStaking)());
|
5163
|
-
subscriber.add(async () => (await unsubCrowdloans)())
|
5008
|
+
// subscriber.add(async () => (await unsubCrowdloans)())
|
5164
5009
|
subscriber.add(async () => (await unsubBase)());
|
5165
5010
|
});
|
5166
5011
|
}));
|
@@ -5192,8 +5037,13 @@ const SubNativeModule = hydrate => {
|
|
5192
5037
|
const nonCurrentTokens = Object.keys(addressesByToken).filter(tokenId => !currentTokens.has(tokenId)).sort(sortChains);
|
5193
5038
|
|
5194
5039
|
// break nonCurrentTokens into chunks of POLLING_WINDOW_SIZE
|
5195
|
-
|
5040
|
+
const pool = new PQueue__default.default({
|
5041
|
+
concurrency: POLLING_WINDOW_SIZE
|
5042
|
+
});
|
5043
|
+
nonCurrentTokens.forEach(nonCurrentTokenId => pool.add(() => poll({
|
5196
5044
|
[nonCurrentTokenId]: addressesByToken[nonCurrentTokenId]
|
5045
|
+
}), {
|
5046
|
+
signal
|
5197
5047
|
}));
|
5198
5048
|
|
5199
5049
|
// now poll every 30s on chains which are not subscriptionTokens
|
@@ -5206,7 +5056,9 @@ const SubNativeModule = hydrate => {
|
|
5206
5056
|
Object.keys(addressesByToken).filter(tokenId => !subscribedTokenIds.includes(tokenId))), rxjs.exhaustMap(tokenIds => rxjs.from(util$1.arrayChunk(tokenIds, POLLING_WINDOW_SIZE)).pipe(rxjs.concatMap(async tokenChunk => {
|
5207
5057
|
// tokenChunk is a chunk of tokenIds with size POLLING_WINDOW_SIZE
|
5208
5058
|
const pollingTokenAddresses = Object.fromEntries(tokenChunk.map(tokenId => [tokenId, addressesByToken[tokenId]]));
|
5209
|
-
await poll(pollingTokenAddresses)
|
5059
|
+
await pool.add(() => poll(pollingTokenAddresses), {
|
5060
|
+
signal
|
5061
|
+
});
|
5210
5062
|
return true;
|
5211
5063
|
})))).subscribe();
|
5212
5064
|
return () => {
|
@@ -5251,7 +5103,7 @@ const SubNativeModule = hydrate => {
|
|
5251
5103
|
};
|
5252
5104
|
const existentialDeposit = getConstantValue("Balances", "ExistentialDeposit")?.toString();
|
5253
5105
|
const nominationPoolsPalletId = getConstantValue("NominationPools", "PalletId")?.asText();
|
5254
|
-
const crowdloanPalletId = getConstantValue("Crowdloan", "PalletId")?.asText();
|
5106
|
+
const crowdloanPalletId = getConstantValue("Crowdloan", "PalletId")?.asText(); // TODO yeet
|
5255
5107
|
const hasSubtensorPallet = getConstantValue("SubtensorModule", "KeySwapCost") !== undefined;
|
5256
5108
|
|
5257
5109
|
//
|
@@ -5274,10 +5126,13 @@ const SubNativeModule = hydrate => {
|
|
5274
5126
|
}, {
|
5275
5127
|
pallet: "Crowdloan",
|
5276
5128
|
items: ["Funds"]
|
5277
|
-
},
|
5129
|
+
},
|
5130
|
+
// TODO yeet
|
5131
|
+
{
|
5278
5132
|
pallet: "Paras",
|
5279
5133
|
items: ["Parachains"]
|
5280
5134
|
},
|
5135
|
+
// TODO yeet
|
5281
5136
|
// TotalColdkeyStake is used until v.2.2.1, then it is replaced by StakingHotkeys+Stake
|
5282
5137
|
// Need to keep TotalColdkeyStake for a while so chaindata keeps including it in miniMetadatas, so it doesnt break old versions of the wallet
|
5283
5138
|
{
|
@@ -5320,22 +5175,24 @@ const SubNativeModule = hydrate => {
|
|
5320
5175
|
const {
|
5321
5176
|
existentialDeposit
|
5322
5177
|
} = chainMeta.extra ?? {};
|
5178
|
+
if (existentialDeposit === undefined) log.warn("Substrate native module: existentialDeposit is undefined for %s, using 0", chainId);
|
5323
5179
|
const id = chaindataProvider.subNativeTokenId(chainId);
|
5324
5180
|
const nativeToken = {
|
5325
5181
|
id,
|
5326
5182
|
type: "substrate-native",
|
5327
5183
|
platform: "polkadot",
|
5328
|
-
isDefault:
|
5184
|
+
isDefault: true,
|
5329
5185
|
symbol: symbol,
|
5330
|
-
name:
|
5186
|
+
name: symbol,
|
5331
5187
|
decimals: decimals,
|
5332
|
-
logo: moduleConfig?.logo,
|
5333
5188
|
existentialDeposit: existentialDeposit ?? "0",
|
5334
5189
|
networkId: chainId
|
5335
5190
|
};
|
5336
|
-
|
5337
|
-
if (moduleConfig?.
|
5338
|
-
if (moduleConfig?.
|
5191
|
+
|
5192
|
+
// if (moduleConfig?.symbol) nativeToken.symbol = moduleConfig?.symbol
|
5193
|
+
// if (moduleConfig?.coingeckoId) nativeToken.coingeckoId = moduleConfig?.coingeckoId
|
5194
|
+
// if (moduleConfig?.mirrorOf) nativeToken.mirrorOf = moduleConfig?.mirrorOf
|
5195
|
+
|
5339
5196
|
return {
|
5340
5197
|
[nativeToken.id]: nativeToken
|
5341
5198
|
};
|
@@ -5367,11 +5224,11 @@ const SubNativeModule = hydrate => {
|
|
5367
5224
|
return subscribeChainBalances(networkId, {
|
5368
5225
|
addressesByToken: addressesByTokenByNetwork[networkId] ?? {},
|
5369
5226
|
initialBalances: initialBalancesByNetwork[networkId] ?? []
|
5370
|
-
}, safeCallback);
|
5227
|
+
}, safeCallback, controller.signal);
|
5371
5228
|
}));
|
5372
5229
|
return () => {
|
5373
|
-
controller.abort();
|
5374
5230
|
unsubsribeFns.then(fns => fns.forEach(unsubscribe => unsubscribe()));
|
5231
|
+
controller.abort();
|
5375
5232
|
};
|
5376
5233
|
},
|
5377
5234
|
fetchBalances,
|
@@ -6589,6 +6446,22 @@ var psp22Abi = {
|
|
6589
6446
|
};
|
6590
6447
|
|
6591
6448
|
const moduleType$1 = "substrate-psp22";
|
6449
|
+
const SubPsp22TokenConfigSchema = TokenConfigBaseSchema.extend({
|
6450
|
+
contractAddress: chaindataProvider.SubPsp22TokenSchema.shape.contractAddress,
|
6451
|
+
existentialDeposit: chaindataProvider.SubPsp22TokenSchema.shape.existentialDeposit.optional()
|
6452
|
+
});
|
6453
|
+
|
6454
|
+
// {
|
6455
|
+
// tokens?: Array<
|
6456
|
+
// {
|
6457
|
+
// symbol?: string
|
6458
|
+
// decimals?: number
|
6459
|
+
// ed?: string
|
6460
|
+
// contractAddress: string
|
6461
|
+
// } & BalancesConfigTokenParams
|
6462
|
+
// >
|
6463
|
+
// }
|
6464
|
+
|
6592
6465
|
const SubPsp22Module = hydrate => {
|
6593
6466
|
const {
|
6594
6467
|
chainConnectors,
|
@@ -6605,7 +6478,8 @@ const SubPsp22Module = hydrate => {
|
|
6605
6478
|
extra: null
|
6606
6479
|
};
|
6607
6480
|
},
|
6608
|
-
async fetchSubstrateChainTokens(chainId, _chainMeta, moduleConfig) {
|
6481
|
+
async fetchSubstrateChainTokens(chainId, _chainMeta, moduleConfig, tokens) {
|
6482
|
+
if (!tokens?.length) return {};
|
6609
6483
|
// const { isTestnet } = chainMeta
|
6610
6484
|
|
6611
6485
|
const registry = new types.TypeRegistry();
|
@@ -6617,12 +6491,12 @@ const SubPsp22Module = hydrate => {
|
|
6617
6491
|
chainId,
|
6618
6492
|
registry
|
6619
6493
|
});
|
6620
|
-
const
|
6621
|
-
for (const tokenConfig of
|
6494
|
+
const tokenList = {};
|
6495
|
+
for (const tokenConfig of tokens ?? []) {
|
6622
6496
|
try {
|
6623
6497
|
let symbol = tokenConfig?.symbol ?? "Unit";
|
6624
6498
|
let decimals = tokenConfig?.decimals ?? 0;
|
6625
|
-
const existentialDeposit = tokenConfig?.
|
6499
|
+
const existentialDeposit = tokenConfig?.existentialDeposit ?? "0";
|
6626
6500
|
const contractAddress = tokenConfig?.contractAddress ?? undefined;
|
6627
6501
|
if (contractAddress === undefined) continue;
|
6628
6502
|
await (async () => {
|
@@ -6655,13 +6529,13 @@ const SubPsp22Module = hydrate => {
|
|
6655
6529
|
};
|
6656
6530
|
if (tokenConfig?.coingeckoId) token.coingeckoId = tokenConfig?.coingeckoId;
|
6657
6531
|
if (tokenConfig?.mirrorOf) token.mirrorOf = tokenConfig?.mirrorOf;
|
6658
|
-
|
6532
|
+
tokenList[token.id] = token;
|
6659
6533
|
} catch (error) {
|
6660
6534
|
log.error(`Failed to build substrate-psp22 token ${tokenConfig.contractAddress} (${tokenConfig.symbol}) on ${chainId}`, error?.message ?? error);
|
6661
6535
|
continue;
|
6662
6536
|
}
|
6663
6537
|
}
|
6664
|
-
return
|
6538
|
+
return tokenList;
|
6665
6539
|
},
|
6666
6540
|
// TODO: Don't create empty subscriptions
|
6667
6541
|
async subscribeBalances({
|
@@ -6836,11 +6710,28 @@ const fetchBalances = async (chainConnector, tokens, addressesByToken) => {
|
|
6836
6710
|
};
|
6837
6711
|
|
6838
6712
|
const moduleType = "substrate-tokens";
|
6713
|
+
const SubTokensTokenConfigSchema = TokenConfigBaseSchema.extend({
|
6714
|
+
onChainId: chaindataProvider.SubTokensTokenSchema.shape.onChainId,
|
6715
|
+
existentialDeposit: chaindataProvider.SubTokensTokenSchema.shape.existentialDeposit
|
6716
|
+
});
|
6839
6717
|
const defaultPalletId = "Tokens";
|
6840
6718
|
const UNSUPPORTED_CHAIN_META = {
|
6841
6719
|
miniMetadata: null,
|
6842
6720
|
extra: {}
|
6843
6721
|
};
|
6722
|
+
|
6723
|
+
// {
|
6724
|
+
// palletId?: string // TODO unlikely it will ever be used - remove this ?
|
6725
|
+
// tokens?: Array<
|
6726
|
+
// {
|
6727
|
+
// symbol?: string
|
6728
|
+
// decimals?: number
|
6729
|
+
// ed?: string
|
6730
|
+
// onChainId?: string | number
|
6731
|
+
// } & BalancesConfigTokenParams
|
6732
|
+
// >
|
6733
|
+
// }
|
6734
|
+
|
6844
6735
|
const SubTokensModule = hydrate => {
|
6845
6736
|
const {
|
6846
6737
|
chainConnectors,
|
@@ -6866,13 +6757,14 @@ const SubTokensModule = hydrate => {
|
|
6866
6757
|
}
|
6867
6758
|
};
|
6868
6759
|
},
|
6869
|
-
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig) {
|
6870
|
-
const
|
6871
|
-
for (const tokenConfig of
|
6760
|
+
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig, tokens) {
|
6761
|
+
const tokenList = {};
|
6762
|
+
for (const tokenConfig of tokens ?? []) {
|
6872
6763
|
try {
|
6764
|
+
// TODO fetch metadata from chain, like we do for assets
|
6873
6765
|
const symbol = tokenConfig?.symbol ?? "Unit";
|
6874
6766
|
const decimals = tokenConfig?.decimals ?? 0;
|
6875
|
-
const existentialDeposit = tokenConfig?.
|
6767
|
+
const existentialDeposit = tokenConfig?.existentialDeposit ?? "0";
|
6876
6768
|
const onChainId = tokenConfig?.onChainId ?? undefined;
|
6877
6769
|
if (onChainId === undefined) continue;
|
6878
6770
|
const id = chaindataProvider.subTokensTokenId(chainId, onChainId);
|
@@ -6891,13 +6783,13 @@ const SubTokensModule = hydrate => {
|
|
6891
6783
|
};
|
6892
6784
|
if (tokenConfig?.coingeckoId) token.coingeckoId = tokenConfig?.coingeckoId;
|
6893
6785
|
if (tokenConfig?.mirrorOf) token.mirrorOf = tokenConfig?.mirrorOf;
|
6894
|
-
|
6786
|
+
tokenList[token.id] = token;
|
6895
6787
|
} catch (error) {
|
6896
6788
|
log.error(`Failed to build substrate-tokens token ${tokenConfig.onChainId} (${tokenConfig.symbol}) on ${chainId}`, error?.message ?? error);
|
6897
6789
|
continue;
|
6898
6790
|
}
|
6899
6791
|
}
|
6900
|
-
return
|
6792
|
+
return tokenList;
|
6901
6793
|
},
|
6902
6794
|
// TODO: Don't create empty subscriptions
|
6903
6795
|
async subscribeBalances({
|
@@ -6927,10 +6819,10 @@ const SubTokensModule = hydrate => {
|
|
6927
6819
|
}
|
6928
6820
|
}));
|
6929
6821
|
return () => {
|
6930
|
-
controller.abort();
|
6931
6822
|
pUnsubs.then(unsubs => {
|
6932
6823
|
unsubs.forEach(unsubscribe => unsubscribe());
|
6933
6824
|
});
|
6825
|
+
controller.abort();
|
6934
6826
|
};
|
6935
6827
|
},
|
6936
6828
|
async fetchBalances(addressesByToken) {
|
@@ -7146,9 +7038,12 @@ exports.Balances = Balances;
|
|
7146
7038
|
exports.Change24hCurrencyFormatter = Change24hCurrencyFormatter;
|
7147
7039
|
exports.DefaultBalanceModule = DefaultBalanceModule;
|
7148
7040
|
exports.EvmErc20Module = EvmErc20Module;
|
7041
|
+
exports.EvmErc20TokenConfigSchema = EvmErc20TokenConfigSchema;
|
7149
7042
|
exports.EvmNativeModule = EvmNativeModule;
|
7043
|
+
exports.EvmNativeTokenConfigSchema = EvmNativeTokenConfigSchema;
|
7150
7044
|
exports.EvmTokenFetcher = EvmTokenFetcher;
|
7151
7045
|
exports.EvmUniswapV2Module = EvmUniswapV2Module;
|
7046
|
+
exports.EvmUniswapV2TokenConfigSchema = EvmUniswapV2TokenConfigSchema;
|
7152
7047
|
exports.FiatSumBalancesFormatter = FiatSumBalancesFormatter;
|
7153
7048
|
exports.ONE_ALPHA_TOKEN = ONE_ALPHA_TOKEN;
|
7154
7049
|
exports.PlanckSumBalancesFormatter = PlanckSumBalancesFormatter;
|
@@ -7157,10 +7052,15 @@ exports.SCALE_FACTOR = SCALE_FACTOR;
|
|
7157
7052
|
exports.SUBTENSOR_MIN_STAKE_AMOUNT_PLANK = SUBTENSOR_MIN_STAKE_AMOUNT_PLANK;
|
7158
7053
|
exports.SUBTENSOR_ROOT_NETUID = SUBTENSOR_ROOT_NETUID;
|
7159
7054
|
exports.SubAssetsModule = SubAssetsModule;
|
7055
|
+
exports.SubAssetsTokenConfigSchema = SubAssetsTokenConfigSchema;
|
7160
7056
|
exports.SubForeignAssetsModule = SubForeignAssetsModule;
|
7057
|
+
exports.SubForeignAssetsTokenConfigSchema = SubForeignAssetsTokenConfigSchema;
|
7161
7058
|
exports.SubNativeModule = SubNativeModule;
|
7059
|
+
exports.SubNativeTokenConfigSchema = SubNativeTokenConfigSchema;
|
7162
7060
|
exports.SubPsp22Module = SubPsp22Module;
|
7061
|
+
exports.SubPsp22TokenConfigSchema = SubPsp22TokenConfigSchema;
|
7163
7062
|
exports.SubTokensModule = SubTokensModule;
|
7063
|
+
exports.SubTokensTokenConfigSchema = SubTokensTokenConfigSchema;
|
7164
7064
|
exports.SumBalancesFormatter = SumBalancesFormatter;
|
7165
7065
|
exports.TalismanBalancesDatabase = TalismanBalancesDatabase;
|
7166
7066
|
exports.abiMulticall = abiMulticall;
|