@talismn/balances 0.8.2 → 0.9.0
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 +1 -1
- package/dist/declarations/src/modules/SubstrateNativeModule/util/subtensor.d.ts +7 -43
- package/dist/declarations/src/modules/util/buildStorageCoders.d.ts +6 -4
- package/dist/declarations/src/modules/util/storageCompression.d.ts +1 -1
- package/dist/declarations/src/types/balances.d.ts +1 -5
- package/dist/talismn-balances.cjs.dev.js +61 -233
- package/dist/talismn-balances.cjs.prod.js +61 -233
- package/dist/talismn-balances.esm.js +63 -235
- package/package.json +11 -10
@@ -4,10 +4,10 @@ import { toHex, decodeMetadata, getDynamicBuilder, getLookupFn, compactMetadata,
|
|
4
4
|
import { Dexie, liveQuery } from 'dexie';
|
5
5
|
import isEqual from 'lodash/isEqual';
|
6
6
|
import { from, Observable, scan, share, map, switchAll, combineLatest, mergeMap, toArray, interval, startWith, exhaustMap, pipe, filter, shareReplay, combineLatestWith, distinctUntilChanged, firstValueFrom, BehaviorSubject, debounceTime, takeUntil, switchMap, withLatestFrom, concatMap } from 'rxjs';
|
7
|
-
import { u32, Option, Bytes, u128, Struct
|
7
|
+
import { u32, Option, Bytes, u128, Struct } from 'scale-ts';
|
8
8
|
import anylogger from 'anylogger';
|
9
9
|
import { newTokenRates } from '@talismn/token-rates';
|
10
|
-
import { BigMath,
|
10
|
+
import { isBigInt, BigMath, planckToTokens, isTruthy, isArrayOf, isEthereumAddress, hasOwnProperty, decodeAnyAddress, isNotNil, blake2Concat, firstThenDebounce, Deferred } from '@talismn/util';
|
11
11
|
import BigNumber from 'bignumber.js';
|
12
12
|
import { u8aToHex, assert, stringCamelCase, u8aConcatStrict, u8aConcat, arrayChunk, u8aToString, hexToNumber, hexToU8a } from '@polkadot/util';
|
13
13
|
import { xxhashAsU8a, blake2AsU8a } from '@polkadot/util-crypto';
|
@@ -20,6 +20,7 @@ import groupBy from 'lodash/groupBy';
|
|
20
20
|
import { mergeUint8, toHex as toHex$1 } from '@polkadot-api/utils';
|
21
21
|
import { Binary, AccountId } from 'polkadot-api';
|
22
22
|
import { ChainConnectionError } from '@talismn/chain-connector';
|
23
|
+
import { getScaleApi } from '@talismn/sapi';
|
23
24
|
import upperFirst from 'lodash/upperFirst';
|
24
25
|
import { Abi } from '@polkadot/api-contract';
|
25
26
|
|
@@ -95,88 +96,7 @@ class EvmTokenFetcher {
|
|
95
96
|
}
|
96
97
|
|
97
98
|
var packageJson = {
|
98
|
-
name: "@talismn/balances"
|
99
|
-
version: "0.8.2",
|
100
|
-
author: "Talisman",
|
101
|
-
homepage: "https://talisman.xyz",
|
102
|
-
license: "GPL-3.0-or-later",
|
103
|
-
publishConfig: {
|
104
|
-
access: "public"
|
105
|
-
},
|
106
|
-
repository: {
|
107
|
-
directory: "packages/balances",
|
108
|
-
type: "git",
|
109
|
-
url: "https://github.com/talismansociety/talisman.git"
|
110
|
-
},
|
111
|
-
main: "dist/talismn-balances.cjs.js",
|
112
|
-
module: "dist/talismn-balances.esm.js",
|
113
|
-
files: [
|
114
|
-
"/dist",
|
115
|
-
"/plugins"
|
116
|
-
],
|
117
|
-
engines: {
|
118
|
-
node: ">=18"
|
119
|
-
},
|
120
|
-
scripts: {
|
121
|
-
test: "jest",
|
122
|
-
lint: "eslint src --max-warnings 0",
|
123
|
-
clean: "rm -rf dist plugins/dist .turbo node_modules"
|
124
|
-
},
|
125
|
-
dependencies: {
|
126
|
-
"@polkadot-api/utils": "^0.1.2",
|
127
|
-
"@supercharge/promise-pool": "^3.2.0",
|
128
|
-
"@talismn/chain-connector": "workspace:*",
|
129
|
-
"@talismn/chain-connector-evm": "workspace:*",
|
130
|
-
"@talismn/chaindata-provider": "workspace:*",
|
131
|
-
"@talismn/scale": "workspace:*",
|
132
|
-
"@talismn/token-rates": "workspace:*",
|
133
|
-
"@talismn/util": "workspace:*",
|
134
|
-
anylogger: "^1.0.11",
|
135
|
-
"bignumber.js": "^9.1.2",
|
136
|
-
dexie: "^4.0.9",
|
137
|
-
lodash: "4.17.21",
|
138
|
-
pako: "^2.1.0",
|
139
|
-
"polkadot-api": "1.7.6",
|
140
|
-
rxjs: "^7.8.1",
|
141
|
-
"scale-ts": "^1.6.1",
|
142
|
-
viem: "^2.21.34"
|
143
|
-
},
|
144
|
-
devDependencies: {
|
145
|
-
"@polkadot/api-contract": "15.8.1",
|
146
|
-
"@polkadot/types": "15.8.1",
|
147
|
-
"@polkadot/util": "13.4.3",
|
148
|
-
"@polkadot/util-crypto": "13.4.3",
|
149
|
-
"@substrate/txwrapper-core": "7.5.3",
|
150
|
-
"@talismn/eslint-config": "workspace:*",
|
151
|
-
"@talismn/tsconfig": "workspace:*",
|
152
|
-
"@types/jest": "^29.5.14",
|
153
|
-
"@types/lodash": "^4.17.12",
|
154
|
-
"@types/pako": "^2.0.3",
|
155
|
-
eslint: "^8.57.1",
|
156
|
-
jest: "^29.7.0",
|
157
|
-
"ts-jest": "^29.2.5",
|
158
|
-
typescript: "^5.6.3"
|
159
|
-
},
|
160
|
-
peerDependencies: {
|
161
|
-
"@polkadot/api-contract": "*",
|
162
|
-
"@polkadot/types": "*",
|
163
|
-
"@polkadot/util": "*",
|
164
|
-
"@polkadot/util-crypto": "*",
|
165
|
-
"@substrate/txwrapper-core": "*"
|
166
|
-
},
|
167
|
-
preconstruct: {
|
168
|
-
entrypoints: [
|
169
|
-
"index.ts",
|
170
|
-
"plugins.ts"
|
171
|
-
]
|
172
|
-
},
|
173
|
-
eslintConfig: {
|
174
|
-
root: true,
|
175
|
-
"extends": [
|
176
|
-
"@talismn/eslint-config/base"
|
177
|
-
]
|
178
|
-
}
|
179
|
-
};
|
99
|
+
name: "@talismn/balances"};
|
180
100
|
|
181
101
|
var log = anylogger(packageJson.name);
|
182
102
|
|
@@ -362,13 +282,9 @@ class Balances {
|
|
362
282
|
return [...this];
|
363
283
|
}
|
364
284
|
|
365
|
-
/**
|
366
|
-
* Get an array of balances in this collection, sorted by chain sortIndex.
|
367
|
-
*
|
368
|
-
* @returns A sorted array of the balances in this collection.
|
369
|
-
*/
|
285
|
+
/** @deprecated use each instead */
|
370
286
|
get sorted() {
|
371
|
-
return
|
287
|
+
return this.each;
|
372
288
|
}
|
373
289
|
|
374
290
|
/**
|
@@ -400,7 +316,7 @@ const getBalanceId = balance => {
|
|
400
316
|
tokenId
|
401
317
|
} = balance;
|
402
318
|
const locationId = isBalanceEvm(balance) ? balance.evmNetworkId : balance.chainId;
|
403
|
-
return [source, address, locationId, tokenId].filter(
|
319
|
+
return [source, address, locationId, tokenId].filter(isTruthy).join("::");
|
404
320
|
};
|
405
321
|
|
406
322
|
/**
|
@@ -1042,7 +958,7 @@ const upgradeBalancesDataBlob = async tx => {
|
|
1042
958
|
...stuffToKeep
|
1043
959
|
} = balance;
|
1044
960
|
return stuffToKeep;
|
1045
|
-
}).filter(
|
961
|
+
}).filter(isTruthy);
|
1046
962
|
const output = pako.deflate(JSON.stringify(migratedData));
|
1047
963
|
// now write the compressed data back to the db and clear the old one
|
1048
964
|
await tx.table("balancesBlob").put({
|
@@ -1783,7 +1699,7 @@ const fetchBalances$3 = async (evmChainConnector, tokenAddressesByNetwork, erc20
|
|
1783
1699
|
const balances = await getEvmTokenBalances(publicClient, networkParams, result.errors, erc20Aggregators[evmNetworkId]);
|
1784
1700
|
|
1785
1701
|
// consider only non null balances in the results
|
1786
|
-
result.results.push(...balances.filter(
|
1702
|
+
result.results.push(...balances.filter(isTruthy).map((free, i) => ({
|
1787
1703
|
source: "evm-erc20",
|
1788
1704
|
status: "live",
|
1789
1705
|
address: networkParams[i].address,
|
@@ -3296,7 +3212,7 @@ const SubAssetsModule = hydrate => {
|
|
3296
3212
|
const assetStateKey = tryEncode(assetCoder, BigInt(assetId)) ?? tryEncode(assetCoder, assetId);
|
3297
3213
|
const metadataStateKey = tryEncode(metadataCoder, BigInt(assetId)) ?? tryEncode(metadataCoder, assetId);
|
3298
3214
|
if (assetStateKey === null || metadataStateKey === null) throw new Error(`Failed to encode stateKey for asset ${assetId} on chain ${chainId}`);
|
3299
|
-
const [assetsAsset, assetsMetadata] = await Promise.all([chainConnector.send(chainId, "state_getStorage", [assetStateKey]).then(result => assetCoder.dec(result) ?? null), chainConnector.send(chainId, "state_getStorage", [metadataStateKey]).then(result => metadataCoder.dec(result) ?? null)]);
|
3215
|
+
const [assetsAsset, assetsMetadata] = await Promise.all([chainConnector.send(chainId, "state_getStorage", [assetStateKey]).then(result => assetCoder.value.dec(result) ?? null), chainConnector.send(chainId, "state_getStorage", [metadataStateKey]).then(result => metadataCoder.value.dec(result) ?? null)]);
|
3300
3216
|
const existentialDeposit = assetsAsset?.min_balance?.toString?.() ?? "0";
|
3301
3217
|
const symbol = assetsMetadata?.symbol?.asText?.() ?? "Unit";
|
3302
3218
|
const decimals = assetsMetadata?.decimals ?? 0;
|
@@ -3463,15 +3379,9 @@ async function buildQueries$4(chaindataProvider, addressesByToken) {
|
|
3463
3379
|
|
3464
3380
|
const decoded = decodeScale(scaleCoder, change, `Failed to decode substrate-assets balance on chain ${chainId}`) ?? {
|
3465
3381
|
balance: 0n,
|
3466
|
-
is_frozen: false,
|
3467
|
-
reason: {
|
3468
|
-
type: "Sufficient"
|
3469
|
-
},
|
3470
3382
|
status: {
|
3471
3383
|
type: "Liquid"
|
3472
|
-
}
|
3473
|
-
extra: undefined
|
3474
|
-
};
|
3384
|
+
}};
|
3475
3385
|
const isFrozen = decoded?.status?.type === "Frozen";
|
3476
3386
|
const amount = (decoded?.balance ?? 0n).toString();
|
3477
3387
|
|
@@ -3523,7 +3433,7 @@ async function buildQueries$4(chaindataProvider, addressesByToken) {
|
|
3523
3433
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
3524
3434
|
const tryEncode = (scaleCoder, ...args) => {
|
3525
3435
|
try {
|
3526
|
-
return scaleCoder?.enc?.(...args);
|
3436
|
+
return scaleCoder?.keys?.enc?.(...args);
|
3527
3437
|
} catch {
|
3528
3438
|
return null;
|
3529
3439
|
}
|
@@ -3594,11 +3504,11 @@ const SubEquilibriumModule = hydrate => {
|
|
3594
3504
|
try {
|
3595
3505
|
const scaleBuilder = getDynamicBuilder(getLookupFn(metadata));
|
3596
3506
|
const assetsCoder = scaleBuilder.buildStorage("EqAssets", "Assets");
|
3597
|
-
const stateKey = assetsCoder.enc();
|
3507
|
+
const stateKey = assetsCoder.keys.enc();
|
3598
3508
|
|
3599
3509
|
/** NOTE: Just a guideline, the RPC can return whatever it wants */
|
3600
3510
|
|
3601
|
-
const assetsResult = await chainConnector.send(chainId, "state_getStorage", [stateKey]).then(result => assetsCoder.dec(result) ?? null);
|
3511
|
+
const assetsResult = await chainConnector.send(chainId, "state_getStorage", [stateKey]).then(result => assetsCoder.value.dec(result) ?? null);
|
3602
3512
|
const tokens = (Array.isArray(assetsResult) ? assetsResult : []).flatMap(asset => {
|
3603
3513
|
if (!asset) return [];
|
3604
3514
|
if (!asset?.id) return [];
|
@@ -3883,9 +3793,9 @@ const SubForeignAssetsModule = hydrate => {
|
|
3883
3793
|
}
|
3884
3794
|
})();
|
3885
3795
|
if (onChainId === undefined) continue;
|
3886
|
-
const assetStateKey = assetCoder.enc(onChainId);
|
3887
|
-
const metadataStateKey = metadataCoder.enc(onChainId);
|
3888
|
-
const [assetsAsset, assetsMetadata] = await Promise.all([chainConnector.send(chainId, "state_getStorage", [assetStateKey]).then(result => assetCoder.dec(result) ?? null), chainConnector.send(chainId, "state_getStorage", [metadataStateKey]).then(result => metadataCoder.dec(result) ?? null)]);
|
3796
|
+
const assetStateKey = assetCoder.keys.enc(onChainId);
|
3797
|
+
const metadataStateKey = metadataCoder.keys.enc(onChainId);
|
3798
|
+
const [assetsAsset, assetsMetadata] = await Promise.all([chainConnector.send(chainId, "state_getStorage", [assetStateKey]).then(result => assetCoder.value.dec(result) ?? null), chainConnector.send(chainId, "state_getStorage", [metadataStateKey]).then(result => metadataCoder.value.dec(result) ?? null)]);
|
3889
3799
|
const existentialDeposit = assetsAsset?.min_balance?.toString?.() ?? "0";
|
3890
3800
|
const symbol = assetsMetadata?.symbol?.asText?.() ?? "Unit";
|
3891
3801
|
const decimals = assetsMetadata?.decimals ?? 0;
|
@@ -4045,15 +3955,9 @@ async function buildQueries$2(chaindataProvider, addressesByToken) {
|
|
4045
3955
|
|
4046
3956
|
const decoded = decodeScale(scaleCoder, change, `Failed to decode substrate-foreignassets balance on chain ${chainId}`) ?? {
|
4047
3957
|
balance: 0n,
|
4048
|
-
is_frozen: false,
|
4049
|
-
reason: {
|
4050
|
-
type: "Sufficient"
|
4051
|
-
},
|
4052
3958
|
status: {
|
4053
3959
|
type: "Liquid"
|
4054
|
-
}
|
4055
|
-
extra: undefined
|
4056
|
-
};
|
3960
|
+
}};
|
4057
3961
|
const isFrozen = decoded?.status?.type === "Frozen";
|
4058
3962
|
const amount = (decoded?.balance ?? 0n).toString();
|
4059
3963
|
|
@@ -4116,7 +4020,7 @@ async function subscribeBase(queries, chainConnector, callback) {
|
|
4116
4020
|
* <TArgs, TResult>(...arguments: TArgs, callback: SubscriptionCallback<TResult>) => UnsubscribeFn
|
4117
4021
|
*/
|
4118
4022
|
const asObservable = handler => (...args) => new Observable(subscriber => {
|
4119
|
-
const callback = (error, result) => error ? subscriber.error(error) : subscriber.next(result);
|
4023
|
+
const callback = (error, result) => error || result === undefined ? subscriber.error(error) : subscriber.next(result);
|
4120
4024
|
const unsubscribe = handler(...args, callback);
|
4121
4025
|
return unsubscribe;
|
4122
4026
|
});
|
@@ -4662,7 +4566,7 @@ async function subscribeNompoolStaking(chaindataProvider, chainConnector, addres
|
|
4662
4566
|
}
|
4663
4567
|
}]
|
4664
4568
|
};
|
4665
|
-
}).filter(
|
4569
|
+
}).filter(isNotNil);
|
4666
4570
|
if (balances.length > 0) callback(null, balances);
|
4667
4571
|
},
|
4668
4572
|
error: error => callback(error)
|
@@ -4677,113 +4581,17 @@ const SUBTENSOR_MIN_STAKE_AMOUNT_PLANK = 1000000n;
|
|
4677
4581
|
const TAO_DECIMALS = 9n;
|
4678
4582
|
const SCALE_FACTOR = 10n ** TAO_DECIMALS; // Equivalent to 10e9 for precision
|
4679
4583
|
const ONE_ALPHA_TOKEN = SCALE_FACTOR;
|
4680
|
-
const BITTENSOR_TESTNET_CHAIN_ID = "bittensor-testnet";
|
4681
|
-
const BittensorAccountPrefix = 42;
|
4682
|
-
const BittensorAccountId = AccountId(BittensorAccountPrefix);
|
4683
|
-
|
4684
|
-
/** For encoding/decoding the GetStakeInfoForColdkey runtime api *after* they added the netuid parameter */
|
4685
|
-
const StakeInfo = Struct({
|
4686
|
-
hotkey: BittensorAccountId,
|
4687
|
-
coldkey: BittensorAccountId,
|
4688
|
-
netuid: compact,
|
4689
|
-
stake: compact,
|
4690
|
-
locked: compact,
|
4691
|
-
emission: compact,
|
4692
|
-
tao_emission: compact,
|
4693
|
-
drain: compact,
|
4694
|
-
isRegistered: bool
|
4695
|
-
});
|
4696
|
-
const EncodeParams_GetStakeInfoForColdkey = address => toHex$1(BittensorAccountId.enc(address));
|
4697
|
-
const DecodeResult_GetStakeInfoForColdkey = result => Vector(StakeInfo).dec(result);
|
4698
|
-
/** Encoding/decoding for GetStakeDynamicInfo */
|
4699
|
-
const EncodeParams_GetDynamicInfo = netuid => {
|
4700
|
-
if (netuid < 0 || netuid > 65535) {
|
4701
|
-
throw new Error("netuid must be a valid u16 (0-65535)");
|
4702
|
-
}
|
4703
|
-
|
4704
|
-
// Convert the number to a Uint8Array (LE encoding)
|
4705
|
-
const encoded = new Uint8Array(2);
|
4706
|
-
encoded[0] = netuid & 0xff; // Lower byte
|
4707
|
-
encoded[1] = netuid >> 8 & 0xff; // Upper byte
|
4708
|
-
|
4709
|
-
// Convert to hex string
|
4710
|
-
return toHex$1(encoded);
|
4711
|
-
};
|
4712
|
-
/** I96F32 representation (Fixed-Point) */
|
4713
|
-
const I96F32 = Struct({
|
4714
|
-
bits: compact
|
4715
|
-
});
|
4716
|
-
const SubnetIdentityV2 = Struct({
|
4717
|
-
subnetName: Bytes(),
|
4718
|
-
githubRepo: Bytes(),
|
4719
|
-
subnetContact: Bytes(),
|
4720
|
-
subnetUrl: Bytes(),
|
4721
|
-
discord: Bytes(),
|
4722
|
-
description: Bytes()
|
4723
|
-
});
|
4724
|
-
const DynamicInfo = Struct({
|
4725
|
-
netuid: compact,
|
4726
|
-
ownerHotkey: BittensorAccountId,
|
4727
|
-
ownerColdkey: BittensorAccountId,
|
4728
|
-
subnetName: Vector(compact),
|
4729
|
-
tokenSymbol: Vector(compact),
|
4730
|
-
tempo: compact,
|
4731
|
-
lastStep: compact,
|
4732
|
-
blocksSinceLastStep: compact,
|
4733
|
-
emission: compact,
|
4734
|
-
alphaIn: compact,
|
4735
|
-
alphaOut: compact,
|
4736
|
-
taoIn: compact,
|
4737
|
-
alphaOutEmission: compact,
|
4738
|
-
alphaInEmission: compact,
|
4739
|
-
taoInEmission: compact,
|
4740
|
-
pendingAlphaEmission: compact,
|
4741
|
-
pendingRootEmission: compact,
|
4742
|
-
subnetVolume: compact,
|
4743
|
-
networkRegisteredAt: compact,
|
4744
|
-
subnetIdentity: Option(SubnetIdentityV2),
|
4745
|
-
movingPrice: I96F32
|
4746
|
-
});
|
4747
|
-
const DecodeResult_GetDynamicInfo = result => {
|
4748
|
-
const LITTLE_ENDIAN_OFFSET = 256;
|
4749
|
-
const decoded = DynamicInfo.dec(result);
|
4750
|
-
const {
|
4751
|
-
netuid: netuidLittleEndian,
|
4752
|
-
subnetIdentity: subnetIdentityScaleOption = {},
|
4753
|
-
tokenSymbol: tokenSymbolU8Arr,
|
4754
|
-
taoIn,
|
4755
|
-
alphaIn,
|
4756
|
-
subnetName: subnetNameVector
|
4757
|
-
} = decoded;
|
4758
|
-
const netuid = Number(netuidLittleEndian) / LITTLE_ENDIAN_OFFSET;
|
4759
|
-
const tokenSymbol = new TextDecoder().decode(Uint8Array.from(tokenSymbolU8Arr.map(val => Number(val))));
|
4760
|
-
const subnetName = new TextDecoder().decode(Uint8Array.from(subnetNameVector.map(val => Number(val))));
|
4761
|
-
const subnetIdentity = Object.keys(subnetIdentityScaleOption).reduce((acc, key) => {
|
4762
|
-
const value = subnetIdentityScaleOption[key];
|
4763
|
-
acc[key] = new TextDecoder().decode(value);
|
4764
|
-
return acc;
|
4765
|
-
}, {});
|
4766
|
-
return {
|
4767
|
-
...decoded,
|
4768
|
-
netuid,
|
4769
|
-
tokenSymbol,
|
4770
|
-
subnetIdentity,
|
4771
|
-
taoIn: BigInt(taoIn),
|
4772
|
-
alphaIn: BigInt(alphaIn),
|
4773
|
-
subnetName
|
4774
|
-
};
|
4775
|
-
};
|
4776
4584
|
const calculateAlphaPrice = ({
|
4777
4585
|
dynamicInfo
|
4778
4586
|
}) => {
|
4779
4587
|
if (!dynamicInfo) return 0n;
|
4780
4588
|
const {
|
4781
|
-
|
4782
|
-
|
4589
|
+
alpha_in,
|
4590
|
+
tao_in
|
4783
4591
|
} = dynamicInfo;
|
4784
4592
|
|
4785
4593
|
// Scale taoIn before division to preserve precision
|
4786
|
-
const result =
|
4594
|
+
const result = tao_in * SCALE_FACTOR / alpha_in;
|
4787
4595
|
return result; // Scaled price as bigint
|
4788
4596
|
};
|
4789
4597
|
const calculateTaoAmountFromAlpha = ({
|
@@ -4848,13 +4656,24 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4848
4656
|
log.warn(`Chain ${chainId} for token ${tokenId} not found`);
|
4849
4657
|
continue;
|
4850
4658
|
}
|
4659
|
+
const [chainMeta] = findChainMeta(miniMetadatas, "substrate-native", chain);
|
4660
|
+
if (!chainMeta?.miniMetadata) {
|
4661
|
+
log.warn(`MiniMetadata for chain ${chainId} not found`);
|
4662
|
+
continue;
|
4663
|
+
}
|
4664
|
+
const scaleApi = getScaleApi({
|
4665
|
+
chainId,
|
4666
|
+
send: (...args) => chainConnector.send(chainId, ...args, {
|
4667
|
+
expectErrors: true
|
4668
|
+
} // don't pollute the wallet logs when this request fails
|
4669
|
+
)
|
4670
|
+
}, chainMeta.miniMetadata, token, chain.hasCheckMetadataHash, chain.signedExtensions, chain.registryTypes);
|
4851
4671
|
|
4852
4672
|
// sets the number of addresses to query in parallel (per chain, since each chain runs in parallel to the others)
|
4853
4673
|
const concurrency = 4;
|
4854
4674
|
// In-memory cache for successful dynamic info results
|
4855
4675
|
const dynamicInfoCache = new Map();
|
4856
4676
|
const fetchDynamicInfoForNetuids = async uniqueNetuids => {
|
4857
|
-
const DYNAMIC_INFO_METHOD = "SubnetInfoRuntimeApi_get_dynamic_info";
|
4858
4677
|
const MAX_RETRIES = 3;
|
4859
4678
|
const RETRY_DELAY_MS = 500;
|
4860
4679
|
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
@@ -4862,12 +4681,10 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4862
4681
|
if (netuid === 0) return null;
|
4863
4682
|
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
4864
4683
|
try {
|
4865
|
-
const
|
4866
|
-
|
4867
|
-
|
4868
|
-
|
4869
|
-
dynamicInfoCache.set(netuid, decodedResult); // Cache successful response
|
4870
|
-
return decodedResult;
|
4684
|
+
const params = [netuid];
|
4685
|
+
const result = await scaleApi.getRuntimeCallValue("SubnetInfoRuntimeApi", "get_dynamic_info", params);
|
4686
|
+
dynamicInfoCache.set(netuid, result); // Cache successful response
|
4687
|
+
return result;
|
4871
4688
|
} catch (error) {
|
4872
4689
|
log.trace(`Attempt ${attempt} failed for netuid ${netuid}:`, error);
|
4873
4690
|
if (attempt < MAX_RETRIES) {
|
@@ -4889,14 +4706,9 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4889
4706
|
// mergeMap lets us run N concurrent queries, where N is the value of `concurrency`
|
4890
4707
|
mergeMap(async address => {
|
4891
4708
|
const queryMethods = [async () => {
|
4892
|
-
if (
|
4893
|
-
const
|
4894
|
-
const
|
4895
|
-
const response = await chainConnector.send(chainId, "state_call", [method, params], undefined, {
|
4896
|
-
expectErrors: true
|
4897
|
-
} // don't pollute the wallet logs when this request fails
|
4898
|
-
);
|
4899
|
-
const result = DecodeResult_GetStakeInfoForColdkey(response);
|
4709
|
+
if (chain.isTestnet) return [];
|
4710
|
+
const params = [address];
|
4711
|
+
const result = await scaleApi.getRuntimeCallValue("StakeInfoRuntimeApi", "get_stake_info_for_coldkey", params);
|
4900
4712
|
if (!Array.isArray(result)) return [];
|
4901
4713
|
const uniqueNetuids = Array.from(new Set(result.map(item => Number(item.netuid)).filter(netuid => netuid !== SUBTENSOR_ROOT_NETUID)));
|
4902
4714
|
await fetchDynamicInfoForNetuids(uniqueNetuids);
|
@@ -4946,10 +4758,19 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4946
4758
|
dynamicInfo
|
4947
4759
|
}) => {
|
4948
4760
|
const {
|
4949
|
-
|
4950
|
-
|
4951
|
-
|
4761
|
+
token_symbol,
|
4762
|
+
subnet_name,
|
4763
|
+
subnet_identity
|
4952
4764
|
} = dynamicInfo ?? {};
|
4765
|
+
const tokenSymbol = new TextDecoder().decode(Uint8Array.from(token_symbol ?? []));
|
4766
|
+
const subnetName = new TextDecoder().decode(Uint8Array.from(subnet_name ?? []));
|
4767
|
+
|
4768
|
+
/** Map from Record<string, Binary> to Record<string, string> */
|
4769
|
+
const binaryToText = input => Object.entries(input).reduce((acc, [key, value]) => {
|
4770
|
+
acc[key] = value.asText();
|
4771
|
+
return acc;
|
4772
|
+
}, {});
|
4773
|
+
const subnetIdentity = subnet_identity ? binaryToText(subnet_identity) : undefined;
|
4953
4774
|
|
4954
4775
|
// Add 1n balance if failed to fetch dynamic info, so the position is not ignored by Balance lib and is displayed in the UI.
|
4955
4776
|
const alphaStakedInTao = dynamicInfo ? calculateTaoFromDynamicInfo({
|
@@ -4957,7 +4778,7 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4957
4778
|
alphaStaked: stake
|
4958
4779
|
}) : 1n;
|
4959
4780
|
const alphaToTaoRate = calculateTaoFromDynamicInfo({
|
4960
|
-
dynamicInfo,
|
4781
|
+
dynamicInfo: dynamicInfo ?? null,
|
4961
4782
|
alphaStaked: ONE_ALPHA_TOKEN
|
4962
4783
|
}).toString();
|
4963
4784
|
const stakeByNetuid = Number(netuid) === SUBTENSOR_ROOT_NETUID ? stake : alphaStakedInTao;
|
@@ -4986,7 +4807,7 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4986
4807
|
subnetName,
|
4987
4808
|
subnetIdentity: {
|
4988
4809
|
...subnetIdentity,
|
4989
|
-
subnetName: subnetIdentity?.
|
4810
|
+
subnetName: subnetIdentity?.subnet_name || subnetName
|
4990
4811
|
}
|
4991
4812
|
}
|
4992
4813
|
}
|
@@ -5673,6 +5494,7 @@ const SubNativeModule = hydrate => {
|
|
5673
5494
|
|
5674
5495
|
compactMetadata(metadata, [{
|
5675
5496
|
pallet: "System",
|
5497
|
+
constants: ["Version", "SS58Prefix"],
|
5676
5498
|
items: ["Account"]
|
5677
5499
|
}, {
|
5678
5500
|
pallet: "Balances",
|
@@ -5695,6 +5517,12 @@ const SubNativeModule = hydrate => {
|
|
5695
5517
|
{
|
5696
5518
|
pallet: "SubtensorModule",
|
5697
5519
|
items: ["TotalColdkeyStake", "StakingHotkeys", "Stake"]
|
5520
|
+
}], [{
|
5521
|
+
runtimeApi: "StakeInfoRuntimeApi",
|
5522
|
+
methods: ["get_stake_info_for_coldkey"]
|
5523
|
+
}, {
|
5524
|
+
runtimeApi: "SubnetInfoRuntimeApi",
|
5525
|
+
methods: ["get_dynamic_info"]
|
5698
5526
|
}]);
|
5699
5527
|
const miniMetadata = encodeMetadata(tag === "v15" ? {
|
5700
5528
|
tag,
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@talismn/balances",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.9.0",
|
4
4
|
"author": "Talisman",
|
5
5
|
"homepage": "https://talisman.xyz",
|
6
6
|
"license": "GPL-3.0-or-later",
|
@@ -22,7 +22,7 @@
|
|
22
22
|
"node": ">=18"
|
23
23
|
},
|
24
24
|
"dependencies": {
|
25
|
-
"@polkadot-api/utils": "
|
25
|
+
"@polkadot-api/utils": "0.1.2",
|
26
26
|
"@supercharge/promise-pool": "^3.2.0",
|
27
27
|
"anylogger": "^1.0.11",
|
28
28
|
"bignumber.js": "^9.1.2",
|
@@ -33,12 +33,13 @@
|
|
33
33
|
"rxjs": "^7.8.1",
|
34
34
|
"scale-ts": "^1.6.1",
|
35
35
|
"viem": "^2.21.34",
|
36
|
-
"@talismn/chain-connector": "0.
|
37
|
-
"@talismn/
|
38
|
-
"@talismn/
|
39
|
-
"@talismn/
|
40
|
-
"@talismn/
|
41
|
-
"@talismn/
|
36
|
+
"@talismn/chain-connector": "0.9.0",
|
37
|
+
"@talismn/chain-connector-evm": "0.9.0",
|
38
|
+
"@talismn/chaindata-provider": "0.9.0",
|
39
|
+
"@talismn/scale": "0.1.1",
|
40
|
+
"@talismn/sapi": "0.0.2",
|
41
|
+
"@talismn/token-rates": "2.0.0",
|
42
|
+
"@talismn/util": "0.3.2"
|
42
43
|
},
|
43
44
|
"devDependencies": {
|
44
45
|
"@polkadot/api-contract": "15.8.1",
|
@@ -53,8 +54,8 @@
|
|
53
54
|
"jest": "^29.7.0",
|
54
55
|
"ts-jest": "^29.2.5",
|
55
56
|
"typescript": "^5.6.3",
|
56
|
-
"@talismn/
|
57
|
-
"@talismn/
|
57
|
+
"@talismn/tsconfig": "0.0.2",
|
58
|
+
"@talismn/eslint-config": "0.0.3"
|
58
59
|
},
|
59
60
|
"peerDependencies": {
|
60
61
|
"@polkadot/api-contract": "*",
|