@talismn/balances 0.0.0-pr2043-20250619165342 → 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 +241 -339
- package/dist/talismn-balances.cjs.prod.js +241 -339
- package/dist/talismn-balances.esm.js +238 -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,12 +2746,15 @@ 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 {
|
2701
2755
|
return await pResult;
|
2702
2756
|
} catch (cause) {
|
2757
|
+
if (util.isAbortError(cause)) throw cause;
|
2703
2758
|
throw new Error(`Failed to fetch metadataRpc for network ${networkId}`, {
|
2704
2759
|
cause
|
2705
2760
|
});
|
@@ -2717,6 +2772,8 @@ const POOL = new PQueue__default.default({
|
|
2717
2772
|
});
|
2718
2773
|
const getMiniMetadatas = async (chainConnector, chaindataProvider, networkId, specVersion, signal) => {
|
2719
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
|
+
);
|
2720
2777
|
const pResult = POOL.add(() => fetchMiniMetadatas(chainConnector, chaindataProvider, networkId, specVersion), {
|
2721
2778
|
signal
|
2722
2779
|
});
|
@@ -2724,6 +2781,7 @@ const getMiniMetadatas = async (chainConnector, chaindataProvider, networkId, sp
|
|
2724
2781
|
try {
|
2725
2782
|
return await pResult;
|
2726
2783
|
} catch (cause) {
|
2784
|
+
if (util.isAbortError(cause)) throw cause;
|
2727
2785
|
throw new Error(`Failed to fetch metadataRpc for network ${networkId}`, {
|
2728
2786
|
cause
|
2729
2787
|
});
|
@@ -2731,9 +2789,10 @@ const getMiniMetadatas = async (chainConnector, chaindataProvider, networkId, sp
|
|
2731
2789
|
CACHE.delete(networkId);
|
2732
2790
|
}
|
2733
2791
|
};
|
2792
|
+
const DotBalanceModuleTypeSchema = z__default.default.keyof(chaindataProvider.DotNetworkBalancesConfigSchema);
|
2734
2793
|
const fetchMiniMetadatas = async (chainConnector, chaindataProvider, chainId, specVersion, signal) => {
|
2735
2794
|
const start = performance.now();
|
2736
|
-
log.
|
2795
|
+
log.info("[miniMetadata] fetching minimetadatas for %s", chainId);
|
2737
2796
|
try {
|
2738
2797
|
const metadataRpc = await getMetadataRpc(chainConnector, chainId);
|
2739
2798
|
signal?.throwIfAborted();
|
@@ -2744,10 +2803,14 @@ const fetchMiniMetadatas = async (chainConnector, chaindataProvider, chainId, sp
|
|
2744
2803
|
const modules = defaultBalanceModules.map(mod => mod({
|
2745
2804
|
chainConnectors,
|
2746
2805
|
chaindataProvider
|
2747
|
-
})).filter(mod => mod.type.
|
2806
|
+
})).filter(mod => DotBalanceModuleTypeSchema.safeParse(mod.type).success);
|
2748
2807
|
return Promise.all(modules.map(async mod => {
|
2749
2808
|
const source = mod.type;
|
2750
|
-
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);
|
2751
2814
|
return {
|
2752
2815
|
id: deriveMiniMetadataId({
|
2753
2816
|
source,
|
@@ -3073,10 +3136,23 @@ const decompress = data => {
|
|
3073
3136
|
};
|
3074
3137
|
|
3075
3138
|
const moduleType$4 = "substrate-assets";
|
3139
|
+
const SubAssetsTokenConfigSchema = TokenConfigBaseSchema.extend({
|
3140
|
+
assetId: chaindataProvider.SubAssetsTokenSchema.shape.assetId,
|
3141
|
+
existentialDeposit: chaindataProvider.SubAssetsTokenSchema.shape.existentialDeposit
|
3142
|
+
});
|
3076
3143
|
const UNSUPPORTED_CHAIN_META$3 = {
|
3077
3144
|
miniMetadata: null,
|
3078
3145
|
extra: null
|
3079
3146
|
};
|
3147
|
+
|
3148
|
+
// {
|
3149
|
+
// tokens?: Array<
|
3150
|
+
// {
|
3151
|
+
// assetId: number | string
|
3152
|
+
// } & BalancesConfigTokenParams
|
3153
|
+
// >
|
3154
|
+
// }
|
3155
|
+
|
3080
3156
|
const SubAssetsModule = hydrate => {
|
3081
3157
|
const {
|
3082
3158
|
chainConnectors,
|
@@ -3100,8 +3176,8 @@ const SubAssetsModule = hydrate => {
|
|
3100
3176
|
extra: null
|
3101
3177
|
};
|
3102
3178
|
},
|
3103
|
-
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig) {
|
3104
|
-
if (
|
3179
|
+
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig, tokens) {
|
3180
|
+
if (!tokens?.length) return {};
|
3105
3181
|
const {
|
3106
3182
|
miniMetadata
|
3107
3183
|
} = chainMeta;
|
@@ -3110,8 +3186,8 @@ const SubAssetsModule = hydrate => {
|
|
3110
3186
|
const scaleBuilder = scale.getDynamicBuilder(scale.getLookupFn(metadata));
|
3111
3187
|
const assetCoder = scaleBuilder.buildStorage("Assets", "Asset");
|
3112
3188
|
const metadataCoder = scaleBuilder.buildStorage("Assets", "Metadata");
|
3113
|
-
const
|
3114
|
-
for (const tokenConfig of
|
3189
|
+
const tokenList = {};
|
3190
|
+
for (const tokenConfig of tokens ?? []) {
|
3115
3191
|
try {
|
3116
3192
|
const assetId = String(tokenConfig.assetId);
|
3117
3193
|
const assetStateKey = tryEncode(assetCoder, BigInt(assetId)) ?? tryEncode(assetCoder, assetId);
|
@@ -3143,13 +3219,13 @@ const SubAssetsModule = hydrate => {
|
|
3143
3219
|
}
|
3144
3220
|
if (tokenConfig?.coingeckoId) token.coingeckoId = tokenConfig?.coingeckoId;
|
3145
3221
|
if (tokenConfig?.mirrorOf) token.mirrorOf = tokenConfig?.mirrorOf;
|
3146
|
-
|
3222
|
+
tokenList[token.id] = token;
|
3147
3223
|
} catch (error) {
|
3148
3224
|
log.error(`Failed to build substrate-assets token ${tokenConfig.assetId} (${tokenConfig.symbol}) on ${chainId}`, error);
|
3149
3225
|
continue;
|
3150
3226
|
}
|
3151
3227
|
}
|
3152
|
-
return
|
3228
|
+
return tokenList;
|
3153
3229
|
},
|
3154
3230
|
// TODO: Don't create empty subscriptions
|
3155
3231
|
async subscribeBalances({
|
@@ -3179,10 +3255,10 @@ const SubAssetsModule = hydrate => {
|
|
3179
3255
|
}
|
3180
3256
|
}));
|
3181
3257
|
return () => {
|
3182
|
-
controller.abort();
|
3183
3258
|
pUnsubs.then(unsubs => {
|
3184
3259
|
unsubs.forEach(unsubscribe => unsubscribe());
|
3185
3260
|
});
|
3261
|
+
controller.abort();
|
3186
3262
|
};
|
3187
3263
|
},
|
3188
3264
|
async fetchBalances(addressesByToken) {
|
@@ -3366,6 +3442,19 @@ const UNSUPPORTED_CHAIN_META$2 = {
|
|
3366
3442
|
miniMetadata: null,
|
3367
3443
|
extra: null
|
3368
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
|
+
|
3369
3458
|
const SubForeignAssetsModule = hydrate => {
|
3370
3459
|
const {
|
3371
3460
|
chainConnectors,
|
@@ -3390,8 +3479,8 @@ const SubForeignAssetsModule = hydrate => {
|
|
3390
3479
|
extra: null
|
3391
3480
|
};
|
3392
3481
|
},
|
3393
|
-
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig) {
|
3394
|
-
if (
|
3482
|
+
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig, tokens) {
|
3483
|
+
if (!tokens?.length) return {};
|
3395
3484
|
const {
|
3396
3485
|
miniMetadata
|
3397
3486
|
} = chainMeta;
|
@@ -3401,8 +3490,8 @@ const SubForeignAssetsModule = hydrate => {
|
|
3401
3490
|
const scaleBuilder = scale.getDynamicBuilder(scale.getLookupFn(unifiedMetadata));
|
3402
3491
|
const assetCoder = scaleBuilder.buildStorage("ForeignAssets", "Asset");
|
3403
3492
|
const metadataCoder = scaleBuilder.buildStorage("ForeignAssets", "Metadata");
|
3404
|
-
const
|
3405
|
-
for (const tokenConfig of
|
3493
|
+
const tokenList = {};
|
3494
|
+
for (const tokenConfig of tokens ?? []) {
|
3406
3495
|
try {
|
3407
3496
|
const onChainId = (() => {
|
3408
3497
|
try {
|
@@ -3437,13 +3526,13 @@ const SubForeignAssetsModule = hydrate => {
|
|
3437
3526
|
};
|
3438
3527
|
if (tokenConfig?.coingeckoId) token.coingeckoId = tokenConfig?.coingeckoId;
|
3439
3528
|
if (tokenConfig?.mirrorOf) token.mirrorOf = tokenConfig?.mirrorOf;
|
3440
|
-
|
3529
|
+
tokenList[token.id] = token;
|
3441
3530
|
} catch (error) {
|
3442
3531
|
log.error(`Failed to build substrate-foreignassets token ${tokenConfig.onChainId} (${tokenConfig.symbol}) on ${chainId}`, error?.message ?? error);
|
3443
3532
|
continue;
|
3444
3533
|
}
|
3445
3534
|
}
|
3446
|
-
return
|
3535
|
+
return tokenList;
|
3447
3536
|
},
|
3448
3537
|
// TODO: Don't create empty subscriptions
|
3449
3538
|
async subscribeBalances({
|
@@ -3472,10 +3561,10 @@ const SubForeignAssetsModule = hydrate => {
|
|
3472
3561
|
}
|
3473
3562
|
}));
|
3474
3563
|
return () => {
|
3475
|
-
controller.abort();
|
3476
3564
|
pUnsubs.then(unsubs => {
|
3477
3565
|
unsubs.forEach(unsubscribe => unsubscribe());
|
3478
3566
|
});
|
3567
|
+
controller.abort();
|
3479
3568
|
};
|
3480
3569
|
},
|
3481
3570
|
async fetchBalances(addressesByToken) {
|
@@ -3662,263 +3751,6 @@ const asObservable = handler => (...args) => new rxjs.Observable(subscriber => {
|
|
3662
3751
|
return unsubscribe;
|
3663
3752
|
});
|
3664
3753
|
|
3665
|
-
/**
|
3666
|
-
* Crowdloan contributions are stored in the `childstate` key returned by this function.
|
3667
|
-
*/
|
3668
|
-
const crowdloanFundContributionsChildKey = fundIndex => util$1.u8aToHex(util$1.u8aConcat(":child_storage:default:", utilCrypto.blake2AsU8a(util$1.u8aConcat("crowdloan", scaleTs.u32.enc(fundIndex)))));
|
3669
|
-
|
3670
|
-
// TODO make this method chain-specific
|
3671
|
-
async function subscribeCrowdloans(chaindataProvider$1, chainConnector, addressesByToken, callback, signal) {
|
3672
|
-
const allChains = await chaindataProvider$1.chainsById();
|
3673
|
-
const tokens = await chaindataProvider$1.tokensById();
|
3674
|
-
|
3675
|
-
// there should be only one network here when subscribing to balances, we've split it up by network at the top level
|
3676
|
-
const networkIds = lodash.keys(addressesByToken).map(tokenId => chaindataProvider.parseTokenId(tokenId).networkId);
|
3677
|
-
const miniMetadatas = new Map();
|
3678
|
-
for (const networkId of networkIds) miniMetadatas.set(networkId, await getMiniMetadata(chaindataProvider$1, chainConnector, networkId, "substrate-native"));
|
3679
|
-
const crowdloanTokenIds = Object.entries(tokens).filter(([, token]) => {
|
3680
|
-
// ignore non-native tokens
|
3681
|
-
if (token.type !== "substrate-native") return;
|
3682
|
-
// ignore tokens on chains with no crowdloans pallet
|
3683
|
-
const miniMetadata = miniMetadatas.get(token.networkId);
|
3684
|
-
return typeof miniMetadata?.extra?.crowdloanPalletId === "string";
|
3685
|
-
}).map(([tokenId]) => tokenId);
|
3686
|
-
|
3687
|
-
// crowdloan contributions can only be done by the native token on chains with the crowdloan pallet
|
3688
|
-
const addressesByCrowdloanToken = Object.fromEntries(Object.entries(addressesByToken)
|
3689
|
-
// remove ethereum addresses
|
3690
|
-
.map(([tokenId, addresses]) => [tokenId, addresses.filter(address => !util.isEthereumAddress(address))])
|
3691
|
-
// remove tokens which aren't crowdloan tokens
|
3692
|
-
.filter(([tokenId]) => crowdloanTokenIds.includes(tokenId)));
|
3693
|
-
const uniqueChainIds = getUniqueChainIds(addressesByCrowdloanToken, tokens);
|
3694
|
-
const chains = Object.fromEntries(Object.entries(allChains).filter(([chainId]) => uniqueChainIds.includes(chainId)));
|
3695
|
-
const chainStorageCoders = buildStorageCoders({
|
3696
|
-
chainIds: uniqueChainIds,
|
3697
|
-
chains,
|
3698
|
-
miniMetadatas,
|
3699
|
-
coders: {
|
3700
|
-
parachains: ["Paras", "Parachains"],
|
3701
|
-
funds: ["Crowdloan", "Funds"]
|
3702
|
-
}
|
3703
|
-
});
|
3704
|
-
const tokenSubscriptions = [];
|
3705
|
-
for (const [tokenId, addresses] of Object.entries(addressesByCrowdloanToken)) {
|
3706
|
-
const token = tokens[tokenId];
|
3707
|
-
if (!token) {
|
3708
|
-
log.warn(`Token ${tokenId} not found`);
|
3709
|
-
continue;
|
3710
|
-
}
|
3711
|
-
if (token.type !== "substrate-native") {
|
3712
|
-
log.debug(`This module doesn't handle tokens of type ${token.type}`);
|
3713
|
-
continue;
|
3714
|
-
}
|
3715
|
-
const chainId = token.networkId;
|
3716
|
-
if (!chainId) {
|
3717
|
-
log.warn(`Token ${tokenId} has no chain`);
|
3718
|
-
continue;
|
3719
|
-
}
|
3720
|
-
const chain = chains[chainId];
|
3721
|
-
if (!chain) {
|
3722
|
-
log.warn(`Chain ${chainId} for token ${tokenId} not found`);
|
3723
|
-
continue;
|
3724
|
-
}
|
3725
|
-
const subscribeParaIds = callback => {
|
3726
|
-
const scaleCoder = chainStorageCoders.get(chainId)?.parachains;
|
3727
|
-
const queries = [0].flatMap(() => {
|
3728
|
-
const stateKey = scale.encodeStateKey(scaleCoder);
|
3729
|
-
if (!stateKey) return [];
|
3730
|
-
const decodeResult = change => {
|
3731
|
-
/** NOTE: This type is only a hint for typescript, the chain can actually return whatever it wants to */
|
3732
|
-
|
3733
|
-
const decoded = scale.decodeScale(scaleCoder, change, `Failed to decode parachains on chain ${chainId}`);
|
3734
|
-
const paraIds = decoded ?? [];
|
3735
|
-
return paraIds;
|
3736
|
-
};
|
3737
|
-
return {
|
3738
|
-
chainId,
|
3739
|
-
stateKey,
|
3740
|
-
decodeResult
|
3741
|
-
};
|
3742
|
-
});
|
3743
|
-
const subscription = new RpcStateQueryHelper(chainConnector, queries).subscribe(callback);
|
3744
|
-
return () => subscription.then(unsubscribe => unsubscribe());
|
3745
|
-
};
|
3746
|
-
const subscribeParaFundIndexes = (paraIds, callback) => {
|
3747
|
-
const scaleCoder = chainStorageCoders.get(chainId)?.funds;
|
3748
|
-
const queries = paraIds.flatMap(paraId => {
|
3749
|
-
const stateKey = scale.encodeStateKey(scaleCoder, `Invalid paraId in ${chainId} funds query ${paraId}`, paraId);
|
3750
|
-
if (!stateKey) return [];
|
3751
|
-
const decodeResult = change => {
|
3752
|
-
/** NOTE: This type is only a hint for typescript, the chain can actually return whatever it wants to */
|
3753
|
-
|
3754
|
-
const decoded = scale.decodeScale(scaleCoder, change, `Failed to decode paras on chain ${chainId}`);
|
3755
|
-
const firstPeriod = decoded?.first_period?.toString?.() ?? "";
|
3756
|
-
const lastPeriod = decoded?.last_period?.toString?.() ?? "";
|
3757
|
-
const fundPeriod = `${firstPeriod}-${lastPeriod}`;
|
3758
|
-
const fundIndex = decoded?.fund_index ?? decoded?.trie_index;
|
3759
|
-
return {
|
3760
|
-
paraId,
|
3761
|
-
fundPeriod,
|
3762
|
-
fundIndex
|
3763
|
-
};
|
3764
|
-
};
|
3765
|
-
return {
|
3766
|
-
chainId,
|
3767
|
-
stateKey,
|
3768
|
-
decodeResult
|
3769
|
-
};
|
3770
|
-
});
|
3771
|
-
const subscription = new RpcStateQueryHelper(chainConnector, queries).subscribe(callback);
|
3772
|
-
return () => subscription.then(unsubscribe => unsubscribe());
|
3773
|
-
};
|
3774
|
-
const subscribeFundContributions = (funds, addresses, callback) => {
|
3775
|
-
// TODO: Watch system_events in order to subscribe to changes, then redo the contributions query when changes are detected:
|
3776
|
-
// https://github.com/polkadot-js/api/blob/8fe02a14345b57e6abb8f7f2c2b624cf70c51b23/packages/api-derive/src/crowdloan/ownContributions.ts#L32-L47
|
3777
|
-
//
|
3778
|
-
// For now we just re-fetch all contributions on a timer and then only send them to the subscription callback when they have changed
|
3779
|
-
|
3780
|
-
const queries = funds.map(({
|
3781
|
-
paraId,
|
3782
|
-
fundIndex
|
3783
|
-
}) => ({
|
3784
|
-
paraId,
|
3785
|
-
fundIndex,
|
3786
|
-
addresses,
|
3787
|
-
childKey: crowdloanFundContributionsChildKey(fundIndex),
|
3788
|
-
storageKeys: addresses.map(address => util$1.u8aToHex(util.decodeAnyAddress(address)))
|
3789
|
-
}));
|
3790
|
-
|
3791
|
-
// track whether our caller is still subscribed
|
3792
|
-
let subscriptionActive = true;
|
3793
|
-
let previousContributions = null;
|
3794
|
-
const fetchContributions = async () => {
|
3795
|
-
try {
|
3796
|
-
const results = await Promise.all(queries.map(async ({
|
3797
|
-
paraId,
|
3798
|
-
fundIndex,
|
3799
|
-
addresses,
|
3800
|
-
childKey,
|
3801
|
-
storageKeys
|
3802
|
-
}) => ({
|
3803
|
-
paraId,
|
3804
|
-
fundIndex,
|
3805
|
-
addresses,
|
3806
|
-
result: await chainConnector.send(chainId, "childstate_getStorageEntries", [childKey, storageKeys])
|
3807
|
-
})));
|
3808
|
-
const contributions = results.flatMap(queryResult => {
|
3809
|
-
const {
|
3810
|
-
paraId,
|
3811
|
-
fundIndex,
|
3812
|
-
addresses,
|
3813
|
-
result
|
3814
|
-
} = queryResult;
|
3815
|
-
return (Array.isArray(result) ? result : []).flatMap((encoded, index) => {
|
3816
|
-
const amount = (() => {
|
3817
|
-
try {
|
3818
|
-
return typeof encoded === "string" ? scaleTs.u128.dec(encoded) ?? 0n : 0n;
|
3819
|
-
} catch {
|
3820
|
-
return 0n;
|
3821
|
-
}
|
3822
|
-
})().toString();
|
3823
|
-
return {
|
3824
|
-
paraId,
|
3825
|
-
fundIndex,
|
3826
|
-
address: addresses[index],
|
3827
|
-
amount
|
3828
|
-
};
|
3829
|
-
});
|
3830
|
-
});
|
3831
|
-
|
3832
|
-
// ignore these results if our caller has tried to close this subscription
|
3833
|
-
if (!subscriptionActive) return;
|
3834
|
-
|
3835
|
-
// ignore these results if they're the same as what we previously fetched
|
3836
|
-
if (isEqual__default.default(previousContributions, contributions)) return;
|
3837
|
-
previousContributions = contributions;
|
3838
|
-
callback(null, contributions);
|
3839
|
-
} catch (error) {
|
3840
|
-
callback(error);
|
3841
|
-
}
|
3842
|
-
};
|
3843
|
-
|
3844
|
-
// set up polling for contributions
|
3845
|
-
const crowdloanContributionsPollInterval = 60_000; // 60_000ms === 1 minute
|
3846
|
-
const pollContributions = async () => {
|
3847
|
-
if (!subscriptionActive) return;
|
3848
|
-
try {
|
3849
|
-
await fetchContributions();
|
3850
|
-
} catch (error) {
|
3851
|
-
// log any errors, but don't cancel the poll for contributions when one fetch fails
|
3852
|
-
log.error(error);
|
3853
|
-
}
|
3854
|
-
if (!subscriptionActive) return;
|
3855
|
-
setTimeout(pollContributions, crowdloanContributionsPollInterval);
|
3856
|
-
};
|
3857
|
-
|
3858
|
-
// start polling
|
3859
|
-
pollContributions();
|
3860
|
-
return () => {
|
3861
|
-
// stop polling
|
3862
|
-
subscriptionActive = false;
|
3863
|
-
};
|
3864
|
-
};
|
3865
|
-
const paraIds$ = asObservable(subscribeParaIds)().pipe(rxjs.scan((_, next) => Array.from(new Set(next.flatMap(paraIds => paraIds))), []), rxjs.share());
|
3866
|
-
const fundIndexesByParaId$ = paraIds$.pipe(rxjs.map(paraIds => asObservable(subscribeParaFundIndexes)(paraIds)), rxjs.switchAll(), rxjs.scan((state, next) => {
|
3867
|
-
for (const fund of next) {
|
3868
|
-
const {
|
3869
|
-
paraId,
|
3870
|
-
fundIndex
|
3871
|
-
} = fund;
|
3872
|
-
if (typeof fundIndex === "number") {
|
3873
|
-
state.set(paraId, (state.get(paraId) ?? new Set()).add(fundIndex));
|
3874
|
-
}
|
3875
|
-
}
|
3876
|
-
return state;
|
3877
|
-
}, new Map()));
|
3878
|
-
const contributionsByAddress$ = fundIndexesByParaId$.pipe(rxjs.map(fundIndexesByParaId => Array.from(fundIndexesByParaId).flatMap(([paraId, fundIndexes]) => Array.from(fundIndexes).map(fundIndex => ({
|
3879
|
-
paraId,
|
3880
|
-
fundIndex
|
3881
|
-
})))), rxjs.map(funds => asObservable(subscribeFundContributions)(funds, addresses)), rxjs.switchAll(), rxjs.scan((state, next) => {
|
3882
|
-
for (const contribution of next) {
|
3883
|
-
const {
|
3884
|
-
address
|
3885
|
-
} = contribution;
|
3886
|
-
state.set(address, (state.get(address) ?? new Set()).add(contribution));
|
3887
|
-
}
|
3888
|
-
return state;
|
3889
|
-
}, new Map()));
|
3890
|
-
const subscription = contributionsByAddress$.subscribe({
|
3891
|
-
next: contributionsByAddress => {
|
3892
|
-
const balances = Array.from(contributionsByAddress).map(([address, contributions]) => {
|
3893
|
-
return {
|
3894
|
-
source: "substrate-native",
|
3895
|
-
status: "live",
|
3896
|
-
address,
|
3897
|
-
networkId: chainId,
|
3898
|
-
tokenId,
|
3899
|
-
values: Array.from(contributions).map(({
|
3900
|
-
amount,
|
3901
|
-
paraId
|
3902
|
-
}) => ({
|
3903
|
-
type: "crowdloan",
|
3904
|
-
label: "crowdloan",
|
3905
|
-
source: "crowdloan",
|
3906
|
-
amount: amount,
|
3907
|
-
meta: {
|
3908
|
-
paraId
|
3909
|
-
}
|
3910
|
-
}))
|
3911
|
-
};
|
3912
|
-
});
|
3913
|
-
if (balances.length > 0) callback(null, balances);
|
3914
|
-
},
|
3915
|
-
error: error => callback(error)
|
3916
|
-
});
|
3917
|
-
tokenSubscriptions.push(() => subscription.unsubscribe());
|
3918
|
-
}
|
3919
|
-
return () => tokenSubscriptions.forEach(unsub => unsub());
|
3920
|
-
}
|
3921
|
-
|
3922
3754
|
/**
|
3923
3755
|
* Each nominationPool in the nominationPools pallet has access to some accountIds which have no
|
3924
3756
|
* associated private key. Instead, they are derived from this function.
|
@@ -3950,6 +3782,7 @@ async function subscribeNompoolStaking(chaindataProvider$1, chainConnector, addr
|
|
3950
3782
|
const miniMetadata = await getMiniMetadata(chaindataProvider$1, chainConnector, networkId, "substrate-native");
|
3951
3783
|
miniMetadatas.set(networkId, miniMetadata);
|
3952
3784
|
}
|
3785
|
+
signal?.throwIfAborted();
|
3953
3786
|
const nomPoolTokenIds = Object.entries(tokens).filter(([, token]) => {
|
3954
3787
|
// ignore non-native tokens
|
3955
3788
|
if (token.type !== "substrate-native") return false;
|
@@ -4267,9 +4100,10 @@ async function subscribeSubtensorStaking(chaindataProvider$1, chainConnector, ad
|
|
4267
4100
|
const networkIds = lodash.keys(addressesByToken).map(tokenId => chaindataProvider.parseTokenId(tokenId).networkId);
|
4268
4101
|
const miniMetadatas = new Map();
|
4269
4102
|
for (const networkId of networkIds) {
|
4270
|
-
const miniMetadata = await getMiniMetadata(chaindataProvider$1, chainConnector, networkId, "substrate-native");
|
4103
|
+
const miniMetadata = await getMiniMetadata(chaindataProvider$1, chainConnector, networkId, "substrate-native", signal);
|
4271
4104
|
miniMetadatas.set(networkId, miniMetadata);
|
4272
4105
|
}
|
4106
|
+
signal?.throwIfAborted();
|
4273
4107
|
const subtensorTokenIds = Object.entries(tokens).filter(([, token]) => {
|
4274
4108
|
// ignore non-native tokens
|
4275
4109
|
if (token.type !== "substrate-native") return false;
|
@@ -4475,7 +4309,9 @@ async function subscribeSubtensorStaking(chaindataProvider$1, chainConnector, ad
|
|
4475
4309
|
});
|
4476
4310
|
|
4477
4311
|
// use the abortController to tear the subscription down when we don't need it anymore
|
4478
|
-
abortController.signal.
|
4312
|
+
abortController.signal.addEventListener("abort", () => {
|
4313
|
+
subscription.unsubscribe();
|
4314
|
+
});
|
4479
4315
|
}
|
4480
4316
|
return () => abortController.abort();
|
4481
4317
|
}
|
@@ -4561,6 +4397,10 @@ const getLockTitle = (lock, {
|
|
4561
4397
|
|
4562
4398
|
const moduleType$2 = "substrate-native";
|
4563
4399
|
|
4400
|
+
// {
|
4401
|
+
// disable?: boolean
|
4402
|
+
// } & BalancesConfigTokenParams
|
4403
|
+
|
4564
4404
|
/**
|
4565
4405
|
* Function to merge two 'sub sources' of the same balance together, or
|
4566
4406
|
* two instances of the same balance with different values.
|
@@ -5038,6 +4878,7 @@ const UNSUPPORTED_CHAIN_META$1 = {
|
|
5038
4878
|
miniMetadata: null,
|
5039
4879
|
extra: null
|
5040
4880
|
};
|
4881
|
+
const SubNativeTokenConfigSchema = TokenConfigBaseSchema;
|
5041
4882
|
const SubNativeModule = hydrate => {
|
5042
4883
|
const {
|
5043
4884
|
chainConnectors,
|
@@ -5053,7 +4894,7 @@ const SubNativeModule = hydrate => {
|
|
5053
4894
|
// subscribeBalances was split by network to prevent all subs to wait for all minimetadatas to be ready.
|
5054
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
|
5055
4896
|
// TODO refactor this be actually network specific
|
5056
|
-
const subscribeChainBalances =
|
4897
|
+
const subscribeChainBalances = (chainId, opts, callback, signal) => {
|
5057
4898
|
const {
|
5058
4899
|
addressesByToken,
|
5059
4900
|
initialBalances
|
@@ -5152,13 +4993,19 @@ const SubNativeModule = hydrate => {
|
|
5152
4993
|
return rxjs.from(queryCache.getQueries(newAddressesByToken)).pipe(rxjs.switchMap(baseQueries => {
|
5153
4994
|
return new rxjs.Observable(subscriber => {
|
5154
4995
|
if (!chainConnectors.substrate) return;
|
5155
|
-
const unsubSubtensorStaking = subscribeSubtensorStaking(chaindataProvider$1, chainConnectors.substrate, newAddressesByToken, handleUpdateForSource("subtensor-staking"));
|
5156
|
-
const unsubNompoolStaking = subscribeNompoolStaking(chaindataProvider$1, chainConnectors.substrate, newAddressesByToken, handleUpdateForSource("nompools-staking"));
|
5157
|
-
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
|
+
// )
|
5158
5005
|
const unsubBase = subscribeBase(baseQueries, chainConnectors.substrate, handleUpdateForSource("base"));
|
5159
5006
|
subscriber.add(async () => (await unsubSubtensorStaking)());
|
5160
5007
|
subscriber.add(async () => (await unsubNompoolStaking)());
|
5161
|
-
subscriber.add(async () => (await unsubCrowdloans)())
|
5008
|
+
// subscriber.add(async () => (await unsubCrowdloans)())
|
5162
5009
|
subscriber.add(async () => (await unsubBase)());
|
5163
5010
|
});
|
5164
5011
|
}));
|
@@ -5190,8 +5037,13 @@ const SubNativeModule = hydrate => {
|
|
5190
5037
|
const nonCurrentTokens = Object.keys(addressesByToken).filter(tokenId => !currentTokens.has(tokenId)).sort(sortChains);
|
5191
5038
|
|
5192
5039
|
// break nonCurrentTokens into chunks of POLLING_WINDOW_SIZE
|
5193
|
-
|
5040
|
+
const pool = new PQueue__default.default({
|
5041
|
+
concurrency: POLLING_WINDOW_SIZE
|
5042
|
+
});
|
5043
|
+
nonCurrentTokens.forEach(nonCurrentTokenId => pool.add(() => poll({
|
5194
5044
|
[nonCurrentTokenId]: addressesByToken[nonCurrentTokenId]
|
5045
|
+
}), {
|
5046
|
+
signal
|
5195
5047
|
}));
|
5196
5048
|
|
5197
5049
|
// now poll every 30s on chains which are not subscriptionTokens
|
@@ -5204,7 +5056,9 @@ const SubNativeModule = hydrate => {
|
|
5204
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 => {
|
5205
5057
|
// tokenChunk is a chunk of tokenIds with size POLLING_WINDOW_SIZE
|
5206
5058
|
const pollingTokenAddresses = Object.fromEntries(tokenChunk.map(tokenId => [tokenId, addressesByToken[tokenId]]));
|
5207
|
-
await poll(pollingTokenAddresses)
|
5059
|
+
await pool.add(() => poll(pollingTokenAddresses), {
|
5060
|
+
signal
|
5061
|
+
});
|
5208
5062
|
return true;
|
5209
5063
|
})))).subscribe();
|
5210
5064
|
return () => {
|
@@ -5249,7 +5103,7 @@ const SubNativeModule = hydrate => {
|
|
5249
5103
|
};
|
5250
5104
|
const existentialDeposit = getConstantValue("Balances", "ExistentialDeposit")?.toString();
|
5251
5105
|
const nominationPoolsPalletId = getConstantValue("NominationPools", "PalletId")?.asText();
|
5252
|
-
const crowdloanPalletId = getConstantValue("Crowdloan", "PalletId")?.asText();
|
5106
|
+
const crowdloanPalletId = getConstantValue("Crowdloan", "PalletId")?.asText(); // TODO yeet
|
5253
5107
|
const hasSubtensorPallet = getConstantValue("SubtensorModule", "KeySwapCost") !== undefined;
|
5254
5108
|
|
5255
5109
|
//
|
@@ -5272,10 +5126,13 @@ const SubNativeModule = hydrate => {
|
|
5272
5126
|
}, {
|
5273
5127
|
pallet: "Crowdloan",
|
5274
5128
|
items: ["Funds"]
|
5275
|
-
},
|
5129
|
+
},
|
5130
|
+
// TODO yeet
|
5131
|
+
{
|
5276
5132
|
pallet: "Paras",
|
5277
5133
|
items: ["Parachains"]
|
5278
5134
|
},
|
5135
|
+
// TODO yeet
|
5279
5136
|
// TotalColdkeyStake is used until v.2.2.1, then it is replaced by StakingHotkeys+Stake
|
5280
5137
|
// Need to keep TotalColdkeyStake for a while so chaindata keeps including it in miniMetadatas, so it doesnt break old versions of the wallet
|
5281
5138
|
{
|
@@ -5318,22 +5175,24 @@ const SubNativeModule = hydrate => {
|
|
5318
5175
|
const {
|
5319
5176
|
existentialDeposit
|
5320
5177
|
} = chainMeta.extra ?? {};
|
5178
|
+
if (existentialDeposit === undefined) log.warn("Substrate native module: existentialDeposit is undefined for %s, using 0", chainId);
|
5321
5179
|
const id = chaindataProvider.subNativeTokenId(chainId);
|
5322
5180
|
const nativeToken = {
|
5323
5181
|
id,
|
5324
5182
|
type: "substrate-native",
|
5325
5183
|
platform: "polkadot",
|
5326
|
-
isDefault:
|
5184
|
+
isDefault: true,
|
5327
5185
|
symbol: symbol,
|
5328
|
-
name:
|
5186
|
+
name: symbol,
|
5329
5187
|
decimals: decimals,
|
5330
|
-
logo: moduleConfig?.logo,
|
5331
5188
|
existentialDeposit: existentialDeposit ?? "0",
|
5332
5189
|
networkId: chainId
|
5333
5190
|
};
|
5334
|
-
|
5335
|
-
if (moduleConfig?.
|
5336
|
-
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
|
+
|
5337
5196
|
return {
|
5338
5197
|
[nativeToken.id]: nativeToken
|
5339
5198
|
};
|
@@ -5365,11 +5224,11 @@ const SubNativeModule = hydrate => {
|
|
5365
5224
|
return subscribeChainBalances(networkId, {
|
5366
5225
|
addressesByToken: addressesByTokenByNetwork[networkId] ?? {},
|
5367
5226
|
initialBalances: initialBalancesByNetwork[networkId] ?? []
|
5368
|
-
}, safeCallback);
|
5227
|
+
}, safeCallback, controller.signal);
|
5369
5228
|
}));
|
5370
5229
|
return () => {
|
5371
|
-
controller.abort();
|
5372
5230
|
unsubsribeFns.then(fns => fns.forEach(unsubscribe => unsubscribe()));
|
5231
|
+
controller.abort();
|
5373
5232
|
};
|
5374
5233
|
},
|
5375
5234
|
fetchBalances,
|
@@ -6587,6 +6446,22 @@ var psp22Abi = {
|
|
6587
6446
|
};
|
6588
6447
|
|
6589
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
|
+
|
6590
6465
|
const SubPsp22Module = hydrate => {
|
6591
6466
|
const {
|
6592
6467
|
chainConnectors,
|
@@ -6603,7 +6478,8 @@ const SubPsp22Module = hydrate => {
|
|
6603
6478
|
extra: null
|
6604
6479
|
};
|
6605
6480
|
},
|
6606
|
-
async fetchSubstrateChainTokens(chainId, _chainMeta, moduleConfig) {
|
6481
|
+
async fetchSubstrateChainTokens(chainId, _chainMeta, moduleConfig, tokens) {
|
6482
|
+
if (!tokens?.length) return {};
|
6607
6483
|
// const { isTestnet } = chainMeta
|
6608
6484
|
|
6609
6485
|
const registry = new types.TypeRegistry();
|
@@ -6615,12 +6491,12 @@ const SubPsp22Module = hydrate => {
|
|
6615
6491
|
chainId,
|
6616
6492
|
registry
|
6617
6493
|
});
|
6618
|
-
const
|
6619
|
-
for (const tokenConfig of
|
6494
|
+
const tokenList = {};
|
6495
|
+
for (const tokenConfig of tokens ?? []) {
|
6620
6496
|
try {
|
6621
6497
|
let symbol = tokenConfig?.symbol ?? "Unit";
|
6622
6498
|
let decimals = tokenConfig?.decimals ?? 0;
|
6623
|
-
const existentialDeposit = tokenConfig?.
|
6499
|
+
const existentialDeposit = tokenConfig?.existentialDeposit ?? "0";
|
6624
6500
|
const contractAddress = tokenConfig?.contractAddress ?? undefined;
|
6625
6501
|
if (contractAddress === undefined) continue;
|
6626
6502
|
await (async () => {
|
@@ -6653,13 +6529,13 @@ const SubPsp22Module = hydrate => {
|
|
6653
6529
|
};
|
6654
6530
|
if (tokenConfig?.coingeckoId) token.coingeckoId = tokenConfig?.coingeckoId;
|
6655
6531
|
if (tokenConfig?.mirrorOf) token.mirrorOf = tokenConfig?.mirrorOf;
|
6656
|
-
|
6532
|
+
tokenList[token.id] = token;
|
6657
6533
|
} catch (error) {
|
6658
6534
|
log.error(`Failed to build substrate-psp22 token ${tokenConfig.contractAddress} (${tokenConfig.symbol}) on ${chainId}`, error?.message ?? error);
|
6659
6535
|
continue;
|
6660
6536
|
}
|
6661
6537
|
}
|
6662
|
-
return
|
6538
|
+
return tokenList;
|
6663
6539
|
},
|
6664
6540
|
// TODO: Don't create empty subscriptions
|
6665
6541
|
async subscribeBalances({
|
@@ -6834,11 +6710,28 @@ const fetchBalances = async (chainConnector, tokens, addressesByToken) => {
|
|
6834
6710
|
};
|
6835
6711
|
|
6836
6712
|
const moduleType = "substrate-tokens";
|
6713
|
+
const SubTokensTokenConfigSchema = TokenConfigBaseSchema.extend({
|
6714
|
+
onChainId: chaindataProvider.SubTokensTokenSchema.shape.onChainId,
|
6715
|
+
existentialDeposit: chaindataProvider.SubTokensTokenSchema.shape.existentialDeposit
|
6716
|
+
});
|
6837
6717
|
const defaultPalletId = "Tokens";
|
6838
6718
|
const UNSUPPORTED_CHAIN_META = {
|
6839
6719
|
miniMetadata: null,
|
6840
6720
|
extra: {}
|
6841
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
|
+
|
6842
6735
|
const SubTokensModule = hydrate => {
|
6843
6736
|
const {
|
6844
6737
|
chainConnectors,
|
@@ -6864,13 +6757,14 @@ const SubTokensModule = hydrate => {
|
|
6864
6757
|
}
|
6865
6758
|
};
|
6866
6759
|
},
|
6867
|
-
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig) {
|
6868
|
-
const
|
6869
|
-
for (const tokenConfig of
|
6760
|
+
async fetchSubstrateChainTokens(chainId, chainMeta, moduleConfig, tokens) {
|
6761
|
+
const tokenList = {};
|
6762
|
+
for (const tokenConfig of tokens ?? []) {
|
6870
6763
|
try {
|
6764
|
+
// TODO fetch metadata from chain, like we do for assets
|
6871
6765
|
const symbol = tokenConfig?.symbol ?? "Unit";
|
6872
6766
|
const decimals = tokenConfig?.decimals ?? 0;
|
6873
|
-
const existentialDeposit = tokenConfig?.
|
6767
|
+
const existentialDeposit = tokenConfig?.existentialDeposit ?? "0";
|
6874
6768
|
const onChainId = tokenConfig?.onChainId ?? undefined;
|
6875
6769
|
if (onChainId === undefined) continue;
|
6876
6770
|
const id = chaindataProvider.subTokensTokenId(chainId, onChainId);
|
@@ -6889,13 +6783,13 @@ const SubTokensModule = hydrate => {
|
|
6889
6783
|
};
|
6890
6784
|
if (tokenConfig?.coingeckoId) token.coingeckoId = tokenConfig?.coingeckoId;
|
6891
6785
|
if (tokenConfig?.mirrorOf) token.mirrorOf = tokenConfig?.mirrorOf;
|
6892
|
-
|
6786
|
+
tokenList[token.id] = token;
|
6893
6787
|
} catch (error) {
|
6894
6788
|
log.error(`Failed to build substrate-tokens token ${tokenConfig.onChainId} (${tokenConfig.symbol}) on ${chainId}`, error?.message ?? error);
|
6895
6789
|
continue;
|
6896
6790
|
}
|
6897
6791
|
}
|
6898
|
-
return
|
6792
|
+
return tokenList;
|
6899
6793
|
},
|
6900
6794
|
// TODO: Don't create empty subscriptions
|
6901
6795
|
async subscribeBalances({
|
@@ -6925,10 +6819,10 @@ const SubTokensModule = hydrate => {
|
|
6925
6819
|
}
|
6926
6820
|
}));
|
6927
6821
|
return () => {
|
6928
|
-
controller.abort();
|
6929
6822
|
pUnsubs.then(unsubs => {
|
6930
6823
|
unsubs.forEach(unsubscribe => unsubscribe());
|
6931
6824
|
});
|
6825
|
+
controller.abort();
|
6932
6826
|
};
|
6933
6827
|
},
|
6934
6828
|
async fetchBalances(addressesByToken) {
|
@@ -7144,9 +7038,12 @@ exports.Balances = Balances;
|
|
7144
7038
|
exports.Change24hCurrencyFormatter = Change24hCurrencyFormatter;
|
7145
7039
|
exports.DefaultBalanceModule = DefaultBalanceModule;
|
7146
7040
|
exports.EvmErc20Module = EvmErc20Module;
|
7041
|
+
exports.EvmErc20TokenConfigSchema = EvmErc20TokenConfigSchema;
|
7147
7042
|
exports.EvmNativeModule = EvmNativeModule;
|
7043
|
+
exports.EvmNativeTokenConfigSchema = EvmNativeTokenConfigSchema;
|
7148
7044
|
exports.EvmTokenFetcher = EvmTokenFetcher;
|
7149
7045
|
exports.EvmUniswapV2Module = EvmUniswapV2Module;
|
7046
|
+
exports.EvmUniswapV2TokenConfigSchema = EvmUniswapV2TokenConfigSchema;
|
7150
7047
|
exports.FiatSumBalancesFormatter = FiatSumBalancesFormatter;
|
7151
7048
|
exports.ONE_ALPHA_TOKEN = ONE_ALPHA_TOKEN;
|
7152
7049
|
exports.PlanckSumBalancesFormatter = PlanckSumBalancesFormatter;
|
@@ -7155,10 +7052,15 @@ exports.SCALE_FACTOR = SCALE_FACTOR;
|
|
7155
7052
|
exports.SUBTENSOR_MIN_STAKE_AMOUNT_PLANK = SUBTENSOR_MIN_STAKE_AMOUNT_PLANK;
|
7156
7053
|
exports.SUBTENSOR_ROOT_NETUID = SUBTENSOR_ROOT_NETUID;
|
7157
7054
|
exports.SubAssetsModule = SubAssetsModule;
|
7055
|
+
exports.SubAssetsTokenConfigSchema = SubAssetsTokenConfigSchema;
|
7158
7056
|
exports.SubForeignAssetsModule = SubForeignAssetsModule;
|
7057
|
+
exports.SubForeignAssetsTokenConfigSchema = SubForeignAssetsTokenConfigSchema;
|
7159
7058
|
exports.SubNativeModule = SubNativeModule;
|
7059
|
+
exports.SubNativeTokenConfigSchema = SubNativeTokenConfigSchema;
|
7160
7060
|
exports.SubPsp22Module = SubPsp22Module;
|
7061
|
+
exports.SubPsp22TokenConfigSchema = SubPsp22TokenConfigSchema;
|
7161
7062
|
exports.SubTokensModule = SubTokensModule;
|
7063
|
+
exports.SubTokensTokenConfigSchema = SubTokensTokenConfigSchema;
|
7162
7064
|
exports.SumBalancesFormatter = SumBalancesFormatter;
|
7163
7065
|
exports.TalismanBalancesDatabase = TalismanBalancesDatabase;
|
7164
7066
|
exports.abiMulticall = abiMulticall;
|