@talismn/balances 0.0.0-pr2277-20251211070508 → 0.0.0-pr2279-20251222112424
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/modules/substrate-dtao/calculatePendingRootClaimable.d.ts +11 -0
- package/dist/declarations/src/modules/substrate-dtao/types.d.ts +13 -0
- package/dist/talismn-balances.cjs.dev.js +183 -16
- package/dist/talismn-balances.cjs.prod.js +183 -16
- package/dist/talismn-balances.esm.js +183 -16
- package/package.json +11 -11
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { GetDynamicInfosResult, SubDTaoBalance } from "./types";
|
|
2
|
+
type DynamicInfo = NonNullable<GetDynamicInfosResult[number]>;
|
|
3
|
+
export declare const calculatePendingRootClaimable: ({ stake, hotkey, address, networkId, validatorRootClaimableRate, dynamicInfoByNetuid, }: {
|
|
4
|
+
stake: bigint;
|
|
5
|
+
hotkey: string;
|
|
6
|
+
address: string;
|
|
7
|
+
networkId: string;
|
|
8
|
+
validatorRootClaimableRate: Map<number, bigint>;
|
|
9
|
+
dynamicInfoByNetuid: Record<number, DynamicInfo | undefined>;
|
|
10
|
+
}) => SubDTaoBalance[];
|
|
11
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { bittensor } from "@polkadot-api/descriptors";
|
|
1
2
|
import z from "zod/v4";
|
|
2
3
|
export declare const SubDTaoTokenConfigSchema: z.ZodObject<{
|
|
3
4
|
symbol: z.ZodOptional<z.ZodString>;
|
|
@@ -15,3 +16,15 @@ export type SubDTaoTokenConfig = z.infer<typeof SubDTaoTokenConfigSchema>;
|
|
|
15
16
|
export type SubDTaoBalanceMeta = {
|
|
16
17
|
scaledAlphaPrice: string;
|
|
17
18
|
};
|
|
19
|
+
export type SubDTaoBalance = {
|
|
20
|
+
address: string;
|
|
21
|
+
tokenId: string;
|
|
22
|
+
baseTokenId: string;
|
|
23
|
+
stake: bigint;
|
|
24
|
+
pendingRootClaim?: bigint;
|
|
25
|
+
hotkey: string;
|
|
26
|
+
netuid: number;
|
|
27
|
+
scaledAlphaPrice: bigint;
|
|
28
|
+
};
|
|
29
|
+
export type GetDynamicInfosResult = (typeof bittensor)["descriptors"]["apis"]["SubnetInfoRuntimeApi"]["get_all_dynamic_info"][1];
|
|
30
|
+
export type GetStakeInfosResult = (typeof bittensor)["descriptors"]["apis"]["StakeInfoRuntimeApi"]["get_stake_info_for_coldkeys"][1];
|
|
@@ -2295,6 +2295,42 @@ const taoToAlpha = (tao, scaledAlphaPrice) => {
|
|
|
2295
2295
|
return tao * ALPHA_PRICE_SCALE / scaledAlphaPrice;
|
|
2296
2296
|
};
|
|
2297
2297
|
|
|
2298
|
+
const calculatePendingRootClaimable = ({
|
|
2299
|
+
stake,
|
|
2300
|
+
hotkey,
|
|
2301
|
+
address,
|
|
2302
|
+
networkId,
|
|
2303
|
+
validatorRootClaimableRate,
|
|
2304
|
+
dynamicInfoByNetuid
|
|
2305
|
+
}) => {
|
|
2306
|
+
const pendingRootClaimBalances = [];
|
|
2307
|
+
for (const [netuid, claimableRate] of validatorRootClaimableRate) {
|
|
2308
|
+
if (claimableRate === 0n) {
|
|
2309
|
+
continue;
|
|
2310
|
+
}
|
|
2311
|
+
const dynamicInfo = dynamicInfoByNetuid[netuid];
|
|
2312
|
+
const scaledAlphaPrice = dynamicInfo ? getScaledAlphaPrice(dynamicInfo.alpha_in, dynamicInfo.tao_in) : 0n;
|
|
2313
|
+
// Calculate claimable = claimable_rate * root_stake
|
|
2314
|
+
// Note: claimableRate is a I96F32, a fixed-point number format
|
|
2315
|
+
|
|
2316
|
+
// Multiply claimable_rate by root_stake
|
|
2317
|
+
// I96F32 multiplication: round((a * b) / 2^32)
|
|
2318
|
+
const pendingRootClaim = stake * claimableRate + (1n << 31n) >> 32n;
|
|
2319
|
+
pendingRootClaimBalances.push({
|
|
2320
|
+
address,
|
|
2321
|
+
tokenId: chaindataProvider.subDTaoTokenId(networkId, netuid, hotkey),
|
|
2322
|
+
baseTokenId: chaindataProvider.subDTaoTokenId(networkId, netuid),
|
|
2323
|
+
hotkey: hotkey,
|
|
2324
|
+
netuid: netuid,
|
|
2325
|
+
scaledAlphaPrice,
|
|
2326
|
+
pendingRootClaim,
|
|
2327
|
+
stake: 0n
|
|
2328
|
+
});
|
|
2329
|
+
}
|
|
2330
|
+
return pendingRootClaimBalances;
|
|
2331
|
+
};
|
|
2332
|
+
|
|
2333
|
+
const ROOT_NETUID = 0;
|
|
2298
2334
|
const fetchBalances$5 = async ({
|
|
2299
2335
|
networkId,
|
|
2300
2336
|
tokensWithAddresses,
|
|
@@ -2344,20 +2380,63 @@ const fetchBalances$5 = async ({
|
|
|
2344
2380
|
const addresses = lodashEs.uniq(balanceDefs.map(def => def.address));
|
|
2345
2381
|
try {
|
|
2346
2382
|
const [stakeInfos, dynamicInfos] = await Promise.all([fetchRuntimeCallResult(connector, networkId, miniMetadata.data, "StakeInfoRuntimeApi", "get_stake_info_for_coldkeys", [addresses]), fetchRuntimeCallResult(connector, networkId, miniMetadata.data, "SubnetInfoRuntimeApi", "get_all_dynamic_info", [])]);
|
|
2383
|
+
const rootHotkeys = lodashEs.uniq(stakeInfos.flatMap(([, stakes]) => stakes.filter(stake => stake.netuid === ROOT_NETUID).map(stake => stake.hotkey)));
|
|
2384
|
+
const rootClaimableRatesByHotkey = rootHotkeys.length && miniMetadata.data ? await fetchRootClaimableRates(connector, networkId, miniMetadata.data, rootHotkeys) : new Map();
|
|
2347
2385
|
const dynamicInfoByNetuid = lodashEs.keyBy(dynamicInfos.filter(util.isNotNil), info => info.netuid);
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2386
|
+
|
|
2387
|
+
// Upserts a balance into the accumulator, merging stake values if the balance already exists.
|
|
2388
|
+
// Eg: Acc X has root staked with validator Y, but also staked on sn 45 with the same validator Y.
|
|
2389
|
+
// We merge the pending root claim of sn 45 and the sn 45 stake in the same balance.
|
|
2390
|
+
const upsertBalance = (acc, address, tokenId, balance) => {
|
|
2391
|
+
const key = `${address}:${tokenId}`;
|
|
2392
|
+
const recordedBalance = acc[key];
|
|
2393
|
+
if (recordedBalance) {
|
|
2394
|
+
acc[key] = {
|
|
2395
|
+
...recordedBalance,
|
|
2396
|
+
stake: recordedBalance.stake + balance.stake,
|
|
2397
|
+
// If the new balance has pendingRootClaim, use it (it's calculated from current state)
|
|
2398
|
+
...(balance.pendingRootClaim !== undefined && {
|
|
2399
|
+
pendingRootClaim: balance.pendingRootClaim
|
|
2400
|
+
})
|
|
2401
|
+
};
|
|
2402
|
+
} else {
|
|
2403
|
+
acc[key] = balance;
|
|
2404
|
+
}
|
|
2405
|
+
};
|
|
2406
|
+
const balancesRaw = stakeInfos.reduce((acc, [address, stakes]) => {
|
|
2407
|
+
for (const stake of stakes) {
|
|
2408
|
+
// Regular stake cases
|
|
2409
|
+
const dynamicInfo = dynamicInfoByNetuid[stake.netuid];
|
|
2410
|
+
const scaledAlphaPrice = dynamicInfo ? getScaledAlphaPrice(dynamicInfo.alpha_in, dynamicInfo.tao_in) : 0n;
|
|
2411
|
+
const balance = {
|
|
2412
|
+
address,
|
|
2413
|
+
tokenId: chaindataProvider.subDTaoTokenId(networkId, stake.netuid, stake.hotkey),
|
|
2414
|
+
baseTokenId: chaindataProvider.subDTaoTokenId(networkId, stake.netuid),
|
|
2415
|
+
stake: stake.stake,
|
|
2416
|
+
hotkey: stake.hotkey,
|
|
2417
|
+
netuid: stake.netuid,
|
|
2418
|
+
scaledAlphaPrice
|
|
2419
|
+
};
|
|
2420
|
+
upsertBalance(acc, address, balance.tokenId, balance);
|
|
2421
|
+
|
|
2422
|
+
// Root stake cases, we need to calculate the pending root claim and add to the balances
|
|
2423
|
+
if (stake.netuid === ROOT_NETUID) {
|
|
2424
|
+
const pendingRootClaimBalances = calculatePendingRootClaimable({
|
|
2425
|
+
stake: stake.stake,
|
|
2426
|
+
hotkey: stake.hotkey,
|
|
2427
|
+
address,
|
|
2428
|
+
networkId,
|
|
2429
|
+
validatorRootClaimableRate: rootClaimableRatesByHotkey.get(stake.hotkey) ?? new Map(),
|
|
2430
|
+
dynamicInfoByNetuid
|
|
2431
|
+
});
|
|
2432
|
+
pendingRootClaimBalances.forEach(balance => {
|
|
2433
|
+
upsertBalance(acc, address, balance.tokenId, balance);
|
|
2434
|
+
});
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
return acc;
|
|
2438
|
+
}, {});
|
|
2439
|
+
const balances = Object.values(balancesRaw);
|
|
2361
2440
|
const tokensById = lodashEs.keyBy(tokensWithAddresses.map(([token]) => token), t => t.id);
|
|
2362
2441
|
const dynamicTokens = [];
|
|
2363
2442
|
|
|
@@ -2383,19 +2462,45 @@ const fetchBalances$5 = async ({
|
|
|
2383
2462
|
const meta = {
|
|
2384
2463
|
scaledAlphaPrice: stake?.scaledAlphaPrice.toString() ?? "0"
|
|
2385
2464
|
};
|
|
2465
|
+
const stakeAmount = BigInt(stake?.stake?.toString() ?? "0");
|
|
2466
|
+
const pendingRootClaimAmount = BigInt(stake?.pendingRootClaim?.toString() ?? "0");
|
|
2467
|
+
const hasZeroStake = stakeAmount === 0n;
|
|
2468
|
+
const hasPendingRootClaim = pendingRootClaimAmount > 0n;
|
|
2386
2469
|
const balanceValue = {
|
|
2387
2470
|
type: "free",
|
|
2388
2471
|
label: stake?.netuid === 0 ? "Root Staking" : `Subnet Staking`,
|
|
2389
|
-
amount:
|
|
2472
|
+
amount: stakeAmount.toString(),
|
|
2390
2473
|
meta
|
|
2391
2474
|
};
|
|
2475
|
+
const pendingRootClaimValue = {
|
|
2476
|
+
type: "locked",
|
|
2477
|
+
label: "Pending root claim",
|
|
2478
|
+
amount: pendingRootClaimAmount.toString(),
|
|
2479
|
+
meta
|
|
2480
|
+
};
|
|
2481
|
+
const values = [balanceValue, pendingRootClaimValue];
|
|
2482
|
+
|
|
2483
|
+
// If stake is 0n but there's a pendingRootClaim, add it as an extra amount
|
|
2484
|
+
// with includeInTotal: true so it counts toward the total balance.
|
|
2485
|
+
// This ensures the balance isn't filtered out when stake is 0n.
|
|
2486
|
+
// The total.planck calculation is: free + reserved + extra (with includeInTotal: true)
|
|
2487
|
+
// So by adding pendingRootClaim as extra, it will be included in total.planck.
|
|
2488
|
+
if (hasZeroStake && hasPendingRootClaim) {
|
|
2489
|
+
values.push({
|
|
2490
|
+
type: "extra",
|
|
2491
|
+
label: "Pending root claim",
|
|
2492
|
+
amount: pendingRootClaimAmount.toString(),
|
|
2493
|
+
includeInTotal: true,
|
|
2494
|
+
meta
|
|
2495
|
+
});
|
|
2496
|
+
}
|
|
2392
2497
|
return {
|
|
2393
2498
|
address: def.address,
|
|
2394
2499
|
networkId,
|
|
2395
2500
|
tokenId: def.token.id,
|
|
2396
2501
|
source: MODULE_TYPE$5,
|
|
2397
2502
|
status: "live",
|
|
2398
|
-
values
|
|
2503
|
+
values
|
|
2399
2504
|
};
|
|
2400
2505
|
});
|
|
2401
2506
|
return {
|
|
@@ -2418,6 +2523,68 @@ const fetchBalances$5 = async ({
|
|
|
2418
2523
|
};
|
|
2419
2524
|
}
|
|
2420
2525
|
};
|
|
2526
|
+
const buildStorageCoder = (metadataRpc, pallet, entry) => {
|
|
2527
|
+
const {
|
|
2528
|
+
builder
|
|
2529
|
+
} = scale.parseMetadataRpc(metadataRpc);
|
|
2530
|
+
return builder.buildStorage(pallet, entry);
|
|
2531
|
+
};
|
|
2532
|
+
const buildRootClaimableStorageCoder = async (connector, networkId, metadataRpc) => {
|
|
2533
|
+
let storageCoder = null;
|
|
2534
|
+
if (metadataRpc) {
|
|
2535
|
+
try {
|
|
2536
|
+
storageCoder = buildStorageCoder(metadataRpc, "SubtensorModule", "RootClaimable");
|
|
2537
|
+
} catch (cause) {
|
|
2538
|
+
log.warn(`Failed to build storage coder for SubtensorModule.RootClaimable using provided metadata on ${networkId}`, {
|
|
2539
|
+
cause
|
|
2540
|
+
});
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
return storageCoder;
|
|
2544
|
+
};
|
|
2545
|
+
const buildRootClaimableQueries = (networkId, hotkeys, storageCoder) => {
|
|
2546
|
+
return hotkeys.map(hotkey => {
|
|
2547
|
+
let stateKey = null;
|
|
2548
|
+
try {
|
|
2549
|
+
stateKey = storageCoder.keys.enc(hotkey);
|
|
2550
|
+
} catch (cause) {
|
|
2551
|
+
log.warn(`Failed to encode storage key for hotkey ${hotkey} on ${networkId}`, {
|
|
2552
|
+
cause
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2555
|
+
const decodeResult = changes => {
|
|
2556
|
+
const hexValue = changes[0];
|
|
2557
|
+
if (!hexValue) {
|
|
2558
|
+
return [hotkey, new Map()];
|
|
2559
|
+
}
|
|
2560
|
+
const decoded = scale.decodeScale(storageCoder, hexValue, `Failed to decode RootClaimable for hotkey ${hotkey} on ${networkId}`);
|
|
2561
|
+
return [hotkey, decoded ? new Map(decoded) : new Map()];
|
|
2562
|
+
};
|
|
2563
|
+
return {
|
|
2564
|
+
stateKeys: [stateKey],
|
|
2565
|
+
decodeResult
|
|
2566
|
+
};
|
|
2567
|
+
});
|
|
2568
|
+
};
|
|
2569
|
+
const fetchRootClaimableRates = async (connector, networkId, metadataRpc, hotkeys) => {
|
|
2570
|
+
if (!hotkeys.length) return new Map();
|
|
2571
|
+
const storageCoder = await buildRootClaimableStorageCoder(connector, networkId, metadataRpc);
|
|
2572
|
+
if (!storageCoder) {
|
|
2573
|
+
// Fallback: return empty map for all hotkeys
|
|
2574
|
+
return new Map(hotkeys.map(hotkey => [hotkey, new Map()]));
|
|
2575
|
+
}
|
|
2576
|
+
const queries = buildRootClaimableQueries(networkId, hotkeys, storageCoder);
|
|
2577
|
+
try {
|
|
2578
|
+
const results = await fetchRpcQueryPack(connector, networkId, queries);
|
|
2579
|
+
return new Map(results);
|
|
2580
|
+
} catch (cause) {
|
|
2581
|
+
log.warn(`Failed to fetch RootClaimable for hotkeys on ${networkId}`, {
|
|
2582
|
+
cause
|
|
2583
|
+
});
|
|
2584
|
+
// Fallback: return empty map for all hotkeys
|
|
2585
|
+
return new Map(hotkeys.map(hotkey => [hotkey, new Map()]));
|
|
2586
|
+
}
|
|
2587
|
+
};
|
|
2421
2588
|
|
|
2422
2589
|
// hardcoded because we dont have access to native tokens from the balance module
|
|
2423
2590
|
const NATIVE_TOKEN_SYMBOLS = {
|
|
@@ -2517,7 +2684,7 @@ const getData$4 = metadataRpc => {
|
|
|
2517
2684
|
if (!isBittensor) return null;
|
|
2518
2685
|
scale.compactMetadata(metadata, [{
|
|
2519
2686
|
pallet: "SubtensorModule",
|
|
2520
|
-
items: ["TransferToggle"]
|
|
2687
|
+
items: ["TransferToggle", "RootClaimable"]
|
|
2521
2688
|
}], [{
|
|
2522
2689
|
runtimeApi: "StakeInfoRuntimeApi",
|
|
2523
2690
|
methods: ["get_stake_info_for_coldkeys"]
|
|
@@ -2295,6 +2295,42 @@ const taoToAlpha = (tao, scaledAlphaPrice) => {
|
|
|
2295
2295
|
return tao * ALPHA_PRICE_SCALE / scaledAlphaPrice;
|
|
2296
2296
|
};
|
|
2297
2297
|
|
|
2298
|
+
const calculatePendingRootClaimable = ({
|
|
2299
|
+
stake,
|
|
2300
|
+
hotkey,
|
|
2301
|
+
address,
|
|
2302
|
+
networkId,
|
|
2303
|
+
validatorRootClaimableRate,
|
|
2304
|
+
dynamicInfoByNetuid
|
|
2305
|
+
}) => {
|
|
2306
|
+
const pendingRootClaimBalances = [];
|
|
2307
|
+
for (const [netuid, claimableRate] of validatorRootClaimableRate) {
|
|
2308
|
+
if (claimableRate === 0n) {
|
|
2309
|
+
continue;
|
|
2310
|
+
}
|
|
2311
|
+
const dynamicInfo = dynamicInfoByNetuid[netuid];
|
|
2312
|
+
const scaledAlphaPrice = dynamicInfo ? getScaledAlphaPrice(dynamicInfo.alpha_in, dynamicInfo.tao_in) : 0n;
|
|
2313
|
+
// Calculate claimable = claimable_rate * root_stake
|
|
2314
|
+
// Note: claimableRate is a I96F32, a fixed-point number format
|
|
2315
|
+
|
|
2316
|
+
// Multiply claimable_rate by root_stake
|
|
2317
|
+
// I96F32 multiplication: round((a * b) / 2^32)
|
|
2318
|
+
const pendingRootClaim = stake * claimableRate + (1n << 31n) >> 32n;
|
|
2319
|
+
pendingRootClaimBalances.push({
|
|
2320
|
+
address,
|
|
2321
|
+
tokenId: chaindataProvider.subDTaoTokenId(networkId, netuid, hotkey),
|
|
2322
|
+
baseTokenId: chaindataProvider.subDTaoTokenId(networkId, netuid),
|
|
2323
|
+
hotkey: hotkey,
|
|
2324
|
+
netuid: netuid,
|
|
2325
|
+
scaledAlphaPrice,
|
|
2326
|
+
pendingRootClaim,
|
|
2327
|
+
stake: 0n
|
|
2328
|
+
});
|
|
2329
|
+
}
|
|
2330
|
+
return pendingRootClaimBalances;
|
|
2331
|
+
};
|
|
2332
|
+
|
|
2333
|
+
const ROOT_NETUID = 0;
|
|
2298
2334
|
const fetchBalances$5 = async ({
|
|
2299
2335
|
networkId,
|
|
2300
2336
|
tokensWithAddresses,
|
|
@@ -2344,20 +2380,63 @@ const fetchBalances$5 = async ({
|
|
|
2344
2380
|
const addresses = lodashEs.uniq(balanceDefs.map(def => def.address));
|
|
2345
2381
|
try {
|
|
2346
2382
|
const [stakeInfos, dynamicInfos] = await Promise.all([fetchRuntimeCallResult(connector, networkId, miniMetadata.data, "StakeInfoRuntimeApi", "get_stake_info_for_coldkeys", [addresses]), fetchRuntimeCallResult(connector, networkId, miniMetadata.data, "SubnetInfoRuntimeApi", "get_all_dynamic_info", [])]);
|
|
2383
|
+
const rootHotkeys = lodashEs.uniq(stakeInfos.flatMap(([, stakes]) => stakes.filter(stake => stake.netuid === ROOT_NETUID).map(stake => stake.hotkey)));
|
|
2384
|
+
const rootClaimableRatesByHotkey = rootHotkeys.length && miniMetadata.data ? await fetchRootClaimableRates(connector, networkId, miniMetadata.data, rootHotkeys) : new Map();
|
|
2347
2385
|
const dynamicInfoByNetuid = lodashEs.keyBy(dynamicInfos.filter(util.isNotNil), info => info.netuid);
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2386
|
+
|
|
2387
|
+
// Upserts a balance into the accumulator, merging stake values if the balance already exists.
|
|
2388
|
+
// Eg: Acc X has root staked with validator Y, but also staked on sn 45 with the same validator Y.
|
|
2389
|
+
// We merge the pending root claim of sn 45 and the sn 45 stake in the same balance.
|
|
2390
|
+
const upsertBalance = (acc, address, tokenId, balance) => {
|
|
2391
|
+
const key = `${address}:${tokenId}`;
|
|
2392
|
+
const recordedBalance = acc[key];
|
|
2393
|
+
if (recordedBalance) {
|
|
2394
|
+
acc[key] = {
|
|
2395
|
+
...recordedBalance,
|
|
2396
|
+
stake: recordedBalance.stake + balance.stake,
|
|
2397
|
+
// If the new balance has pendingRootClaim, use it (it's calculated from current state)
|
|
2398
|
+
...(balance.pendingRootClaim !== undefined && {
|
|
2399
|
+
pendingRootClaim: balance.pendingRootClaim
|
|
2400
|
+
})
|
|
2401
|
+
};
|
|
2402
|
+
} else {
|
|
2403
|
+
acc[key] = balance;
|
|
2404
|
+
}
|
|
2405
|
+
};
|
|
2406
|
+
const balancesRaw = stakeInfos.reduce((acc, [address, stakes]) => {
|
|
2407
|
+
for (const stake of stakes) {
|
|
2408
|
+
// Regular stake cases
|
|
2409
|
+
const dynamicInfo = dynamicInfoByNetuid[stake.netuid];
|
|
2410
|
+
const scaledAlphaPrice = dynamicInfo ? getScaledAlphaPrice(dynamicInfo.alpha_in, dynamicInfo.tao_in) : 0n;
|
|
2411
|
+
const balance = {
|
|
2412
|
+
address,
|
|
2413
|
+
tokenId: chaindataProvider.subDTaoTokenId(networkId, stake.netuid, stake.hotkey),
|
|
2414
|
+
baseTokenId: chaindataProvider.subDTaoTokenId(networkId, stake.netuid),
|
|
2415
|
+
stake: stake.stake,
|
|
2416
|
+
hotkey: stake.hotkey,
|
|
2417
|
+
netuid: stake.netuid,
|
|
2418
|
+
scaledAlphaPrice
|
|
2419
|
+
};
|
|
2420
|
+
upsertBalance(acc, address, balance.tokenId, balance);
|
|
2421
|
+
|
|
2422
|
+
// Root stake cases, we need to calculate the pending root claim and add to the balances
|
|
2423
|
+
if (stake.netuid === ROOT_NETUID) {
|
|
2424
|
+
const pendingRootClaimBalances = calculatePendingRootClaimable({
|
|
2425
|
+
stake: stake.stake,
|
|
2426
|
+
hotkey: stake.hotkey,
|
|
2427
|
+
address,
|
|
2428
|
+
networkId,
|
|
2429
|
+
validatorRootClaimableRate: rootClaimableRatesByHotkey.get(stake.hotkey) ?? new Map(),
|
|
2430
|
+
dynamicInfoByNetuid
|
|
2431
|
+
});
|
|
2432
|
+
pendingRootClaimBalances.forEach(balance => {
|
|
2433
|
+
upsertBalance(acc, address, balance.tokenId, balance);
|
|
2434
|
+
});
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
return acc;
|
|
2438
|
+
}, {});
|
|
2439
|
+
const balances = Object.values(balancesRaw);
|
|
2361
2440
|
const tokensById = lodashEs.keyBy(tokensWithAddresses.map(([token]) => token), t => t.id);
|
|
2362
2441
|
const dynamicTokens = [];
|
|
2363
2442
|
|
|
@@ -2383,19 +2462,45 @@ const fetchBalances$5 = async ({
|
|
|
2383
2462
|
const meta = {
|
|
2384
2463
|
scaledAlphaPrice: stake?.scaledAlphaPrice.toString() ?? "0"
|
|
2385
2464
|
};
|
|
2465
|
+
const stakeAmount = BigInt(stake?.stake?.toString() ?? "0");
|
|
2466
|
+
const pendingRootClaimAmount = BigInt(stake?.pendingRootClaim?.toString() ?? "0");
|
|
2467
|
+
const hasZeroStake = stakeAmount === 0n;
|
|
2468
|
+
const hasPendingRootClaim = pendingRootClaimAmount > 0n;
|
|
2386
2469
|
const balanceValue = {
|
|
2387
2470
|
type: "free",
|
|
2388
2471
|
label: stake?.netuid === 0 ? "Root Staking" : `Subnet Staking`,
|
|
2389
|
-
amount:
|
|
2472
|
+
amount: stakeAmount.toString(),
|
|
2390
2473
|
meta
|
|
2391
2474
|
};
|
|
2475
|
+
const pendingRootClaimValue = {
|
|
2476
|
+
type: "locked",
|
|
2477
|
+
label: "Pending root claim",
|
|
2478
|
+
amount: pendingRootClaimAmount.toString(),
|
|
2479
|
+
meta
|
|
2480
|
+
};
|
|
2481
|
+
const values = [balanceValue, pendingRootClaimValue];
|
|
2482
|
+
|
|
2483
|
+
// If stake is 0n but there's a pendingRootClaim, add it as an extra amount
|
|
2484
|
+
// with includeInTotal: true so it counts toward the total balance.
|
|
2485
|
+
// This ensures the balance isn't filtered out when stake is 0n.
|
|
2486
|
+
// The total.planck calculation is: free + reserved + extra (with includeInTotal: true)
|
|
2487
|
+
// So by adding pendingRootClaim as extra, it will be included in total.planck.
|
|
2488
|
+
if (hasZeroStake && hasPendingRootClaim) {
|
|
2489
|
+
values.push({
|
|
2490
|
+
type: "extra",
|
|
2491
|
+
label: "Pending root claim",
|
|
2492
|
+
amount: pendingRootClaimAmount.toString(),
|
|
2493
|
+
includeInTotal: true,
|
|
2494
|
+
meta
|
|
2495
|
+
});
|
|
2496
|
+
}
|
|
2392
2497
|
return {
|
|
2393
2498
|
address: def.address,
|
|
2394
2499
|
networkId,
|
|
2395
2500
|
tokenId: def.token.id,
|
|
2396
2501
|
source: MODULE_TYPE$5,
|
|
2397
2502
|
status: "live",
|
|
2398
|
-
values
|
|
2503
|
+
values
|
|
2399
2504
|
};
|
|
2400
2505
|
});
|
|
2401
2506
|
return {
|
|
@@ -2418,6 +2523,68 @@ const fetchBalances$5 = async ({
|
|
|
2418
2523
|
};
|
|
2419
2524
|
}
|
|
2420
2525
|
};
|
|
2526
|
+
const buildStorageCoder = (metadataRpc, pallet, entry) => {
|
|
2527
|
+
const {
|
|
2528
|
+
builder
|
|
2529
|
+
} = scale.parseMetadataRpc(metadataRpc);
|
|
2530
|
+
return builder.buildStorage(pallet, entry);
|
|
2531
|
+
};
|
|
2532
|
+
const buildRootClaimableStorageCoder = async (connector, networkId, metadataRpc) => {
|
|
2533
|
+
let storageCoder = null;
|
|
2534
|
+
if (metadataRpc) {
|
|
2535
|
+
try {
|
|
2536
|
+
storageCoder = buildStorageCoder(metadataRpc, "SubtensorModule", "RootClaimable");
|
|
2537
|
+
} catch (cause) {
|
|
2538
|
+
log.warn(`Failed to build storage coder for SubtensorModule.RootClaimable using provided metadata on ${networkId}`, {
|
|
2539
|
+
cause
|
|
2540
|
+
});
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
return storageCoder;
|
|
2544
|
+
};
|
|
2545
|
+
const buildRootClaimableQueries = (networkId, hotkeys, storageCoder) => {
|
|
2546
|
+
return hotkeys.map(hotkey => {
|
|
2547
|
+
let stateKey = null;
|
|
2548
|
+
try {
|
|
2549
|
+
stateKey = storageCoder.keys.enc(hotkey);
|
|
2550
|
+
} catch (cause) {
|
|
2551
|
+
log.warn(`Failed to encode storage key for hotkey ${hotkey} on ${networkId}`, {
|
|
2552
|
+
cause
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2555
|
+
const decodeResult = changes => {
|
|
2556
|
+
const hexValue = changes[0];
|
|
2557
|
+
if (!hexValue) {
|
|
2558
|
+
return [hotkey, new Map()];
|
|
2559
|
+
}
|
|
2560
|
+
const decoded = scale.decodeScale(storageCoder, hexValue, `Failed to decode RootClaimable for hotkey ${hotkey} on ${networkId}`);
|
|
2561
|
+
return [hotkey, decoded ? new Map(decoded) : new Map()];
|
|
2562
|
+
};
|
|
2563
|
+
return {
|
|
2564
|
+
stateKeys: [stateKey],
|
|
2565
|
+
decodeResult
|
|
2566
|
+
};
|
|
2567
|
+
});
|
|
2568
|
+
};
|
|
2569
|
+
const fetchRootClaimableRates = async (connector, networkId, metadataRpc, hotkeys) => {
|
|
2570
|
+
if (!hotkeys.length) return new Map();
|
|
2571
|
+
const storageCoder = await buildRootClaimableStorageCoder(connector, networkId, metadataRpc);
|
|
2572
|
+
if (!storageCoder) {
|
|
2573
|
+
// Fallback: return empty map for all hotkeys
|
|
2574
|
+
return new Map(hotkeys.map(hotkey => [hotkey, new Map()]));
|
|
2575
|
+
}
|
|
2576
|
+
const queries = buildRootClaimableQueries(networkId, hotkeys, storageCoder);
|
|
2577
|
+
try {
|
|
2578
|
+
const results = await fetchRpcQueryPack(connector, networkId, queries);
|
|
2579
|
+
return new Map(results);
|
|
2580
|
+
} catch (cause) {
|
|
2581
|
+
log.warn(`Failed to fetch RootClaimable for hotkeys on ${networkId}`, {
|
|
2582
|
+
cause
|
|
2583
|
+
});
|
|
2584
|
+
// Fallback: return empty map for all hotkeys
|
|
2585
|
+
return new Map(hotkeys.map(hotkey => [hotkey, new Map()]));
|
|
2586
|
+
}
|
|
2587
|
+
};
|
|
2421
2588
|
|
|
2422
2589
|
// hardcoded because we dont have access to native tokens from the balance module
|
|
2423
2590
|
const NATIVE_TOKEN_SYMBOLS = {
|
|
@@ -2517,7 +2684,7 @@ const getData$4 = metadataRpc => {
|
|
|
2517
2684
|
if (!isBittensor) return null;
|
|
2518
2685
|
scale.compactMetadata(metadata, [{
|
|
2519
2686
|
pallet: "SubtensorModule",
|
|
2520
|
-
items: ["TransferToggle"]
|
|
2687
|
+
items: ["TransferToggle", "RootClaimable"]
|
|
2521
2688
|
}], [{
|
|
2522
2689
|
runtimeApi: "StakeInfoRuntimeApi",
|
|
2523
2690
|
methods: ["get_stake_info_for_coldkeys"]
|
|
@@ -2286,6 +2286,42 @@ const taoToAlpha = (tao, scaledAlphaPrice) => {
|
|
|
2286
2286
|
return tao * ALPHA_PRICE_SCALE / scaledAlphaPrice;
|
|
2287
2287
|
};
|
|
2288
2288
|
|
|
2289
|
+
const calculatePendingRootClaimable = ({
|
|
2290
|
+
stake,
|
|
2291
|
+
hotkey,
|
|
2292
|
+
address,
|
|
2293
|
+
networkId,
|
|
2294
|
+
validatorRootClaimableRate,
|
|
2295
|
+
dynamicInfoByNetuid
|
|
2296
|
+
}) => {
|
|
2297
|
+
const pendingRootClaimBalances = [];
|
|
2298
|
+
for (const [netuid, claimableRate] of validatorRootClaimableRate) {
|
|
2299
|
+
if (claimableRate === 0n) {
|
|
2300
|
+
continue;
|
|
2301
|
+
}
|
|
2302
|
+
const dynamicInfo = dynamicInfoByNetuid[netuid];
|
|
2303
|
+
const scaledAlphaPrice = dynamicInfo ? getScaledAlphaPrice(dynamicInfo.alpha_in, dynamicInfo.tao_in) : 0n;
|
|
2304
|
+
// Calculate claimable = claimable_rate * root_stake
|
|
2305
|
+
// Note: claimableRate is a I96F32, a fixed-point number format
|
|
2306
|
+
|
|
2307
|
+
// Multiply claimable_rate by root_stake
|
|
2308
|
+
// I96F32 multiplication: round((a * b) / 2^32)
|
|
2309
|
+
const pendingRootClaim = stake * claimableRate + (1n << 31n) >> 32n;
|
|
2310
|
+
pendingRootClaimBalances.push({
|
|
2311
|
+
address,
|
|
2312
|
+
tokenId: subDTaoTokenId(networkId, netuid, hotkey),
|
|
2313
|
+
baseTokenId: subDTaoTokenId(networkId, netuid),
|
|
2314
|
+
hotkey: hotkey,
|
|
2315
|
+
netuid: netuid,
|
|
2316
|
+
scaledAlphaPrice,
|
|
2317
|
+
pendingRootClaim,
|
|
2318
|
+
stake: 0n
|
|
2319
|
+
});
|
|
2320
|
+
}
|
|
2321
|
+
return pendingRootClaimBalances;
|
|
2322
|
+
};
|
|
2323
|
+
|
|
2324
|
+
const ROOT_NETUID = 0;
|
|
2289
2325
|
const fetchBalances$5 = async ({
|
|
2290
2326
|
networkId,
|
|
2291
2327
|
tokensWithAddresses,
|
|
@@ -2335,20 +2371,63 @@ const fetchBalances$5 = async ({
|
|
|
2335
2371
|
const addresses = uniq(balanceDefs.map(def => def.address));
|
|
2336
2372
|
try {
|
|
2337
2373
|
const [stakeInfos, dynamicInfos] = await Promise.all([fetchRuntimeCallResult(connector, networkId, miniMetadata.data, "StakeInfoRuntimeApi", "get_stake_info_for_coldkeys", [addresses]), fetchRuntimeCallResult(connector, networkId, miniMetadata.data, "SubnetInfoRuntimeApi", "get_all_dynamic_info", [])]);
|
|
2374
|
+
const rootHotkeys = uniq(stakeInfos.flatMap(([, stakes]) => stakes.filter(stake => stake.netuid === ROOT_NETUID).map(stake => stake.hotkey)));
|
|
2375
|
+
const rootClaimableRatesByHotkey = rootHotkeys.length && miniMetadata.data ? await fetchRootClaimableRates(connector, networkId, miniMetadata.data, rootHotkeys) : new Map();
|
|
2338
2376
|
const dynamicInfoByNetuid = keyBy(dynamicInfos.filter(isNotNil), info => info.netuid);
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2377
|
+
|
|
2378
|
+
// Upserts a balance into the accumulator, merging stake values if the balance already exists.
|
|
2379
|
+
// Eg: Acc X has root staked with validator Y, but also staked on sn 45 with the same validator Y.
|
|
2380
|
+
// We merge the pending root claim of sn 45 and the sn 45 stake in the same balance.
|
|
2381
|
+
const upsertBalance = (acc, address, tokenId, balance) => {
|
|
2382
|
+
const key = `${address}:${tokenId}`;
|
|
2383
|
+
const recordedBalance = acc[key];
|
|
2384
|
+
if (recordedBalance) {
|
|
2385
|
+
acc[key] = {
|
|
2386
|
+
...recordedBalance,
|
|
2387
|
+
stake: recordedBalance.stake + balance.stake,
|
|
2388
|
+
// If the new balance has pendingRootClaim, use it (it's calculated from current state)
|
|
2389
|
+
...(balance.pendingRootClaim !== undefined && {
|
|
2390
|
+
pendingRootClaim: balance.pendingRootClaim
|
|
2391
|
+
})
|
|
2392
|
+
};
|
|
2393
|
+
} else {
|
|
2394
|
+
acc[key] = balance;
|
|
2395
|
+
}
|
|
2396
|
+
};
|
|
2397
|
+
const balancesRaw = stakeInfos.reduce((acc, [address, stakes]) => {
|
|
2398
|
+
for (const stake of stakes) {
|
|
2399
|
+
// Regular stake cases
|
|
2400
|
+
const dynamicInfo = dynamicInfoByNetuid[stake.netuid];
|
|
2401
|
+
const scaledAlphaPrice = dynamicInfo ? getScaledAlphaPrice(dynamicInfo.alpha_in, dynamicInfo.tao_in) : 0n;
|
|
2402
|
+
const balance = {
|
|
2403
|
+
address,
|
|
2404
|
+
tokenId: subDTaoTokenId(networkId, stake.netuid, stake.hotkey),
|
|
2405
|
+
baseTokenId: subDTaoTokenId(networkId, stake.netuid),
|
|
2406
|
+
stake: stake.stake,
|
|
2407
|
+
hotkey: stake.hotkey,
|
|
2408
|
+
netuid: stake.netuid,
|
|
2409
|
+
scaledAlphaPrice
|
|
2410
|
+
};
|
|
2411
|
+
upsertBalance(acc, address, balance.tokenId, balance);
|
|
2412
|
+
|
|
2413
|
+
// Root stake cases, we need to calculate the pending root claim and add to the balances
|
|
2414
|
+
if (stake.netuid === ROOT_NETUID) {
|
|
2415
|
+
const pendingRootClaimBalances = calculatePendingRootClaimable({
|
|
2416
|
+
stake: stake.stake,
|
|
2417
|
+
hotkey: stake.hotkey,
|
|
2418
|
+
address,
|
|
2419
|
+
networkId,
|
|
2420
|
+
validatorRootClaimableRate: rootClaimableRatesByHotkey.get(stake.hotkey) ?? new Map(),
|
|
2421
|
+
dynamicInfoByNetuid
|
|
2422
|
+
});
|
|
2423
|
+
pendingRootClaimBalances.forEach(balance => {
|
|
2424
|
+
upsertBalance(acc, address, balance.tokenId, balance);
|
|
2425
|
+
});
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
return acc;
|
|
2429
|
+
}, {});
|
|
2430
|
+
const balances = Object.values(balancesRaw);
|
|
2352
2431
|
const tokensById = keyBy(tokensWithAddresses.map(([token]) => token), t => t.id);
|
|
2353
2432
|
const dynamicTokens = [];
|
|
2354
2433
|
|
|
@@ -2374,19 +2453,45 @@ const fetchBalances$5 = async ({
|
|
|
2374
2453
|
const meta = {
|
|
2375
2454
|
scaledAlphaPrice: stake?.scaledAlphaPrice.toString() ?? "0"
|
|
2376
2455
|
};
|
|
2456
|
+
const stakeAmount = BigInt(stake?.stake?.toString() ?? "0");
|
|
2457
|
+
const pendingRootClaimAmount = BigInt(stake?.pendingRootClaim?.toString() ?? "0");
|
|
2458
|
+
const hasZeroStake = stakeAmount === 0n;
|
|
2459
|
+
const hasPendingRootClaim = pendingRootClaimAmount > 0n;
|
|
2377
2460
|
const balanceValue = {
|
|
2378
2461
|
type: "free",
|
|
2379
2462
|
label: stake?.netuid === 0 ? "Root Staking" : `Subnet Staking`,
|
|
2380
|
-
amount:
|
|
2463
|
+
amount: stakeAmount.toString(),
|
|
2381
2464
|
meta
|
|
2382
2465
|
};
|
|
2466
|
+
const pendingRootClaimValue = {
|
|
2467
|
+
type: "locked",
|
|
2468
|
+
label: "Pending root claim",
|
|
2469
|
+
amount: pendingRootClaimAmount.toString(),
|
|
2470
|
+
meta
|
|
2471
|
+
};
|
|
2472
|
+
const values = [balanceValue, pendingRootClaimValue];
|
|
2473
|
+
|
|
2474
|
+
// If stake is 0n but there's a pendingRootClaim, add it as an extra amount
|
|
2475
|
+
// with includeInTotal: true so it counts toward the total balance.
|
|
2476
|
+
// This ensures the balance isn't filtered out when stake is 0n.
|
|
2477
|
+
// The total.planck calculation is: free + reserved + extra (with includeInTotal: true)
|
|
2478
|
+
// So by adding pendingRootClaim as extra, it will be included in total.planck.
|
|
2479
|
+
if (hasZeroStake && hasPendingRootClaim) {
|
|
2480
|
+
values.push({
|
|
2481
|
+
type: "extra",
|
|
2482
|
+
label: "Pending root claim",
|
|
2483
|
+
amount: pendingRootClaimAmount.toString(),
|
|
2484
|
+
includeInTotal: true,
|
|
2485
|
+
meta
|
|
2486
|
+
});
|
|
2487
|
+
}
|
|
2383
2488
|
return {
|
|
2384
2489
|
address: def.address,
|
|
2385
2490
|
networkId,
|
|
2386
2491
|
tokenId: def.token.id,
|
|
2387
2492
|
source: MODULE_TYPE$5,
|
|
2388
2493
|
status: "live",
|
|
2389
|
-
values
|
|
2494
|
+
values
|
|
2390
2495
|
};
|
|
2391
2496
|
});
|
|
2392
2497
|
return {
|
|
@@ -2409,6 +2514,68 @@ const fetchBalances$5 = async ({
|
|
|
2409
2514
|
};
|
|
2410
2515
|
}
|
|
2411
2516
|
};
|
|
2517
|
+
const buildStorageCoder = (metadataRpc, pallet, entry) => {
|
|
2518
|
+
const {
|
|
2519
|
+
builder
|
|
2520
|
+
} = parseMetadataRpc(metadataRpc);
|
|
2521
|
+
return builder.buildStorage(pallet, entry);
|
|
2522
|
+
};
|
|
2523
|
+
const buildRootClaimableStorageCoder = async (connector, networkId, metadataRpc) => {
|
|
2524
|
+
let storageCoder = null;
|
|
2525
|
+
if (metadataRpc) {
|
|
2526
|
+
try {
|
|
2527
|
+
storageCoder = buildStorageCoder(metadataRpc, "SubtensorModule", "RootClaimable");
|
|
2528
|
+
} catch (cause) {
|
|
2529
|
+
log.warn(`Failed to build storage coder for SubtensorModule.RootClaimable using provided metadata on ${networkId}`, {
|
|
2530
|
+
cause
|
|
2531
|
+
});
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
return storageCoder;
|
|
2535
|
+
};
|
|
2536
|
+
const buildRootClaimableQueries = (networkId, hotkeys, storageCoder) => {
|
|
2537
|
+
return hotkeys.map(hotkey => {
|
|
2538
|
+
let stateKey = null;
|
|
2539
|
+
try {
|
|
2540
|
+
stateKey = storageCoder.keys.enc(hotkey);
|
|
2541
|
+
} catch (cause) {
|
|
2542
|
+
log.warn(`Failed to encode storage key for hotkey ${hotkey} on ${networkId}`, {
|
|
2543
|
+
cause
|
|
2544
|
+
});
|
|
2545
|
+
}
|
|
2546
|
+
const decodeResult = changes => {
|
|
2547
|
+
const hexValue = changes[0];
|
|
2548
|
+
if (!hexValue) {
|
|
2549
|
+
return [hotkey, new Map()];
|
|
2550
|
+
}
|
|
2551
|
+
const decoded = decodeScale(storageCoder, hexValue, `Failed to decode RootClaimable for hotkey ${hotkey} on ${networkId}`);
|
|
2552
|
+
return [hotkey, decoded ? new Map(decoded) : new Map()];
|
|
2553
|
+
};
|
|
2554
|
+
return {
|
|
2555
|
+
stateKeys: [stateKey],
|
|
2556
|
+
decodeResult
|
|
2557
|
+
};
|
|
2558
|
+
});
|
|
2559
|
+
};
|
|
2560
|
+
const fetchRootClaimableRates = async (connector, networkId, metadataRpc, hotkeys) => {
|
|
2561
|
+
if (!hotkeys.length) return new Map();
|
|
2562
|
+
const storageCoder = await buildRootClaimableStorageCoder(connector, networkId, metadataRpc);
|
|
2563
|
+
if (!storageCoder) {
|
|
2564
|
+
// Fallback: return empty map for all hotkeys
|
|
2565
|
+
return new Map(hotkeys.map(hotkey => [hotkey, new Map()]));
|
|
2566
|
+
}
|
|
2567
|
+
const queries = buildRootClaimableQueries(networkId, hotkeys, storageCoder);
|
|
2568
|
+
try {
|
|
2569
|
+
const results = await fetchRpcQueryPack(connector, networkId, queries);
|
|
2570
|
+
return new Map(results);
|
|
2571
|
+
} catch (cause) {
|
|
2572
|
+
log.warn(`Failed to fetch RootClaimable for hotkeys on ${networkId}`, {
|
|
2573
|
+
cause
|
|
2574
|
+
});
|
|
2575
|
+
// Fallback: return empty map for all hotkeys
|
|
2576
|
+
return new Map(hotkeys.map(hotkey => [hotkey, new Map()]));
|
|
2577
|
+
}
|
|
2578
|
+
};
|
|
2412
2579
|
|
|
2413
2580
|
// hardcoded because we dont have access to native tokens from the balance module
|
|
2414
2581
|
const NATIVE_TOKEN_SYMBOLS = {
|
|
@@ -2508,7 +2675,7 @@ const getData$4 = metadataRpc => {
|
|
|
2508
2675
|
if (!isBittensor) return null;
|
|
2509
2676
|
compactMetadata(metadata, [{
|
|
2510
2677
|
pallet: "SubtensorModule",
|
|
2511
|
-
items: ["TransferToggle"]
|
|
2678
|
+
items: ["TransferToggle", "RootClaimable"]
|
|
2512
2679
|
}], [{
|
|
2513
2680
|
runtimeApi: "StakeInfoRuntimeApi",
|
|
2514
2681
|
methods: ["get_stake_info_for_coldkeys"]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@talismn/balances",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-pr2279-20251222112424",
|
|
4
4
|
"author": "Talisman",
|
|
5
5
|
"homepage": "https://talisman.xyz",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -38,14 +38,14 @@
|
|
|
38
38
|
"scale-ts": "^1.6.1",
|
|
39
39
|
"viem": "^2.27.3",
|
|
40
40
|
"zod": "^3.25.76",
|
|
41
|
-
"@talismn/
|
|
42
|
-
"@talismn/
|
|
43
|
-
"@talismn/sapi": "0.
|
|
44
|
-
"@talismn/crypto": "0.
|
|
45
|
-
"@talismn/
|
|
46
|
-
"@talismn/
|
|
47
|
-
"@talismn/
|
|
48
|
-
"@talismn/
|
|
41
|
+
"@talismn/chain-connectors": "0.0.0-pr2279-20251222112424",
|
|
42
|
+
"@talismn/chaindata-provider": "0.0.0-pr2279-20251222112424",
|
|
43
|
+
"@talismn/sapi": "0.1.0",
|
|
44
|
+
"@talismn/crypto": "0.3.0",
|
|
45
|
+
"@talismn/scale": "0.3.0",
|
|
46
|
+
"@talismn/solana": "0.0.5",
|
|
47
|
+
"@talismn/token-rates": "0.0.0-pr2279-20251222112424",
|
|
48
|
+
"@talismn/util": "0.5.6"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@polkadot/api-contract": "16.1.2",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"jest": "^29.7.0",
|
|
61
61
|
"ts-jest": "^29.2.5",
|
|
62
62
|
"typescript": "^5.6.3",
|
|
63
|
-
"@talismn/
|
|
64
|
-
"@talismn/
|
|
63
|
+
"@talismn/eslint-config": "0.0.3",
|
|
64
|
+
"@talismn/tsconfig": "0.0.3"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"@polkadot/api-contract": "*",
|