@talismn/balances 1.1.0 → 1.2.1
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.
|
@@ -2432,7 +2432,7 @@ const fetchTokens$5 = async ({
|
|
|
2432
2432
|
}) => {
|
|
2433
2433
|
const anyMiniMetadata = miniMetadata;
|
|
2434
2434
|
if (!anyMiniMetadata?.data) return [];
|
|
2435
|
-
const dynamicInfos = await fetchRuntimeCallResult(connector, networkId, anyMiniMetadata.data, "SubnetInfoRuntimeApi", "get_all_dynamic_info", []);
|
|
2435
|
+
const [transferableTokensMap, dynamicInfos] = await Promise.all([fetchTransferableTokensMap(connector, anyMiniMetadata.data, networkId), fetchRuntimeCallResult(connector, networkId, anyMiniMetadata.data, "SubnetInfoRuntimeApi", "get_all_dynamic_info", [])]);
|
|
2436
2436
|
return dynamicInfos.filter(util.isNotNil).map(info => {
|
|
2437
2437
|
const config = tokens.find(t => t.netuid === info.netuid);
|
|
2438
2438
|
let symbol = new TextDecoder().decode(Uint8Array.from(info.token_symbol));
|
|
@@ -2441,7 +2441,10 @@ const fetchTokens$5 = async ({
|
|
|
2441
2441
|
|
|
2442
2442
|
// for root we want same symbol as native so they can be grouped together in portfolio
|
|
2443
2443
|
if (info.netuid === 0 && NATIVE_TOKEN_SYMBOLS[networkId]) symbol = NATIVE_TOKEN_SYMBOLS[networkId];
|
|
2444
|
-
|
|
2444
|
+
|
|
2445
|
+
// if not stage in storage, consider transferable
|
|
2446
|
+
const isTransferable = transferableTokensMap[info.netuid] ?? true;
|
|
2447
|
+
const token = {
|
|
2445
2448
|
id: chaindataProvider.subDTaoTokenId(networkId, info.netuid),
|
|
2446
2449
|
type: MODULE_TYPE$5,
|
|
2447
2450
|
platform: PLATFORM$5,
|
|
@@ -2451,13 +2454,29 @@ const fetchTokens$5 = async ({
|
|
|
2451
2454
|
symbol,
|
|
2452
2455
|
decimals: 9,
|
|
2453
2456
|
name,
|
|
2454
|
-
subnetName
|
|
2455
|
-
|
|
2457
|
+
subnetName,
|
|
2458
|
+
isTransferable
|
|
2459
|
+
};
|
|
2460
|
+
return Object.assign({}, token, config);
|
|
2456
2461
|
}).filter(t => {
|
|
2457
2462
|
const parsed = chaindataProvider.SubDTaoTokenSchema.safeParse(t);
|
|
2458
2463
|
return parsed.success;
|
|
2459
2464
|
});
|
|
2460
2465
|
};
|
|
2466
|
+
const fetchTransferableTokensMap = async (connector, metadata, networkId) => {
|
|
2467
|
+
const {
|
|
2468
|
+
builder
|
|
2469
|
+
} = scale.parseMetadataRpc(metadata);
|
|
2470
|
+
const transferToggleCodec = builder.buildStorage("SubtensorModule", "TransferToggle");
|
|
2471
|
+
const transferToggleKeys = await connector.send(networkId, "state_getKeys", [scale.getStorageKeyPrefix("SubtensorModule", "TransferToggle")]);
|
|
2472
|
+
const transferToggleResults = await connector.send(networkId, "state_queryStorageAt", [transferToggleKeys]);
|
|
2473
|
+
const transferToggleEntries = transferToggleResults.length ? transferToggleResults[0].changes : [];
|
|
2474
|
+
return lodashEs.fromPairs(transferToggleEntries.map(([key, value]) => {
|
|
2475
|
+
const [netuid] = transferToggleCodec.keys.dec(key);
|
|
2476
|
+
const isTransferable = transferToggleCodec.value.dec(value);
|
|
2477
|
+
return [netuid, isTransferable];
|
|
2478
|
+
}));
|
|
2479
|
+
};
|
|
2461
2480
|
|
|
2462
2481
|
const getMiniMetadata$6 = ({
|
|
2463
2482
|
networkId,
|
|
@@ -2496,9 +2515,10 @@ const getData$4 = metadataRpc => {
|
|
|
2496
2515
|
name
|
|
2497
2516
|
}) => name === "SubtensorModule");
|
|
2498
2517
|
if (!isBittensor) return null;
|
|
2499
|
-
scale.compactMetadata(metadata, [
|
|
2500
|
-
|
|
2501
|
-
|
|
2518
|
+
scale.compactMetadata(metadata, [{
|
|
2519
|
+
pallet: "SubtensorModule",
|
|
2520
|
+
items: ["TransferToggle"]
|
|
2521
|
+
}], [{
|
|
2502
2522
|
runtimeApi: "StakeInfoRuntimeApi",
|
|
2503
2523
|
methods: ["get_stake_info_for_coldkeys"]
|
|
2504
2524
|
}, {
|
|
@@ -6947,7 +6967,8 @@ class BalancesProvider {
|
|
|
6947
6967
|
balances: results.flatMap(result => result.balances.map(b => isStale && b.status !== "live" ? {
|
|
6948
6968
|
...b,
|
|
6949
6969
|
status: "stale"
|
|
6950
|
-
} : b)).sort(sortByBalanceId)
|
|
6970
|
+
} : b)).sort(sortByBalanceId),
|
|
6971
|
+
failedBalanceIds: results.flatMap(result => result.failedBalanceIds)
|
|
6951
6972
|
})), rxjs.distinctUntilChanged(lodashEs.isEqual));
|
|
6952
6973
|
}
|
|
6953
6974
|
fetchBalances(addressesByTokenId) {
|
|
@@ -6988,17 +7009,25 @@ class BalancesProvider {
|
|
|
6988
7009
|
});
|
|
6989
7010
|
return rxjs.of({
|
|
6990
7011
|
status: "live",
|
|
6991
|
-
balances: []
|
|
7012
|
+
balances: [],
|
|
7013
|
+
failedBalanceIds: []
|
|
6992
7014
|
});
|
|
6993
7015
|
}
|
|
6994
7016
|
}
|
|
6995
7017
|
}));
|
|
6996
7018
|
}), rxjs.map(results => {
|
|
7019
|
+
// for each balance that could not be fetched, see if we have a stored balance and return it, marked as stale
|
|
7020
|
+
const errorBalanceIds = results.flatMap(result => result.failedBalanceIds);
|
|
7021
|
+
const staleBalances = errorBalanceIds.map(balanceId => this.#storage.value.balances[balanceId]).filter(util.isNotNil).map(b => ({
|
|
7022
|
+
...b,
|
|
7023
|
+
status: "stale"
|
|
7024
|
+
}));
|
|
6997
7025
|
return {
|
|
6998
7026
|
status: results.some(({
|
|
6999
7027
|
status
|
|
7000
7028
|
}) => status === "initialising") ? "initialising" : "live",
|
|
7001
|
-
balances: results.flatMap(result => result.balances).sort(sortByBalanceId)
|
|
7029
|
+
balances: results.flatMap(result => result.balances).concat(staleBalances).sort(sortByBalanceId),
|
|
7030
|
+
failedBalanceIds: []
|
|
7002
7031
|
};
|
|
7003
7032
|
}), rxjs.distinctUntilChanged(lodashEs.isEqual));
|
|
7004
7033
|
}
|
|
@@ -7010,7 +7039,8 @@ class BalancesProvider {
|
|
|
7010
7039
|
}, () => {
|
|
7011
7040
|
if (!tokensWithAddresses.length) return rxjs.of({
|
|
7012
7041
|
status: "live",
|
|
7013
|
-
balances: []
|
|
7042
|
+
balances: [],
|
|
7043
|
+
failedBalanceIds: []
|
|
7014
7044
|
});
|
|
7015
7045
|
const moduleAddressesByTokenId = lodashEs.fromPairs(tokensWithAddresses.map(([token, addresses]) => [token.id, addresses]));
|
|
7016
7046
|
|
|
@@ -7023,7 +7053,8 @@ class BalancesProvider {
|
|
|
7023
7053
|
log.warn("[balances] no substrate connector or miniMetadata for module", mod.type);
|
|
7024
7054
|
return rxjs.defer(() => rxjs.of({
|
|
7025
7055
|
status: "initialising",
|
|
7026
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7056
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7057
|
+
failedBalanceIds: []
|
|
7027
7058
|
}));
|
|
7028
7059
|
}
|
|
7029
7060
|
const moduleBalances$ = this.getNetworkMiniMetadatas$(networkId).pipe(rxjs.map(miniMetadatas => miniMetadatas.find(m => m.source === mod.type)), rxjs.switchMap(miniMetadata => mod.subscribeBalances({
|
|
@@ -7041,7 +7072,14 @@ class BalancesProvider {
|
|
|
7041
7072
|
}), rxjs.map(results => ({
|
|
7042
7073
|
status: "live",
|
|
7043
7074
|
// exclude zero balances
|
|
7044
|
-
balances: results.success.filter(b => new Balance(b).total.planck > 0n)
|
|
7075
|
+
balances: results.success.filter(b => new Balance(b).total.planck > 0n),
|
|
7076
|
+
failedBalanceIds: results.errors.map(({
|
|
7077
|
+
tokenId,
|
|
7078
|
+
address
|
|
7079
|
+
}) => getBalanceId({
|
|
7080
|
+
tokenId,
|
|
7081
|
+
address
|
|
7082
|
+
}))
|
|
7045
7083
|
})), rxjs.tap(results => {
|
|
7046
7084
|
this.updateStorage$(balanceIds, results);
|
|
7047
7085
|
}),
|
|
@@ -7054,7 +7092,8 @@ class BalancesProvider {
|
|
|
7054
7092
|
// defer the startWith call to start with up to date balances each time the observable is re-subscribed to
|
|
7055
7093
|
return rxjs.defer(() => moduleBalances$.pipe(rxjs.startWith({
|
|
7056
7094
|
status: "initialising",
|
|
7057
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7095
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7096
|
+
failedBalanceIds: []
|
|
7058
7097
|
})));
|
|
7059
7098
|
});
|
|
7060
7099
|
}
|
|
@@ -7066,7 +7105,8 @@ class BalancesProvider {
|
|
|
7066
7105
|
}, () => {
|
|
7067
7106
|
if (!tokensWithAddresses.length) return rxjs.of({
|
|
7068
7107
|
status: "live",
|
|
7069
|
-
balances: []
|
|
7108
|
+
balances: [],
|
|
7109
|
+
failedBalanceIds: []
|
|
7070
7110
|
});
|
|
7071
7111
|
const moduleAddressesByTokenId = lodashEs.fromPairs(tokensWithAddresses.map(([token, addresses]) => [token.id, addresses]));
|
|
7072
7112
|
|
|
@@ -7079,7 +7119,8 @@ class BalancesProvider {
|
|
|
7079
7119
|
log.warn("[balances] no ethereum connector for module", mod.type);
|
|
7080
7120
|
return rxjs.defer(() => rxjs.of({
|
|
7081
7121
|
status: "initialising",
|
|
7082
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7122
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7123
|
+
failedBalanceIds: []
|
|
7083
7124
|
}));
|
|
7084
7125
|
}
|
|
7085
7126
|
const moduleBalances$ = mod.subscribeBalances({
|
|
@@ -7091,7 +7132,14 @@ class BalancesProvider {
|
|
|
7091
7132
|
rxjs.map(results => ({
|
|
7092
7133
|
status: "live",
|
|
7093
7134
|
// exclude zero balances
|
|
7094
|
-
balances: results.success.filter(b => new Balance(b).total.planck > 0n)
|
|
7135
|
+
balances: results.success.filter(b => new Balance(b).total.planck > 0n),
|
|
7136
|
+
failedBalanceIds: results.errors.map(({
|
|
7137
|
+
tokenId,
|
|
7138
|
+
address
|
|
7139
|
+
}) => getBalanceId({
|
|
7140
|
+
tokenId,
|
|
7141
|
+
address
|
|
7142
|
+
}))
|
|
7095
7143
|
})), rxjs.tap(results => {
|
|
7096
7144
|
this.updateStorage$(balanceIds, results);
|
|
7097
7145
|
}),
|
|
@@ -7104,7 +7152,8 @@ class BalancesProvider {
|
|
|
7104
7152
|
// defer the startWith call to start with up to date balances each time the observable is re-subscribed to
|
|
7105
7153
|
return rxjs.defer(() => moduleBalances$.pipe(rxjs.startWith({
|
|
7106
7154
|
status: "initialising",
|
|
7107
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7155
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7156
|
+
failedBalanceIds: []
|
|
7108
7157
|
})));
|
|
7109
7158
|
});
|
|
7110
7159
|
}
|
|
@@ -7116,7 +7165,8 @@ class BalancesProvider {
|
|
|
7116
7165
|
}, () => {
|
|
7117
7166
|
if (!tokensWithAddresses.length) return rxjs.of({
|
|
7118
7167
|
status: "live",
|
|
7119
|
-
balances: []
|
|
7168
|
+
balances: [],
|
|
7169
|
+
failedBalanceIds: []
|
|
7120
7170
|
});
|
|
7121
7171
|
const moduleAddressesByTokenId = lodashEs.fromPairs(tokensWithAddresses.map(([token, addresses]) => [token.id, addresses]));
|
|
7122
7172
|
|
|
@@ -7129,7 +7179,8 @@ class BalancesProvider {
|
|
|
7129
7179
|
log.warn("[balances] no solana connector for module", mod.type);
|
|
7130
7180
|
return rxjs.defer(() => rxjs.of({
|
|
7131
7181
|
status: "initialising",
|
|
7132
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7182
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7183
|
+
failedBalanceIds: []
|
|
7133
7184
|
}));
|
|
7134
7185
|
}
|
|
7135
7186
|
const moduleBalances$ = mod.subscribeBalances({
|
|
@@ -7141,7 +7192,14 @@ class BalancesProvider {
|
|
|
7141
7192
|
rxjs.map(results => ({
|
|
7142
7193
|
status: "live",
|
|
7143
7194
|
// exclude zero balances
|
|
7144
|
-
balances: results.success.filter(b => new Balance(b).total.planck > 0n)
|
|
7195
|
+
balances: results.success.filter(b => new Balance(b).total.planck > 0n),
|
|
7196
|
+
failedBalanceIds: results.errors.map(({
|
|
7197
|
+
tokenId,
|
|
7198
|
+
address
|
|
7199
|
+
}) => getBalanceId({
|
|
7200
|
+
tokenId,
|
|
7201
|
+
address
|
|
7202
|
+
}))
|
|
7145
7203
|
})), rxjs.tap(results => {
|
|
7146
7204
|
this.updateStorage$(balanceIds, results);
|
|
7147
7205
|
}),
|
|
@@ -7154,7 +7212,8 @@ class BalancesProvider {
|
|
|
7154
7212
|
// defer the startWith call to start with up to date balances each time the observable is re-subscribed to
|
|
7155
7213
|
return rxjs.defer(() => moduleBalances$.pipe(rxjs.startWith({
|
|
7156
7214
|
status: "initialising",
|
|
7157
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7215
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7216
|
+
failedBalanceIds: []
|
|
7158
7217
|
})));
|
|
7159
7218
|
});
|
|
7160
7219
|
}
|
|
@@ -7162,13 +7221,19 @@ class BalancesProvider {
|
|
|
7162
7221
|
if (balancesResult.status !== "live") return;
|
|
7163
7222
|
const storage = this.#storage.getValue();
|
|
7164
7223
|
const balances = lodashEs.assign({}, storage.balances,
|
|
7165
|
-
// delete all balances expected in the result set. because if they are not present it means they are empty.
|
|
7166
|
-
lodashEs.fromPairs(balanceIds.map(balanceId => [balanceId, undefined])), lodashEs.keyBy(
|
|
7224
|
+
// delete all balances expected in the result set (except the ones that failed). because if they are not present it means they are empty.
|
|
7225
|
+
lodashEs.fromPairs(balanceIds.filter(bid => !balancesResult.failedBalanceIds.includes(bid)).map(balanceId => [balanceId, undefined])), lodashEs.keyBy(
|
|
7167
7226
|
// storage balances must have status "cache", because they are used as start value when initialising subsequent subscriptions
|
|
7168
7227
|
balancesResult.balances.map(b => ({
|
|
7169
7228
|
...b,
|
|
7170
7229
|
status: "cache"
|
|
7171
7230
|
})), b => getBalanceId(b)));
|
|
7231
|
+
|
|
7232
|
+
// update status of stale balances
|
|
7233
|
+
for (const errorBalanceId of balancesResult.failedBalanceIds) {
|
|
7234
|
+
const balance = balances[errorBalanceId];
|
|
7235
|
+
if (balance) balance.status = "stale";
|
|
7236
|
+
}
|
|
7172
7237
|
this.#storage.next(lodashEs.assign({}, storage, {
|
|
7173
7238
|
balances
|
|
7174
7239
|
}));
|
|
@@ -2432,7 +2432,7 @@ const fetchTokens$5 = async ({
|
|
|
2432
2432
|
}) => {
|
|
2433
2433
|
const anyMiniMetadata = miniMetadata;
|
|
2434
2434
|
if (!anyMiniMetadata?.data) return [];
|
|
2435
|
-
const dynamicInfos = await fetchRuntimeCallResult(connector, networkId, anyMiniMetadata.data, "SubnetInfoRuntimeApi", "get_all_dynamic_info", []);
|
|
2435
|
+
const [transferableTokensMap, dynamicInfos] = await Promise.all([fetchTransferableTokensMap(connector, anyMiniMetadata.data, networkId), fetchRuntimeCallResult(connector, networkId, anyMiniMetadata.data, "SubnetInfoRuntimeApi", "get_all_dynamic_info", [])]);
|
|
2436
2436
|
return dynamicInfos.filter(util.isNotNil).map(info => {
|
|
2437
2437
|
const config = tokens.find(t => t.netuid === info.netuid);
|
|
2438
2438
|
let symbol = new TextDecoder().decode(Uint8Array.from(info.token_symbol));
|
|
@@ -2441,7 +2441,10 @@ const fetchTokens$5 = async ({
|
|
|
2441
2441
|
|
|
2442
2442
|
// for root we want same symbol as native so they can be grouped together in portfolio
|
|
2443
2443
|
if (info.netuid === 0 && NATIVE_TOKEN_SYMBOLS[networkId]) symbol = NATIVE_TOKEN_SYMBOLS[networkId];
|
|
2444
|
-
|
|
2444
|
+
|
|
2445
|
+
// if not stage in storage, consider transferable
|
|
2446
|
+
const isTransferable = transferableTokensMap[info.netuid] ?? true;
|
|
2447
|
+
const token = {
|
|
2445
2448
|
id: chaindataProvider.subDTaoTokenId(networkId, info.netuid),
|
|
2446
2449
|
type: MODULE_TYPE$5,
|
|
2447
2450
|
platform: PLATFORM$5,
|
|
@@ -2451,13 +2454,29 @@ const fetchTokens$5 = async ({
|
|
|
2451
2454
|
symbol,
|
|
2452
2455
|
decimals: 9,
|
|
2453
2456
|
name,
|
|
2454
|
-
subnetName
|
|
2455
|
-
|
|
2457
|
+
subnetName,
|
|
2458
|
+
isTransferable
|
|
2459
|
+
};
|
|
2460
|
+
return Object.assign({}, token, config);
|
|
2456
2461
|
}).filter(t => {
|
|
2457
2462
|
const parsed = chaindataProvider.SubDTaoTokenSchema.safeParse(t);
|
|
2458
2463
|
return parsed.success;
|
|
2459
2464
|
});
|
|
2460
2465
|
};
|
|
2466
|
+
const fetchTransferableTokensMap = async (connector, metadata, networkId) => {
|
|
2467
|
+
const {
|
|
2468
|
+
builder
|
|
2469
|
+
} = scale.parseMetadataRpc(metadata);
|
|
2470
|
+
const transferToggleCodec = builder.buildStorage("SubtensorModule", "TransferToggle");
|
|
2471
|
+
const transferToggleKeys = await connector.send(networkId, "state_getKeys", [scale.getStorageKeyPrefix("SubtensorModule", "TransferToggle")]);
|
|
2472
|
+
const transferToggleResults = await connector.send(networkId, "state_queryStorageAt", [transferToggleKeys]);
|
|
2473
|
+
const transferToggleEntries = transferToggleResults.length ? transferToggleResults[0].changes : [];
|
|
2474
|
+
return lodashEs.fromPairs(transferToggleEntries.map(([key, value]) => {
|
|
2475
|
+
const [netuid] = transferToggleCodec.keys.dec(key);
|
|
2476
|
+
const isTransferable = transferToggleCodec.value.dec(value);
|
|
2477
|
+
return [netuid, isTransferable];
|
|
2478
|
+
}));
|
|
2479
|
+
};
|
|
2461
2480
|
|
|
2462
2481
|
const getMiniMetadata$6 = ({
|
|
2463
2482
|
networkId,
|
|
@@ -2496,9 +2515,10 @@ const getData$4 = metadataRpc => {
|
|
|
2496
2515
|
name
|
|
2497
2516
|
}) => name === "SubtensorModule");
|
|
2498
2517
|
if (!isBittensor) return null;
|
|
2499
|
-
scale.compactMetadata(metadata, [
|
|
2500
|
-
|
|
2501
|
-
|
|
2518
|
+
scale.compactMetadata(metadata, [{
|
|
2519
|
+
pallet: "SubtensorModule",
|
|
2520
|
+
items: ["TransferToggle"]
|
|
2521
|
+
}], [{
|
|
2502
2522
|
runtimeApi: "StakeInfoRuntimeApi",
|
|
2503
2523
|
methods: ["get_stake_info_for_coldkeys"]
|
|
2504
2524
|
}, {
|
|
@@ -6947,7 +6967,8 @@ class BalancesProvider {
|
|
|
6947
6967
|
balances: results.flatMap(result => result.balances.map(b => isStale && b.status !== "live" ? {
|
|
6948
6968
|
...b,
|
|
6949
6969
|
status: "stale"
|
|
6950
|
-
} : b)).sort(sortByBalanceId)
|
|
6970
|
+
} : b)).sort(sortByBalanceId),
|
|
6971
|
+
failedBalanceIds: results.flatMap(result => result.failedBalanceIds)
|
|
6951
6972
|
})), rxjs.distinctUntilChanged(lodashEs.isEqual));
|
|
6952
6973
|
}
|
|
6953
6974
|
fetchBalances(addressesByTokenId) {
|
|
@@ -6988,17 +7009,25 @@ class BalancesProvider {
|
|
|
6988
7009
|
});
|
|
6989
7010
|
return rxjs.of({
|
|
6990
7011
|
status: "live",
|
|
6991
|
-
balances: []
|
|
7012
|
+
balances: [],
|
|
7013
|
+
failedBalanceIds: []
|
|
6992
7014
|
});
|
|
6993
7015
|
}
|
|
6994
7016
|
}
|
|
6995
7017
|
}));
|
|
6996
7018
|
}), rxjs.map(results => {
|
|
7019
|
+
// for each balance that could not be fetched, see if we have a stored balance and return it, marked as stale
|
|
7020
|
+
const errorBalanceIds = results.flatMap(result => result.failedBalanceIds);
|
|
7021
|
+
const staleBalances = errorBalanceIds.map(balanceId => this.#storage.value.balances[balanceId]).filter(util.isNotNil).map(b => ({
|
|
7022
|
+
...b,
|
|
7023
|
+
status: "stale"
|
|
7024
|
+
}));
|
|
6997
7025
|
return {
|
|
6998
7026
|
status: results.some(({
|
|
6999
7027
|
status
|
|
7000
7028
|
}) => status === "initialising") ? "initialising" : "live",
|
|
7001
|
-
balances: results.flatMap(result => result.balances).sort(sortByBalanceId)
|
|
7029
|
+
balances: results.flatMap(result => result.balances).concat(staleBalances).sort(sortByBalanceId),
|
|
7030
|
+
failedBalanceIds: []
|
|
7002
7031
|
};
|
|
7003
7032
|
}), rxjs.distinctUntilChanged(lodashEs.isEqual));
|
|
7004
7033
|
}
|
|
@@ -7010,7 +7039,8 @@ class BalancesProvider {
|
|
|
7010
7039
|
}, () => {
|
|
7011
7040
|
if (!tokensWithAddresses.length) return rxjs.of({
|
|
7012
7041
|
status: "live",
|
|
7013
|
-
balances: []
|
|
7042
|
+
balances: [],
|
|
7043
|
+
failedBalanceIds: []
|
|
7014
7044
|
});
|
|
7015
7045
|
const moduleAddressesByTokenId = lodashEs.fromPairs(tokensWithAddresses.map(([token, addresses]) => [token.id, addresses]));
|
|
7016
7046
|
|
|
@@ -7023,7 +7053,8 @@ class BalancesProvider {
|
|
|
7023
7053
|
log.warn("[balances] no substrate connector or miniMetadata for module", mod.type);
|
|
7024
7054
|
return rxjs.defer(() => rxjs.of({
|
|
7025
7055
|
status: "initialising",
|
|
7026
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7056
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7057
|
+
failedBalanceIds: []
|
|
7027
7058
|
}));
|
|
7028
7059
|
}
|
|
7029
7060
|
const moduleBalances$ = this.getNetworkMiniMetadatas$(networkId).pipe(rxjs.map(miniMetadatas => miniMetadatas.find(m => m.source === mod.type)), rxjs.switchMap(miniMetadata => mod.subscribeBalances({
|
|
@@ -7041,7 +7072,14 @@ class BalancesProvider {
|
|
|
7041
7072
|
}), rxjs.map(results => ({
|
|
7042
7073
|
status: "live",
|
|
7043
7074
|
// exclude zero balances
|
|
7044
|
-
balances: results.success.filter(b => new Balance(b).total.planck > 0n)
|
|
7075
|
+
balances: results.success.filter(b => new Balance(b).total.planck > 0n),
|
|
7076
|
+
failedBalanceIds: results.errors.map(({
|
|
7077
|
+
tokenId,
|
|
7078
|
+
address
|
|
7079
|
+
}) => getBalanceId({
|
|
7080
|
+
tokenId,
|
|
7081
|
+
address
|
|
7082
|
+
}))
|
|
7045
7083
|
})), rxjs.tap(results => {
|
|
7046
7084
|
this.updateStorage$(balanceIds, results);
|
|
7047
7085
|
}),
|
|
@@ -7054,7 +7092,8 @@ class BalancesProvider {
|
|
|
7054
7092
|
// defer the startWith call to start with up to date balances each time the observable is re-subscribed to
|
|
7055
7093
|
return rxjs.defer(() => moduleBalances$.pipe(rxjs.startWith({
|
|
7056
7094
|
status: "initialising",
|
|
7057
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7095
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7096
|
+
failedBalanceIds: []
|
|
7058
7097
|
})));
|
|
7059
7098
|
});
|
|
7060
7099
|
}
|
|
@@ -7066,7 +7105,8 @@ class BalancesProvider {
|
|
|
7066
7105
|
}, () => {
|
|
7067
7106
|
if (!tokensWithAddresses.length) return rxjs.of({
|
|
7068
7107
|
status: "live",
|
|
7069
|
-
balances: []
|
|
7108
|
+
balances: [],
|
|
7109
|
+
failedBalanceIds: []
|
|
7070
7110
|
});
|
|
7071
7111
|
const moduleAddressesByTokenId = lodashEs.fromPairs(tokensWithAddresses.map(([token, addresses]) => [token.id, addresses]));
|
|
7072
7112
|
|
|
@@ -7079,7 +7119,8 @@ class BalancesProvider {
|
|
|
7079
7119
|
log.warn("[balances] no ethereum connector for module", mod.type);
|
|
7080
7120
|
return rxjs.defer(() => rxjs.of({
|
|
7081
7121
|
status: "initialising",
|
|
7082
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7122
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7123
|
+
failedBalanceIds: []
|
|
7083
7124
|
}));
|
|
7084
7125
|
}
|
|
7085
7126
|
const moduleBalances$ = mod.subscribeBalances({
|
|
@@ -7091,7 +7132,14 @@ class BalancesProvider {
|
|
|
7091
7132
|
rxjs.map(results => ({
|
|
7092
7133
|
status: "live",
|
|
7093
7134
|
// exclude zero balances
|
|
7094
|
-
balances: results.success.filter(b => new Balance(b).total.planck > 0n)
|
|
7135
|
+
balances: results.success.filter(b => new Balance(b).total.planck > 0n),
|
|
7136
|
+
failedBalanceIds: results.errors.map(({
|
|
7137
|
+
tokenId,
|
|
7138
|
+
address
|
|
7139
|
+
}) => getBalanceId({
|
|
7140
|
+
tokenId,
|
|
7141
|
+
address
|
|
7142
|
+
}))
|
|
7095
7143
|
})), rxjs.tap(results => {
|
|
7096
7144
|
this.updateStorage$(balanceIds, results);
|
|
7097
7145
|
}),
|
|
@@ -7104,7 +7152,8 @@ class BalancesProvider {
|
|
|
7104
7152
|
// defer the startWith call to start with up to date balances each time the observable is re-subscribed to
|
|
7105
7153
|
return rxjs.defer(() => moduleBalances$.pipe(rxjs.startWith({
|
|
7106
7154
|
status: "initialising",
|
|
7107
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7155
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7156
|
+
failedBalanceIds: []
|
|
7108
7157
|
})));
|
|
7109
7158
|
});
|
|
7110
7159
|
}
|
|
@@ -7116,7 +7165,8 @@ class BalancesProvider {
|
|
|
7116
7165
|
}, () => {
|
|
7117
7166
|
if (!tokensWithAddresses.length) return rxjs.of({
|
|
7118
7167
|
status: "live",
|
|
7119
|
-
balances: []
|
|
7168
|
+
balances: [],
|
|
7169
|
+
failedBalanceIds: []
|
|
7120
7170
|
});
|
|
7121
7171
|
const moduleAddressesByTokenId = lodashEs.fromPairs(tokensWithAddresses.map(([token, addresses]) => [token.id, addresses]));
|
|
7122
7172
|
|
|
@@ -7129,7 +7179,8 @@ class BalancesProvider {
|
|
|
7129
7179
|
log.warn("[balances] no solana connector for module", mod.type);
|
|
7130
7180
|
return rxjs.defer(() => rxjs.of({
|
|
7131
7181
|
status: "initialising",
|
|
7132
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7182
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7183
|
+
failedBalanceIds: []
|
|
7133
7184
|
}));
|
|
7134
7185
|
}
|
|
7135
7186
|
const moduleBalances$ = mod.subscribeBalances({
|
|
@@ -7141,7 +7192,14 @@ class BalancesProvider {
|
|
|
7141
7192
|
rxjs.map(results => ({
|
|
7142
7193
|
status: "live",
|
|
7143
7194
|
// exclude zero balances
|
|
7144
|
-
balances: results.success.filter(b => new Balance(b).total.planck > 0n)
|
|
7195
|
+
balances: results.success.filter(b => new Balance(b).total.planck > 0n),
|
|
7196
|
+
failedBalanceIds: results.errors.map(({
|
|
7197
|
+
tokenId,
|
|
7198
|
+
address
|
|
7199
|
+
}) => getBalanceId({
|
|
7200
|
+
tokenId,
|
|
7201
|
+
address
|
|
7202
|
+
}))
|
|
7145
7203
|
})), rxjs.tap(results => {
|
|
7146
7204
|
this.updateStorage$(balanceIds, results);
|
|
7147
7205
|
}),
|
|
@@ -7154,7 +7212,8 @@ class BalancesProvider {
|
|
|
7154
7212
|
// defer the startWith call to start with up to date balances each time the observable is re-subscribed to
|
|
7155
7213
|
return rxjs.defer(() => moduleBalances$.pipe(rxjs.startWith({
|
|
7156
7214
|
status: "initialising",
|
|
7157
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7215
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7216
|
+
failedBalanceIds: []
|
|
7158
7217
|
})));
|
|
7159
7218
|
});
|
|
7160
7219
|
}
|
|
@@ -7162,13 +7221,19 @@ class BalancesProvider {
|
|
|
7162
7221
|
if (balancesResult.status !== "live") return;
|
|
7163
7222
|
const storage = this.#storage.getValue();
|
|
7164
7223
|
const balances = lodashEs.assign({}, storage.balances,
|
|
7165
|
-
// delete all balances expected in the result set. because if they are not present it means they are empty.
|
|
7166
|
-
lodashEs.fromPairs(balanceIds.map(balanceId => [balanceId, undefined])), lodashEs.keyBy(
|
|
7224
|
+
// delete all balances expected in the result set (except the ones that failed). because if they are not present it means they are empty.
|
|
7225
|
+
lodashEs.fromPairs(balanceIds.filter(bid => !balancesResult.failedBalanceIds.includes(bid)).map(balanceId => [balanceId, undefined])), lodashEs.keyBy(
|
|
7167
7226
|
// storage balances must have status "cache", because they are used as start value when initialising subsequent subscriptions
|
|
7168
7227
|
balancesResult.balances.map(b => ({
|
|
7169
7228
|
...b,
|
|
7170
7229
|
status: "cache"
|
|
7171
7230
|
})), b => getBalanceId(b)));
|
|
7231
|
+
|
|
7232
|
+
// update status of stale balances
|
|
7233
|
+
for (const errorBalanceId of balancesResult.failedBalanceIds) {
|
|
7234
|
+
const balance = balances[errorBalanceId];
|
|
7235
|
+
if (balance) balance.status = "stale";
|
|
7236
|
+
}
|
|
7172
7237
|
this.#storage.next(lodashEs.assign({}, storage, {
|
|
7173
7238
|
balances
|
|
7174
7239
|
}));
|
|
@@ -2,7 +2,7 @@ import { EvmErc20TokenSchema, parseTokenId, parseEvmErc20TokenId, evmErc20TokenI
|
|
|
2
2
|
export { MINIMETADATA_VERSION } from '@talismn/chaindata-provider';
|
|
3
3
|
import { isEthereumAddress, isSolanaAddress, normalizeAddress, getAccountPlatformFromAddress } from '@talismn/crypto';
|
|
4
4
|
import { parseAbi, erc20Abi, getContract, ContractFunctionExecutionError, hexToString, erc20Abi_bytes32, encodeFunctionData, withRetry } from 'viem';
|
|
5
|
-
import { assign, omit, isEqual, uniq, keyBy, toPairs, keys,
|
|
5
|
+
import { assign, omit, isEqual, uniq, keyBy, toPairs, keys, fromPairs, values } from 'lodash-es';
|
|
6
6
|
import z from 'zod/v4';
|
|
7
7
|
import anylogger from 'anylogger';
|
|
8
8
|
import { of, Observable, distinctUntilChanged, BehaviorSubject, map, switchMap, shareReplay, combineLatest, timer, startWith, firstValueFrom, filter, defer, catchError, EMPTY, tap, from } from 'rxjs';
|
|
@@ -2423,7 +2423,7 @@ const fetchTokens$5 = async ({
|
|
|
2423
2423
|
}) => {
|
|
2424
2424
|
const anyMiniMetadata = miniMetadata;
|
|
2425
2425
|
if (!anyMiniMetadata?.data) return [];
|
|
2426
|
-
const dynamicInfos = await fetchRuntimeCallResult(connector, networkId, anyMiniMetadata.data, "SubnetInfoRuntimeApi", "get_all_dynamic_info", []);
|
|
2426
|
+
const [transferableTokensMap, dynamicInfos] = await Promise.all([fetchTransferableTokensMap(connector, anyMiniMetadata.data, networkId), fetchRuntimeCallResult(connector, networkId, anyMiniMetadata.data, "SubnetInfoRuntimeApi", "get_all_dynamic_info", [])]);
|
|
2427
2427
|
return dynamicInfos.filter(isNotNil).map(info => {
|
|
2428
2428
|
const config = tokens.find(t => t.netuid === info.netuid);
|
|
2429
2429
|
let symbol = new TextDecoder().decode(Uint8Array.from(info.token_symbol));
|
|
@@ -2432,7 +2432,10 @@ const fetchTokens$5 = async ({
|
|
|
2432
2432
|
|
|
2433
2433
|
// for root we want same symbol as native so they can be grouped together in portfolio
|
|
2434
2434
|
if (info.netuid === 0 && NATIVE_TOKEN_SYMBOLS[networkId]) symbol = NATIVE_TOKEN_SYMBOLS[networkId];
|
|
2435
|
-
|
|
2435
|
+
|
|
2436
|
+
// if not stage in storage, consider transferable
|
|
2437
|
+
const isTransferable = transferableTokensMap[info.netuid] ?? true;
|
|
2438
|
+
const token = {
|
|
2436
2439
|
id: subDTaoTokenId(networkId, info.netuid),
|
|
2437
2440
|
type: MODULE_TYPE$5,
|
|
2438
2441
|
platform: PLATFORM$5,
|
|
@@ -2442,13 +2445,29 @@ const fetchTokens$5 = async ({
|
|
|
2442
2445
|
symbol,
|
|
2443
2446
|
decimals: 9,
|
|
2444
2447
|
name,
|
|
2445
|
-
subnetName
|
|
2446
|
-
|
|
2448
|
+
subnetName,
|
|
2449
|
+
isTransferable
|
|
2450
|
+
};
|
|
2451
|
+
return Object.assign({}, token, config);
|
|
2447
2452
|
}).filter(t => {
|
|
2448
2453
|
const parsed = SubDTaoTokenSchema.safeParse(t);
|
|
2449
2454
|
return parsed.success;
|
|
2450
2455
|
});
|
|
2451
2456
|
};
|
|
2457
|
+
const fetchTransferableTokensMap = async (connector, metadata, networkId) => {
|
|
2458
|
+
const {
|
|
2459
|
+
builder
|
|
2460
|
+
} = parseMetadataRpc(metadata);
|
|
2461
|
+
const transferToggleCodec = builder.buildStorage("SubtensorModule", "TransferToggle");
|
|
2462
|
+
const transferToggleKeys = await connector.send(networkId, "state_getKeys", [getStorageKeyPrefix("SubtensorModule", "TransferToggle")]);
|
|
2463
|
+
const transferToggleResults = await connector.send(networkId, "state_queryStorageAt", [transferToggleKeys]);
|
|
2464
|
+
const transferToggleEntries = transferToggleResults.length ? transferToggleResults[0].changes : [];
|
|
2465
|
+
return fromPairs(transferToggleEntries.map(([key, value]) => {
|
|
2466
|
+
const [netuid] = transferToggleCodec.keys.dec(key);
|
|
2467
|
+
const isTransferable = transferToggleCodec.value.dec(value);
|
|
2468
|
+
return [netuid, isTransferable];
|
|
2469
|
+
}));
|
|
2470
|
+
};
|
|
2452
2471
|
|
|
2453
2472
|
const getMiniMetadata$6 = ({
|
|
2454
2473
|
networkId,
|
|
@@ -2487,9 +2506,10 @@ const getData$4 = metadataRpc => {
|
|
|
2487
2506
|
name
|
|
2488
2507
|
}) => name === "SubtensorModule");
|
|
2489
2508
|
if (!isBittensor) return null;
|
|
2490
|
-
compactMetadata(metadata, [
|
|
2491
|
-
|
|
2492
|
-
|
|
2509
|
+
compactMetadata(metadata, [{
|
|
2510
|
+
pallet: "SubtensorModule",
|
|
2511
|
+
items: ["TransferToggle"]
|
|
2512
|
+
}], [{
|
|
2493
2513
|
runtimeApi: "StakeInfoRuntimeApi",
|
|
2494
2514
|
methods: ["get_stake_info_for_coldkeys"]
|
|
2495
2515
|
}, {
|
|
@@ -6938,7 +6958,8 @@ class BalancesProvider {
|
|
|
6938
6958
|
balances: results.flatMap(result => result.balances.map(b => isStale && b.status !== "live" ? {
|
|
6939
6959
|
...b,
|
|
6940
6960
|
status: "stale"
|
|
6941
|
-
} : b)).sort(sortByBalanceId)
|
|
6961
|
+
} : b)).sort(sortByBalanceId),
|
|
6962
|
+
failedBalanceIds: results.flatMap(result => result.failedBalanceIds)
|
|
6942
6963
|
})), distinctUntilChanged(isEqual));
|
|
6943
6964
|
}
|
|
6944
6965
|
fetchBalances(addressesByTokenId) {
|
|
@@ -6979,17 +7000,25 @@ class BalancesProvider {
|
|
|
6979
7000
|
});
|
|
6980
7001
|
return of({
|
|
6981
7002
|
status: "live",
|
|
6982
|
-
balances: []
|
|
7003
|
+
balances: [],
|
|
7004
|
+
failedBalanceIds: []
|
|
6983
7005
|
});
|
|
6984
7006
|
}
|
|
6985
7007
|
}
|
|
6986
7008
|
}));
|
|
6987
7009
|
}), map(results => {
|
|
7010
|
+
// for each balance that could not be fetched, see if we have a stored balance and return it, marked as stale
|
|
7011
|
+
const errorBalanceIds = results.flatMap(result => result.failedBalanceIds);
|
|
7012
|
+
const staleBalances = errorBalanceIds.map(balanceId => this.#storage.value.balances[balanceId]).filter(isNotNil).map(b => ({
|
|
7013
|
+
...b,
|
|
7014
|
+
status: "stale"
|
|
7015
|
+
}));
|
|
6988
7016
|
return {
|
|
6989
7017
|
status: results.some(({
|
|
6990
7018
|
status
|
|
6991
7019
|
}) => status === "initialising") ? "initialising" : "live",
|
|
6992
|
-
balances: results.flatMap(result => result.balances).sort(sortByBalanceId)
|
|
7020
|
+
balances: results.flatMap(result => result.balances).concat(staleBalances).sort(sortByBalanceId),
|
|
7021
|
+
failedBalanceIds: []
|
|
6993
7022
|
};
|
|
6994
7023
|
}), distinctUntilChanged(isEqual));
|
|
6995
7024
|
}
|
|
@@ -7001,7 +7030,8 @@ class BalancesProvider {
|
|
|
7001
7030
|
}, () => {
|
|
7002
7031
|
if (!tokensWithAddresses.length) return of({
|
|
7003
7032
|
status: "live",
|
|
7004
|
-
balances: []
|
|
7033
|
+
balances: [],
|
|
7034
|
+
failedBalanceIds: []
|
|
7005
7035
|
});
|
|
7006
7036
|
const moduleAddressesByTokenId = fromPairs(tokensWithAddresses.map(([token, addresses]) => [token.id, addresses]));
|
|
7007
7037
|
|
|
@@ -7014,7 +7044,8 @@ class BalancesProvider {
|
|
|
7014
7044
|
log.warn("[balances] no substrate connector or miniMetadata for module", mod.type);
|
|
7015
7045
|
return defer(() => of({
|
|
7016
7046
|
status: "initialising",
|
|
7017
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7047
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7048
|
+
failedBalanceIds: []
|
|
7018
7049
|
}));
|
|
7019
7050
|
}
|
|
7020
7051
|
const moduleBalances$ = this.getNetworkMiniMetadatas$(networkId).pipe(map(miniMetadatas => miniMetadatas.find(m => m.source === mod.type)), switchMap(miniMetadata => mod.subscribeBalances({
|
|
@@ -7032,7 +7063,14 @@ class BalancesProvider {
|
|
|
7032
7063
|
}), map(results => ({
|
|
7033
7064
|
status: "live",
|
|
7034
7065
|
// exclude zero balances
|
|
7035
|
-
balances: results.success.filter(b => new Balance(b).total.planck > 0n)
|
|
7066
|
+
balances: results.success.filter(b => new Balance(b).total.planck > 0n),
|
|
7067
|
+
failedBalanceIds: results.errors.map(({
|
|
7068
|
+
tokenId,
|
|
7069
|
+
address
|
|
7070
|
+
}) => getBalanceId({
|
|
7071
|
+
tokenId,
|
|
7072
|
+
address
|
|
7073
|
+
}))
|
|
7036
7074
|
})), tap(results => {
|
|
7037
7075
|
this.updateStorage$(balanceIds, results);
|
|
7038
7076
|
}),
|
|
@@ -7045,7 +7083,8 @@ class BalancesProvider {
|
|
|
7045
7083
|
// defer the startWith call to start with up to date balances each time the observable is re-subscribed to
|
|
7046
7084
|
return defer(() => moduleBalances$.pipe(startWith({
|
|
7047
7085
|
status: "initialising",
|
|
7048
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7086
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7087
|
+
failedBalanceIds: []
|
|
7049
7088
|
})));
|
|
7050
7089
|
});
|
|
7051
7090
|
}
|
|
@@ -7057,7 +7096,8 @@ class BalancesProvider {
|
|
|
7057
7096
|
}, () => {
|
|
7058
7097
|
if (!tokensWithAddresses.length) return of({
|
|
7059
7098
|
status: "live",
|
|
7060
|
-
balances: []
|
|
7099
|
+
balances: [],
|
|
7100
|
+
failedBalanceIds: []
|
|
7061
7101
|
});
|
|
7062
7102
|
const moduleAddressesByTokenId = fromPairs(tokensWithAddresses.map(([token, addresses]) => [token.id, addresses]));
|
|
7063
7103
|
|
|
@@ -7070,7 +7110,8 @@ class BalancesProvider {
|
|
|
7070
7110
|
log.warn("[balances] no ethereum connector for module", mod.type);
|
|
7071
7111
|
return defer(() => of({
|
|
7072
7112
|
status: "initialising",
|
|
7073
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7113
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7114
|
+
failedBalanceIds: []
|
|
7074
7115
|
}));
|
|
7075
7116
|
}
|
|
7076
7117
|
const moduleBalances$ = mod.subscribeBalances({
|
|
@@ -7082,7 +7123,14 @@ class BalancesProvider {
|
|
|
7082
7123
|
map(results => ({
|
|
7083
7124
|
status: "live",
|
|
7084
7125
|
// exclude zero balances
|
|
7085
|
-
balances: results.success.filter(b => new Balance(b).total.planck > 0n)
|
|
7126
|
+
balances: results.success.filter(b => new Balance(b).total.planck > 0n),
|
|
7127
|
+
failedBalanceIds: results.errors.map(({
|
|
7128
|
+
tokenId,
|
|
7129
|
+
address
|
|
7130
|
+
}) => getBalanceId({
|
|
7131
|
+
tokenId,
|
|
7132
|
+
address
|
|
7133
|
+
}))
|
|
7086
7134
|
})), tap(results => {
|
|
7087
7135
|
this.updateStorage$(balanceIds, results);
|
|
7088
7136
|
}),
|
|
@@ -7095,7 +7143,8 @@ class BalancesProvider {
|
|
|
7095
7143
|
// defer the startWith call to start with up to date balances each time the observable is re-subscribed to
|
|
7096
7144
|
return defer(() => moduleBalances$.pipe(startWith({
|
|
7097
7145
|
status: "initialising",
|
|
7098
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7146
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7147
|
+
failedBalanceIds: []
|
|
7099
7148
|
})));
|
|
7100
7149
|
});
|
|
7101
7150
|
}
|
|
@@ -7107,7 +7156,8 @@ class BalancesProvider {
|
|
|
7107
7156
|
}, () => {
|
|
7108
7157
|
if (!tokensWithAddresses.length) return of({
|
|
7109
7158
|
status: "live",
|
|
7110
|
-
balances: []
|
|
7159
|
+
balances: [],
|
|
7160
|
+
failedBalanceIds: []
|
|
7111
7161
|
});
|
|
7112
7162
|
const moduleAddressesByTokenId = fromPairs(tokensWithAddresses.map(([token, addresses]) => [token.id, addresses]));
|
|
7113
7163
|
|
|
@@ -7120,7 +7170,8 @@ class BalancesProvider {
|
|
|
7120
7170
|
log.warn("[balances] no solana connector for module", mod.type);
|
|
7121
7171
|
return defer(() => of({
|
|
7122
7172
|
status: "initialising",
|
|
7123
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7173
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7174
|
+
failedBalanceIds: []
|
|
7124
7175
|
}));
|
|
7125
7176
|
}
|
|
7126
7177
|
const moduleBalances$ = mod.subscribeBalances({
|
|
@@ -7132,7 +7183,14 @@ class BalancesProvider {
|
|
|
7132
7183
|
map(results => ({
|
|
7133
7184
|
status: "live",
|
|
7134
7185
|
// exclude zero balances
|
|
7135
|
-
balances: results.success.filter(b => new Balance(b).total.planck > 0n)
|
|
7186
|
+
balances: results.success.filter(b => new Balance(b).total.planck > 0n),
|
|
7187
|
+
failedBalanceIds: results.errors.map(({
|
|
7188
|
+
tokenId,
|
|
7189
|
+
address
|
|
7190
|
+
}) => getBalanceId({
|
|
7191
|
+
tokenId,
|
|
7192
|
+
address
|
|
7193
|
+
}))
|
|
7136
7194
|
})), tap(results => {
|
|
7137
7195
|
this.updateStorage$(balanceIds, results);
|
|
7138
7196
|
}),
|
|
@@ -7145,7 +7203,8 @@ class BalancesProvider {
|
|
|
7145
7203
|
// defer the startWith call to start with up to date balances each time the observable is re-subscribed to
|
|
7146
7204
|
return defer(() => moduleBalances$.pipe(startWith({
|
|
7147
7205
|
status: "initialising",
|
|
7148
|
-
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
|
7206
|
+
balances: this.getStoredBalances(moduleAddressesByTokenId),
|
|
7207
|
+
failedBalanceIds: []
|
|
7149
7208
|
})));
|
|
7150
7209
|
});
|
|
7151
7210
|
}
|
|
@@ -7153,13 +7212,19 @@ class BalancesProvider {
|
|
|
7153
7212
|
if (balancesResult.status !== "live") return;
|
|
7154
7213
|
const storage = this.#storage.getValue();
|
|
7155
7214
|
const balances = assign({}, storage.balances,
|
|
7156
|
-
// delete all balances expected in the result set. because if they are not present it means they are empty.
|
|
7157
|
-
fromPairs(balanceIds.map(balanceId => [balanceId, undefined])), keyBy(
|
|
7215
|
+
// delete all balances expected in the result set (except the ones that failed). because if they are not present it means they are empty.
|
|
7216
|
+
fromPairs(balanceIds.filter(bid => !balancesResult.failedBalanceIds.includes(bid)).map(balanceId => [balanceId, undefined])), keyBy(
|
|
7158
7217
|
// storage balances must have status "cache", because they are used as start value when initialising subsequent subscriptions
|
|
7159
7218
|
balancesResult.balances.map(b => ({
|
|
7160
7219
|
...b,
|
|
7161
7220
|
status: "cache"
|
|
7162
7221
|
})), b => getBalanceId(b)));
|
|
7222
|
+
|
|
7223
|
+
// update status of stale balances
|
|
7224
|
+
for (const errorBalanceId of balancesResult.failedBalanceIds) {
|
|
7225
|
+
const balance = balances[errorBalanceId];
|
|
7226
|
+
if (balance) balance.status = "stale";
|
|
7227
|
+
}
|
|
7163
7228
|
this.#storage.next(assign({}, storage, {
|
|
7164
7229
|
balances
|
|
7165
7230
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@talismn/balances",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
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/chain-connectors": "0.0.
|
|
42
|
-
"@talismn/
|
|
43
|
-
"@talismn/chaindata-provider": "1.2.0",
|
|
41
|
+
"@talismn/chain-connectors": "0.0.10",
|
|
42
|
+
"@talismn/chaindata-provider": "1.3.1",
|
|
44
43
|
"@talismn/scale": "0.2.2",
|
|
44
|
+
"@talismn/solana": "0.0.4",
|
|
45
|
+
"@talismn/crypto": "0.2.3",
|
|
45
46
|
"@talismn/sapi": "0.0.12",
|
|
46
|
-
"@talismn/token-rates": "3.0.
|
|
47
|
-
"@talismn/
|
|
48
|
-
"@talismn/util": "0.5.5"
|
|
47
|
+
"@talismn/token-rates": "3.0.12",
|
|
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/tsconfig": "0.0.3",
|
|
64
|
+
"@talismn/eslint-config": "0.0.3"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"@polkadot/api-contract": "*",
|