@talismn/balances 0.8.1 → 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
@@ -37,7 +37,7 @@ export type Hydrate = {
|
|
37
37
|
export type NewBalanceModule<TModuleType extends string, TTokenType extends SelectableTokenType, TChainMeta extends ExtendableChainMeta = DefaultChainMeta, TModuleConfig extends ExtendableModuleConfig = DefaultModuleConfig, TTransferParams extends ExtendableTransferParams = DefaultTransferParams> = (hydrate: Hydrate) => BalanceModule<TModuleType, TTokenType, TChainMeta, TModuleConfig, TTransferParams>;
|
38
38
|
export interface BalanceModule<TModuleType extends string, TTokenType extends SelectableTokenType, TChainMeta extends ExtendableChainMeta = DefaultChainMeta, TModuleConfig extends ExtendableModuleConfig = DefaultModuleConfig, TTransferParams extends ExtendableTransferParams = DefaultTransferParams> extends BalanceModuleSubstrate<TModuleType, TTokenType, TChainMeta, TModuleConfig, TTransferParams>, BalanceModuleEvm<TModuleType, TTokenType, TChainMeta, TModuleConfig, TTransferParams> {
|
39
39
|
}
|
40
|
-
export declare const DefaultBalanceModule: <TModuleType extends string, TTokenType extends SelectableTokenType, TChainMeta extends ExtendableChainMeta =
|
40
|
+
export declare const DefaultBalanceModule: <TModuleType extends string, TTokenType extends SelectableTokenType, TChainMeta extends ExtendableChainMeta = DefaultChainMeta, TModuleConfig extends ExtendableModuleConfig = DefaultModuleConfig, TTransferParams extends ExtendableTransferParams = DefaultTransferParams>(type: TModuleType) => BalanceModule<TModuleType, TTokenType, TChainMeta, TModuleConfig, TTransferParams>;
|
41
41
|
interface BalanceModuleSubstrate<TModuleType extends string, TTokenType extends SelectableTokenType, TChainMeta extends ExtendableChainMeta = DefaultChainMeta, TModuleConfig extends ExtendableModuleConfig = DefaultModuleConfig, TTransferParams extends ExtendableTransferParams = DefaultTransferParams> extends BalanceModuleCommon<TModuleType, TTokenType, TTransferParams> {
|
42
42
|
/** Pre-processes any substrate chain metadata required by this module ahead of time */
|
43
43
|
fetchSubstrateChainMeta(chainId: ChainId, moduleConfig?: TModuleConfig, metadataRpc?: `0x${string}`, systemProperties?: Record<string, any>): Promise<TChainMeta | null>;
|
@@ -1,56 +1,20 @@
|
|
1
|
+
import type { bittensor } from "@polkadot-api/descriptors";
|
2
|
+
export type GetStakeInfoForColdkeyParams = (typeof bittensor)["descriptors"]["apis"]["StakeInfoRuntimeApi"]["get_stake_info_for_coldkey"][0];
|
3
|
+
export type GetStakeInfoForColdkeyResult = (typeof bittensor)["descriptors"]["apis"]["StakeInfoRuntimeApi"]["get_stake_info_for_coldkey"][1];
|
4
|
+
export type GetDynamicInfoParams = (typeof bittensor)["descriptors"]["apis"]["SubnetInfoRuntimeApi"]["get_dynamic_info"][0];
|
5
|
+
export type GetDynamicInfoResult = (typeof bittensor)["descriptors"]["apis"]["SubnetInfoRuntimeApi"]["get_dynamic_info"][1];
|
1
6
|
export declare const SUBTENSOR_ROOT_NETUID = 0;
|
2
7
|
export declare const SUBTENSOR_MIN_STAKE_AMOUNT_PLANK = 1000000n;
|
3
8
|
export declare const SCALE_FACTOR: bigint;
|
4
9
|
export declare const ONE_ALPHA_TOKEN: bigint;
|
5
|
-
export declare const BITTENSOR_TESTNET_CHAIN_ID = "bittensor-testnet";
|
6
|
-
export declare const EncodeParams_GetStakeInfoForColdkey: (address: string) => string;
|
7
|
-
export declare const DecodeResult_GetStakeInfoForColdkey: (result: string) => {
|
8
|
-
hotkey: import("polkadot-api").SS58String;
|
9
|
-
coldkey: import("polkadot-api").SS58String;
|
10
|
-
netuid: number | bigint;
|
11
|
-
stake: number | bigint;
|
12
|
-
locked: number | bigint;
|
13
|
-
emission: number | bigint;
|
14
|
-
tao_emission: number | bigint;
|
15
|
-
drain: number | bigint;
|
16
|
-
isRegistered: boolean;
|
17
|
-
}[];
|
18
|
-
/** Encoding/decoding for GetStakeDynamicInfo */
|
19
|
-
export declare const EncodeParams_GetDynamicInfo: (netuid: number) => string;
|
20
|
-
export type DynamicInfoType = ReturnType<typeof DecodeResult_GetDynamicInfo>;
|
21
|
-
export declare const DecodeResult_GetDynamicInfo: (result: string) => {
|
22
|
-
netuid: number;
|
23
|
-
tokenSymbol: string;
|
24
|
-
subnetIdentity: Record<string, string>;
|
25
|
-
taoIn: bigint;
|
26
|
-
alphaIn: bigint;
|
27
|
-
subnetName: string;
|
28
|
-
ownerHotkey: import("polkadot-api").SS58String;
|
29
|
-
ownerColdkey: import("polkadot-api").SS58String;
|
30
|
-
tempo: number | bigint;
|
31
|
-
lastStep: number | bigint;
|
32
|
-
blocksSinceLastStep: number | bigint;
|
33
|
-
emission: number | bigint;
|
34
|
-
alphaOut: number | bigint;
|
35
|
-
alphaOutEmission: number | bigint;
|
36
|
-
alphaInEmission: number | bigint;
|
37
|
-
taoInEmission: number | bigint;
|
38
|
-
pendingAlphaEmission: number | bigint;
|
39
|
-
pendingRootEmission: number | bigint;
|
40
|
-
subnetVolume: number | bigint;
|
41
|
-
networkRegisteredAt: number | bigint;
|
42
|
-
movingPrice: {
|
43
|
-
bits: number | bigint;
|
44
|
-
};
|
45
|
-
};
|
46
10
|
export declare const calculateAlphaPrice: ({ dynamicInfo, }: {
|
47
|
-
dynamicInfo:
|
11
|
+
dynamicInfo: GetDynamicInfoResult | null | undefined;
|
48
12
|
}) => bigint;
|
49
13
|
export declare const calculateTaoAmountFromAlpha: ({ alphaPrice, alphaStaked, }: {
|
50
14
|
alphaPrice: bigint;
|
51
15
|
alphaStaked: bigint;
|
52
16
|
}) => bigint;
|
53
17
|
export declare const calculateTaoFromDynamicInfo: ({ dynamicInfo, alphaStaked, }: {
|
54
|
-
dynamicInfo:
|
18
|
+
dynamicInfo: GetDynamicInfoResult | null | undefined;
|
55
19
|
alphaStaked: bigint;
|
56
20
|
}) => bigint;
|
@@ -18,9 +18,11 @@ export declare const buildStorageCoders: <TBalanceModule extends AnyNewBalanceMo
|
|
18
18
|
moduleType: InferModuleType<TBalanceModule>;
|
19
19
|
coders: TCoders;
|
20
20
|
}) => Map<string, { [Property in keyof TCoders]: {
|
21
|
+
keys: {
|
22
|
+
enc: (...args: any[]) => string;
|
23
|
+
dec: (value: string) => any[];
|
24
|
+
};
|
25
|
+
value: import("@talismn/scale").Codec<any>;
|
21
26
|
len: number;
|
22
|
-
fallback:
|
23
|
-
enc: (...args: any[]) => string;
|
24
|
-
dec: import("scale-ts").Decoder<unknown>;
|
25
|
-
keyDecoder: (value: string) => any[];
|
27
|
+
fallback: any;
|
26
28
|
} | undefined; }>;
|
@@ -5,5 +5,5 @@ export declare const configureStore: (dbTable?: Table) => {
|
|
5
5
|
persistData: (balances: StoredBalanceJson[]) => Promise<void>;
|
6
6
|
retrieveData: () => Promise<StoredBalanceJson[]>;
|
7
7
|
};
|
8
|
-
export declare const compress: (balances: StoredBalanceJson[]) => Uint8Array
|
8
|
+
export declare const compress: (balances: StoredBalanceJson[]) => Uint8Array<ArrayBufferLike>;
|
9
9
|
export declare const decompress: (data: Uint8Array | ArrayBuffer) => StoredBalanceJson[];
|
@@ -96,11 +96,7 @@ export declare class Balances {
|
|
96
96
|
*/
|
97
97
|
remove: (ids: string[] | string) => Balances;
|
98
98
|
get each(): Balance[];
|
99
|
-
/**
|
100
|
-
* Get an array of balances in this collection, sorted by chain sortIndex.
|
101
|
-
*
|
102
|
-
* @returns A sorted array of the balances in this collection.
|
103
|
-
*/
|
99
|
+
/** @deprecated use each instead */
|
104
100
|
get sorted(): Balance[];
|
105
101
|
/**
|
106
102
|
* Get the number of balances in this collection.
|
@@ -22,6 +22,7 @@ var groupBy = require('lodash/groupBy');
|
|
22
22
|
var utils = require('@polkadot-api/utils');
|
23
23
|
var polkadotApi = require('polkadot-api');
|
24
24
|
var chainConnector = require('@talismn/chain-connector');
|
25
|
+
var sapi = require('@talismn/sapi');
|
25
26
|
var upperFirst = require('lodash/upperFirst');
|
26
27
|
var apiContract = require('@polkadot/api-contract');
|
27
28
|
|
@@ -108,88 +109,7 @@ class EvmTokenFetcher {
|
|
108
109
|
}
|
109
110
|
|
110
111
|
var packageJson = {
|
111
|
-
name: "@talismn/balances"
|
112
|
-
version: "0.8.1",
|
113
|
-
author: "Talisman",
|
114
|
-
homepage: "https://talisman.xyz",
|
115
|
-
license: "GPL-3.0-or-later",
|
116
|
-
publishConfig: {
|
117
|
-
access: "public"
|
118
|
-
},
|
119
|
-
repository: {
|
120
|
-
directory: "packages/balances",
|
121
|
-
type: "git",
|
122
|
-
url: "https://github.com/talismansociety/talisman.git"
|
123
|
-
},
|
124
|
-
main: "dist/talismn-balances.cjs.js",
|
125
|
-
module: "dist/talismn-balances.esm.js",
|
126
|
-
files: [
|
127
|
-
"/dist",
|
128
|
-
"/plugins"
|
129
|
-
],
|
130
|
-
engines: {
|
131
|
-
node: ">=18"
|
132
|
-
},
|
133
|
-
scripts: {
|
134
|
-
test: "jest",
|
135
|
-
lint: "eslint src --max-warnings 0",
|
136
|
-
clean: "rm -rf dist plugins/dist .turbo node_modules"
|
137
|
-
},
|
138
|
-
dependencies: {
|
139
|
-
"@polkadot-api/utils": "^0.1.2",
|
140
|
-
"@supercharge/promise-pool": "^3.2.0",
|
141
|
-
"@talismn/chain-connector": "workspace:*",
|
142
|
-
"@talismn/chain-connector-evm": "workspace:*",
|
143
|
-
"@talismn/chaindata-provider": "workspace:*",
|
144
|
-
"@talismn/scale": "workspace:*",
|
145
|
-
"@talismn/token-rates": "workspace:*",
|
146
|
-
"@talismn/util": "workspace:*",
|
147
|
-
anylogger: "^1.0.11",
|
148
|
-
"bignumber.js": "^9.1.2",
|
149
|
-
dexie: "^4.0.9",
|
150
|
-
lodash: "4.17.21",
|
151
|
-
pako: "^2.1.0",
|
152
|
-
"polkadot-api": "1.7.6",
|
153
|
-
rxjs: "^7.8.1",
|
154
|
-
"scale-ts": "^1.6.1",
|
155
|
-
viem: "^2.21.34"
|
156
|
-
},
|
157
|
-
devDependencies: {
|
158
|
-
"@polkadot/api-contract": "15.8.1",
|
159
|
-
"@polkadot/types": "15.8.1",
|
160
|
-
"@polkadot/util": "13.4.3",
|
161
|
-
"@polkadot/util-crypto": "13.4.3",
|
162
|
-
"@substrate/txwrapper-core": "7.5.3",
|
163
|
-
"@talismn/eslint-config": "workspace:*",
|
164
|
-
"@talismn/tsconfig": "workspace:*",
|
165
|
-
"@types/jest": "^29.5.14",
|
166
|
-
"@types/lodash": "^4.17.12",
|
167
|
-
"@types/pako": "^2.0.3",
|
168
|
-
eslint: "^8.57.1",
|
169
|
-
jest: "^29.7.0",
|
170
|
-
"ts-jest": "^29.2.5",
|
171
|
-
typescript: "^5.6.3"
|
172
|
-
},
|
173
|
-
peerDependencies: {
|
174
|
-
"@polkadot/api-contract": "*",
|
175
|
-
"@polkadot/types": "*",
|
176
|
-
"@polkadot/util": "*",
|
177
|
-
"@polkadot/util-crypto": "*",
|
178
|
-
"@substrate/txwrapper-core": "*"
|
179
|
-
},
|
180
|
-
preconstruct: {
|
181
|
-
entrypoints: [
|
182
|
-
"index.ts",
|
183
|
-
"plugins.ts"
|
184
|
-
]
|
185
|
-
},
|
186
|
-
eslintConfig: {
|
187
|
-
root: true,
|
188
|
-
"extends": [
|
189
|
-
"@talismn/eslint-config/base"
|
190
|
-
]
|
191
|
-
}
|
192
|
-
};
|
112
|
+
name: "@talismn/balances"};
|
193
113
|
|
194
114
|
var log = anylogger__default.default(packageJson.name);
|
195
115
|
|
@@ -375,13 +295,9 @@ class Balances {
|
|
375
295
|
return [...this];
|
376
296
|
}
|
377
297
|
|
378
|
-
/**
|
379
|
-
* Get an array of balances in this collection, sorted by chain sortIndex.
|
380
|
-
*
|
381
|
-
* @returns A sorted array of the balances in this collection.
|
382
|
-
*/
|
298
|
+
/** @deprecated use each instead */
|
383
299
|
get sorted() {
|
384
|
-
return
|
300
|
+
return this.each;
|
385
301
|
}
|
386
302
|
|
387
303
|
/**
|
@@ -413,7 +329,7 @@ const getBalanceId = balance => {
|
|
413
329
|
tokenId
|
414
330
|
} = balance;
|
415
331
|
const locationId = isBalanceEvm(balance) ? balance.evmNetworkId : balance.chainId;
|
416
|
-
return [source, address, locationId, tokenId].filter(
|
332
|
+
return [source, address, locationId, tokenId].filter(util.isTruthy).join("::");
|
417
333
|
};
|
418
334
|
|
419
335
|
/**
|
@@ -1055,7 +971,7 @@ const upgradeBalancesDataBlob = async tx => {
|
|
1055
971
|
...stuffToKeep
|
1056
972
|
} = balance;
|
1057
973
|
return stuffToKeep;
|
1058
|
-
}).filter(
|
974
|
+
}).filter(util.isTruthy);
|
1059
975
|
const output = pako__default.default.deflate(JSON.stringify(migratedData));
|
1060
976
|
// now write the compressed data back to the db and clear the old one
|
1061
977
|
await tx.table("balancesBlob").put({
|
@@ -1796,7 +1712,7 @@ const fetchBalances$3 = async (evmChainConnector, tokenAddressesByNetwork, erc20
|
|
1796
1712
|
const balances = await getEvmTokenBalances(publicClient, networkParams, result.errors, erc20Aggregators[evmNetworkId]);
|
1797
1713
|
|
1798
1714
|
// consider only non null balances in the results
|
1799
|
-
result.results.push(...balances.filter(
|
1715
|
+
result.results.push(...balances.filter(util.isTruthy).map((free, i) => ({
|
1800
1716
|
source: "evm-erc20",
|
1801
1717
|
status: "live",
|
1802
1718
|
address: networkParams[i].address,
|
@@ -3309,7 +3225,7 @@ const SubAssetsModule = hydrate => {
|
|
3309
3225
|
const assetStateKey = tryEncode(assetCoder, BigInt(assetId)) ?? tryEncode(assetCoder, assetId);
|
3310
3226
|
const metadataStateKey = tryEncode(metadataCoder, BigInt(assetId)) ?? tryEncode(metadataCoder, assetId);
|
3311
3227
|
if (assetStateKey === null || metadataStateKey === null) throw new Error(`Failed to encode stateKey for asset ${assetId} on chain ${chainId}`);
|
3312
|
-
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)]);
|
3228
|
+
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)]);
|
3313
3229
|
const existentialDeposit = assetsAsset?.min_balance?.toString?.() ?? "0";
|
3314
3230
|
const symbol = assetsMetadata?.symbol?.asText?.() ?? "Unit";
|
3315
3231
|
const decimals = assetsMetadata?.decimals ?? 0;
|
@@ -3476,15 +3392,9 @@ async function buildQueries$4(chaindataProvider, addressesByToken) {
|
|
3476
3392
|
|
3477
3393
|
const decoded = scale.decodeScale(scaleCoder, change, `Failed to decode substrate-assets balance on chain ${chainId}`) ?? {
|
3478
3394
|
balance: 0n,
|
3479
|
-
is_frozen: false,
|
3480
|
-
reason: {
|
3481
|
-
type: "Sufficient"
|
3482
|
-
},
|
3483
3395
|
status: {
|
3484
3396
|
type: "Liquid"
|
3485
|
-
}
|
3486
|
-
extra: undefined
|
3487
|
-
};
|
3397
|
+
}};
|
3488
3398
|
const isFrozen = decoded?.status?.type === "Frozen";
|
3489
3399
|
const amount = (decoded?.balance ?? 0n).toString();
|
3490
3400
|
|
@@ -3536,7 +3446,7 @@ async function buildQueries$4(chaindataProvider, addressesByToken) {
|
|
3536
3446
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
3537
3447
|
const tryEncode = (scaleCoder, ...args) => {
|
3538
3448
|
try {
|
3539
|
-
return scaleCoder?.enc?.(...args);
|
3449
|
+
return scaleCoder?.keys?.enc?.(...args);
|
3540
3450
|
} catch {
|
3541
3451
|
return null;
|
3542
3452
|
}
|
@@ -3607,11 +3517,11 @@ const SubEquilibriumModule = hydrate => {
|
|
3607
3517
|
try {
|
3608
3518
|
const scaleBuilder = scale.getDynamicBuilder(scale.getLookupFn(metadata));
|
3609
3519
|
const assetsCoder = scaleBuilder.buildStorage("EqAssets", "Assets");
|
3610
|
-
const stateKey = assetsCoder.enc();
|
3520
|
+
const stateKey = assetsCoder.keys.enc();
|
3611
3521
|
|
3612
3522
|
/** NOTE: Just a guideline, the RPC can return whatever it wants */
|
3613
3523
|
|
3614
|
-
const assetsResult = await chainConnector.send(chainId, "state_getStorage", [stateKey]).then(result => assetsCoder.dec(result) ?? null);
|
3524
|
+
const assetsResult = await chainConnector.send(chainId, "state_getStorage", [stateKey]).then(result => assetsCoder.value.dec(result) ?? null);
|
3615
3525
|
const tokens = (Array.isArray(assetsResult) ? assetsResult : []).flatMap(asset => {
|
3616
3526
|
if (!asset) return [];
|
3617
3527
|
if (!asset?.id) return [];
|
@@ -3896,9 +3806,9 @@ const SubForeignAssetsModule = hydrate => {
|
|
3896
3806
|
}
|
3897
3807
|
})();
|
3898
3808
|
if (onChainId === undefined) continue;
|
3899
|
-
const assetStateKey = assetCoder.enc(onChainId);
|
3900
|
-
const metadataStateKey = metadataCoder.enc(onChainId);
|
3901
|
-
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)]);
|
3809
|
+
const assetStateKey = assetCoder.keys.enc(onChainId);
|
3810
|
+
const metadataStateKey = metadataCoder.keys.enc(onChainId);
|
3811
|
+
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)]);
|
3902
3812
|
const existentialDeposit = assetsAsset?.min_balance?.toString?.() ?? "0";
|
3903
3813
|
const symbol = assetsMetadata?.symbol?.asText?.() ?? "Unit";
|
3904
3814
|
const decimals = assetsMetadata?.decimals ?? 0;
|
@@ -4058,15 +3968,9 @@ async function buildQueries$2(chaindataProvider, addressesByToken) {
|
|
4058
3968
|
|
4059
3969
|
const decoded = scale.decodeScale(scaleCoder, change, `Failed to decode substrate-foreignassets balance on chain ${chainId}`) ?? {
|
4060
3970
|
balance: 0n,
|
4061
|
-
is_frozen: false,
|
4062
|
-
reason: {
|
4063
|
-
type: "Sufficient"
|
4064
|
-
},
|
4065
3971
|
status: {
|
4066
3972
|
type: "Liquid"
|
4067
|
-
}
|
4068
|
-
extra: undefined
|
4069
|
-
};
|
3973
|
+
}};
|
4070
3974
|
const isFrozen = decoded?.status?.type === "Frozen";
|
4071
3975
|
const amount = (decoded?.balance ?? 0n).toString();
|
4072
3976
|
|
@@ -4129,7 +4033,7 @@ async function subscribeBase(queries, chainConnector, callback) {
|
|
4129
4033
|
* <TArgs, TResult>(...arguments: TArgs, callback: SubscriptionCallback<TResult>) => UnsubscribeFn
|
4130
4034
|
*/
|
4131
4035
|
const asObservable = handler => (...args) => new rxjs.Observable(subscriber => {
|
4132
|
-
const callback = (error, result) => error ? subscriber.error(error) : subscriber.next(result);
|
4036
|
+
const callback = (error, result) => error || result === undefined ? subscriber.error(error) : subscriber.next(result);
|
4133
4037
|
const unsubscribe = handler(...args, callback);
|
4134
4038
|
return unsubscribe;
|
4135
4039
|
});
|
@@ -4675,7 +4579,7 @@ async function subscribeNompoolStaking(chaindataProvider, chainConnector, addres
|
|
4675
4579
|
}
|
4676
4580
|
}]
|
4677
4581
|
};
|
4678
|
-
}).filter(
|
4582
|
+
}).filter(util.isNotNil);
|
4679
4583
|
if (balances.length > 0) callback(null, balances);
|
4680
4584
|
},
|
4681
4585
|
error: error => callback(error)
|
@@ -4690,113 +4594,17 @@ const SUBTENSOR_MIN_STAKE_AMOUNT_PLANK = 1000000n;
|
|
4690
4594
|
const TAO_DECIMALS = 9n;
|
4691
4595
|
const SCALE_FACTOR = 10n ** TAO_DECIMALS; // Equivalent to 10e9 for precision
|
4692
4596
|
const ONE_ALPHA_TOKEN = SCALE_FACTOR;
|
4693
|
-
const BITTENSOR_TESTNET_CHAIN_ID = "bittensor-testnet";
|
4694
|
-
const BittensorAccountPrefix = 42;
|
4695
|
-
const BittensorAccountId = polkadotApi.AccountId(BittensorAccountPrefix);
|
4696
|
-
|
4697
|
-
/** For encoding/decoding the GetStakeInfoForColdkey runtime api *after* they added the netuid parameter */
|
4698
|
-
const StakeInfo = scaleTs.Struct({
|
4699
|
-
hotkey: BittensorAccountId,
|
4700
|
-
coldkey: BittensorAccountId,
|
4701
|
-
netuid: scaleTs.compact,
|
4702
|
-
stake: scaleTs.compact,
|
4703
|
-
locked: scaleTs.compact,
|
4704
|
-
emission: scaleTs.compact,
|
4705
|
-
tao_emission: scaleTs.compact,
|
4706
|
-
drain: scaleTs.compact,
|
4707
|
-
isRegistered: scaleTs.bool
|
4708
|
-
});
|
4709
|
-
const EncodeParams_GetStakeInfoForColdkey = address => utils.toHex(BittensorAccountId.enc(address));
|
4710
|
-
const DecodeResult_GetStakeInfoForColdkey = result => scaleTs.Vector(StakeInfo).dec(result);
|
4711
|
-
/** Encoding/decoding for GetStakeDynamicInfo */
|
4712
|
-
const EncodeParams_GetDynamicInfo = netuid => {
|
4713
|
-
if (netuid < 0 || netuid > 65535) {
|
4714
|
-
throw new Error("netuid must be a valid u16 (0-65535)");
|
4715
|
-
}
|
4716
|
-
|
4717
|
-
// Convert the number to a Uint8Array (LE encoding)
|
4718
|
-
const encoded = new Uint8Array(2);
|
4719
|
-
encoded[0] = netuid & 0xff; // Lower byte
|
4720
|
-
encoded[1] = netuid >> 8 & 0xff; // Upper byte
|
4721
|
-
|
4722
|
-
// Convert to hex string
|
4723
|
-
return utils.toHex(encoded);
|
4724
|
-
};
|
4725
|
-
/** I96F32 representation (Fixed-Point) */
|
4726
|
-
const I96F32 = scaleTs.Struct({
|
4727
|
-
bits: scaleTs.compact
|
4728
|
-
});
|
4729
|
-
const SubnetIdentityV2 = scaleTs.Struct({
|
4730
|
-
subnetName: scaleTs.Bytes(),
|
4731
|
-
githubRepo: scaleTs.Bytes(),
|
4732
|
-
subnetContact: scaleTs.Bytes(),
|
4733
|
-
subnetUrl: scaleTs.Bytes(),
|
4734
|
-
discord: scaleTs.Bytes(),
|
4735
|
-
description: scaleTs.Bytes()
|
4736
|
-
});
|
4737
|
-
const DynamicInfo = scaleTs.Struct({
|
4738
|
-
netuid: scaleTs.compact,
|
4739
|
-
ownerHotkey: BittensorAccountId,
|
4740
|
-
ownerColdkey: BittensorAccountId,
|
4741
|
-
subnetName: scaleTs.Vector(scaleTs.compact),
|
4742
|
-
tokenSymbol: scaleTs.Vector(scaleTs.compact),
|
4743
|
-
tempo: scaleTs.compact,
|
4744
|
-
lastStep: scaleTs.compact,
|
4745
|
-
blocksSinceLastStep: scaleTs.compact,
|
4746
|
-
emission: scaleTs.compact,
|
4747
|
-
alphaIn: scaleTs.compact,
|
4748
|
-
alphaOut: scaleTs.compact,
|
4749
|
-
taoIn: scaleTs.compact,
|
4750
|
-
alphaOutEmission: scaleTs.compact,
|
4751
|
-
alphaInEmission: scaleTs.compact,
|
4752
|
-
taoInEmission: scaleTs.compact,
|
4753
|
-
pendingAlphaEmission: scaleTs.compact,
|
4754
|
-
pendingRootEmission: scaleTs.compact,
|
4755
|
-
subnetVolume: scaleTs.compact,
|
4756
|
-
networkRegisteredAt: scaleTs.compact,
|
4757
|
-
subnetIdentity: scaleTs.Option(SubnetIdentityV2),
|
4758
|
-
movingPrice: I96F32
|
4759
|
-
});
|
4760
|
-
const DecodeResult_GetDynamicInfo = result => {
|
4761
|
-
const LITTLE_ENDIAN_OFFSET = 256;
|
4762
|
-
const decoded = DynamicInfo.dec(result);
|
4763
|
-
const {
|
4764
|
-
netuid: netuidLittleEndian,
|
4765
|
-
subnetIdentity: subnetIdentityScaleOption = {},
|
4766
|
-
tokenSymbol: tokenSymbolU8Arr,
|
4767
|
-
taoIn,
|
4768
|
-
alphaIn,
|
4769
|
-
subnetName: subnetNameVector
|
4770
|
-
} = decoded;
|
4771
|
-
const netuid = Number(netuidLittleEndian) / LITTLE_ENDIAN_OFFSET;
|
4772
|
-
const tokenSymbol = new TextDecoder().decode(Uint8Array.from(tokenSymbolU8Arr.map(val => Number(val))));
|
4773
|
-
const subnetName = new TextDecoder().decode(Uint8Array.from(subnetNameVector.map(val => Number(val))));
|
4774
|
-
const subnetIdentity = Object.keys(subnetIdentityScaleOption).reduce((acc, key) => {
|
4775
|
-
const value = subnetIdentityScaleOption[key];
|
4776
|
-
acc[key] = new TextDecoder().decode(value);
|
4777
|
-
return acc;
|
4778
|
-
}, {});
|
4779
|
-
return {
|
4780
|
-
...decoded,
|
4781
|
-
netuid,
|
4782
|
-
tokenSymbol,
|
4783
|
-
subnetIdentity,
|
4784
|
-
taoIn: BigInt(taoIn),
|
4785
|
-
alphaIn: BigInt(alphaIn),
|
4786
|
-
subnetName
|
4787
|
-
};
|
4788
|
-
};
|
4789
4597
|
const calculateAlphaPrice = ({
|
4790
4598
|
dynamicInfo
|
4791
4599
|
}) => {
|
4792
4600
|
if (!dynamicInfo) return 0n;
|
4793
4601
|
const {
|
4794
|
-
|
4795
|
-
|
4602
|
+
alpha_in,
|
4603
|
+
tao_in
|
4796
4604
|
} = dynamicInfo;
|
4797
4605
|
|
4798
4606
|
// Scale taoIn before division to preserve precision
|
4799
|
-
const result =
|
4607
|
+
const result = tao_in * SCALE_FACTOR / alpha_in;
|
4800
4608
|
return result; // Scaled price as bigint
|
4801
4609
|
};
|
4802
4610
|
const calculateTaoAmountFromAlpha = ({
|
@@ -4861,13 +4669,24 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4861
4669
|
log.warn(`Chain ${chainId} for token ${tokenId} not found`);
|
4862
4670
|
continue;
|
4863
4671
|
}
|
4672
|
+
const [chainMeta] = findChainMeta(miniMetadatas, "substrate-native", chain);
|
4673
|
+
if (!chainMeta?.miniMetadata) {
|
4674
|
+
log.warn(`MiniMetadata for chain ${chainId} not found`);
|
4675
|
+
continue;
|
4676
|
+
}
|
4677
|
+
const scaleApi = sapi.getScaleApi({
|
4678
|
+
chainId,
|
4679
|
+
send: (...args) => chainConnector.send(chainId, ...args, {
|
4680
|
+
expectErrors: true
|
4681
|
+
} // don't pollute the wallet logs when this request fails
|
4682
|
+
)
|
4683
|
+
}, chainMeta.miniMetadata, token, chain.hasCheckMetadataHash, chain.signedExtensions, chain.registryTypes);
|
4864
4684
|
|
4865
4685
|
// sets the number of addresses to query in parallel (per chain, since each chain runs in parallel to the others)
|
4866
4686
|
const concurrency = 4;
|
4867
4687
|
// In-memory cache for successful dynamic info results
|
4868
4688
|
const dynamicInfoCache = new Map();
|
4869
4689
|
const fetchDynamicInfoForNetuids = async uniqueNetuids => {
|
4870
|
-
const DYNAMIC_INFO_METHOD = "SubnetInfoRuntimeApi_get_dynamic_info";
|
4871
4690
|
const MAX_RETRIES = 3;
|
4872
4691
|
const RETRY_DELAY_MS = 500;
|
4873
4692
|
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
@@ -4875,12 +4694,10 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4875
4694
|
if (netuid === 0) return null;
|
4876
4695
|
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
4877
4696
|
try {
|
4878
|
-
const
|
4879
|
-
|
4880
|
-
|
4881
|
-
|
4882
|
-
dynamicInfoCache.set(netuid, decodedResult); // Cache successful response
|
4883
|
-
return decodedResult;
|
4697
|
+
const params = [netuid];
|
4698
|
+
const result = await scaleApi.getRuntimeCallValue("SubnetInfoRuntimeApi", "get_dynamic_info", params);
|
4699
|
+
dynamicInfoCache.set(netuid, result); // Cache successful response
|
4700
|
+
return result;
|
4884
4701
|
} catch (error) {
|
4885
4702
|
log.trace(`Attempt ${attempt} failed for netuid ${netuid}:`, error);
|
4886
4703
|
if (attempt < MAX_RETRIES) {
|
@@ -4902,14 +4719,9 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4902
4719
|
// mergeMap lets us run N concurrent queries, where N is the value of `concurrency`
|
4903
4720
|
rxjs.mergeMap(async address => {
|
4904
4721
|
const queryMethods = [async () => {
|
4905
|
-
if (
|
4906
|
-
const
|
4907
|
-
const
|
4908
|
-
const response = await chainConnector.send(chainId, "state_call", [method, params], undefined, {
|
4909
|
-
expectErrors: true
|
4910
|
-
} // don't pollute the wallet logs when this request fails
|
4911
|
-
);
|
4912
|
-
const result = DecodeResult_GetStakeInfoForColdkey(response);
|
4722
|
+
if (chain.isTestnet) return [];
|
4723
|
+
const params = [address];
|
4724
|
+
const result = await scaleApi.getRuntimeCallValue("StakeInfoRuntimeApi", "get_stake_info_for_coldkey", params);
|
4913
4725
|
if (!Array.isArray(result)) return [];
|
4914
4726
|
const uniqueNetuids = Array.from(new Set(result.map(item => Number(item.netuid)).filter(netuid => netuid !== SUBTENSOR_ROOT_NETUID)));
|
4915
4727
|
await fetchDynamicInfoForNetuids(uniqueNetuids);
|
@@ -4959,10 +4771,19 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4959
4771
|
dynamicInfo
|
4960
4772
|
}) => {
|
4961
4773
|
const {
|
4962
|
-
|
4963
|
-
|
4964
|
-
|
4774
|
+
token_symbol,
|
4775
|
+
subnet_name,
|
4776
|
+
subnet_identity
|
4965
4777
|
} = dynamicInfo ?? {};
|
4778
|
+
const tokenSymbol = new TextDecoder().decode(Uint8Array.from(token_symbol ?? []));
|
4779
|
+
const subnetName = new TextDecoder().decode(Uint8Array.from(subnet_name ?? []));
|
4780
|
+
|
4781
|
+
/** Map from Record<string, Binary> to Record<string, string> */
|
4782
|
+
const binaryToText = input => Object.entries(input).reduce((acc, [key, value]) => {
|
4783
|
+
acc[key] = value.asText();
|
4784
|
+
return acc;
|
4785
|
+
}, {});
|
4786
|
+
const subnetIdentity = subnet_identity ? binaryToText(subnet_identity) : undefined;
|
4966
4787
|
|
4967
4788
|
// Add 1n balance if failed to fetch dynamic info, so the position is not ignored by Balance lib and is displayed in the UI.
|
4968
4789
|
const alphaStakedInTao = dynamicInfo ? calculateTaoFromDynamicInfo({
|
@@ -4970,7 +4791,7 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4970
4791
|
alphaStaked: stake
|
4971
4792
|
}) : 1n;
|
4972
4793
|
const alphaToTaoRate = calculateTaoFromDynamicInfo({
|
4973
|
-
dynamicInfo,
|
4794
|
+
dynamicInfo: dynamicInfo ?? null,
|
4974
4795
|
alphaStaked: ONE_ALPHA_TOKEN
|
4975
4796
|
}).toString();
|
4976
4797
|
const stakeByNetuid = Number(netuid) === SUBTENSOR_ROOT_NETUID ? stake : alphaStakedInTao;
|
@@ -4999,7 +4820,7 @@ async function subscribeSubtensorStaking(chaindataProvider, chainConnector, addr
|
|
4999
4820
|
subnetName,
|
5000
4821
|
subnetIdentity: {
|
5001
4822
|
...subnetIdentity,
|
5002
|
-
subnetName: subnetIdentity?.
|
4823
|
+
subnetName: subnetIdentity?.subnet_name || subnetName
|
5003
4824
|
}
|
5004
4825
|
}
|
5005
4826
|
}
|
@@ -5686,6 +5507,7 @@ const SubNativeModule = hydrate => {
|
|
5686
5507
|
|
5687
5508
|
scale.compactMetadata(metadata, [{
|
5688
5509
|
pallet: "System",
|
5510
|
+
constants: ["Version", "SS58Prefix"],
|
5689
5511
|
items: ["Account"]
|
5690
5512
|
}, {
|
5691
5513
|
pallet: "Balances",
|
@@ -5708,6 +5530,12 @@ const SubNativeModule = hydrate => {
|
|
5708
5530
|
{
|
5709
5531
|
pallet: "SubtensorModule",
|
5710
5532
|
items: ["TotalColdkeyStake", "StakingHotkeys", "Stake"]
|
5533
|
+
}], [{
|
5534
|
+
runtimeApi: "StakeInfoRuntimeApi",
|
5535
|
+
methods: ["get_stake_info_for_coldkey"]
|
5536
|
+
}, {
|
5537
|
+
runtimeApi: "SubnetInfoRuntimeApi",
|
5538
|
+
methods: ["get_dynamic_info"]
|
5711
5539
|
}]);
|
5712
5540
|
const miniMetadata = scale.encodeMetadata(tag === "v15" ? {
|
5713
5541
|
tag,
|