@talismn/balances 0.3.3 → 0.4.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.
- package/CHANGELOG.md +38 -0
- package/dist/declarations/src/BalanceModule.d.ts +41 -19
- package/dist/declarations/src/helpers.d.ts +67 -14
- package/dist/declarations/src/types/balances.d.ts +49 -2
- package/dist/declarations/src/types/balancetypes.d.ts +9 -1
- package/dist/talismn-balances.cjs.dev.js +371 -108
- package/dist/talismn-balances.cjs.prod.js +371 -108
- package/dist/talismn-balances.esm.js +363 -109
- package/package.json +15 -15
@@ -4,19 +4,14 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
5
5
|
var dexie = require('dexie');
|
6
6
|
var types = require('@polkadot/types');
|
7
|
-
var anylogger = require('anylogger');
|
8
7
|
var util = require('@talismn/util');
|
9
|
-
var
|
10
|
-
var
|
8
|
+
var groupBy = require('lodash/groupBy');
|
9
|
+
var anylogger = require('anylogger');
|
11
10
|
|
12
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
13
12
|
|
13
|
+
var groupBy__default = /*#__PURE__*/_interopDefault(groupBy);
|
14
14
|
var anylogger__default = /*#__PURE__*/_interopDefault(anylogger);
|
15
|
-
var memoize__default = /*#__PURE__*/_interopDefault(memoize);
|
16
|
-
|
17
|
-
//
|
18
|
-
// exported
|
19
|
-
//
|
20
15
|
|
21
16
|
// TODO: Document default balances module purpose/usage
|
22
17
|
const DefaultBalanceModule = type => ({
|
@@ -35,12 +30,15 @@ const DefaultBalanceModule = type => ({
|
|
35
30
|
async fetchEvmChainTokens() {
|
36
31
|
return Promise.resolve({});
|
37
32
|
},
|
38
|
-
async subscribeBalances(
|
33
|
+
async subscribeBalances(_, callback) {
|
39
34
|
callback(new Error("Balance subscriptions are not implemented in this module."));
|
40
35
|
return () => {};
|
41
36
|
},
|
42
37
|
async fetchBalances() {
|
43
38
|
throw new Error("Balance fetching is not implemented in this module.");
|
39
|
+
},
|
40
|
+
async transferToken() {
|
41
|
+
throw new Error("Token transfers are not implemented in this module.");
|
44
42
|
}
|
45
43
|
});
|
46
44
|
|
@@ -71,7 +69,7 @@ const db = new TalismanBalancesDatabase();
|
|
71
69
|
|
72
70
|
var packageJson = {
|
73
71
|
name: "@talismn/balances",
|
74
|
-
version: "0.
|
72
|
+
version: "0.4.1",
|
75
73
|
author: "Talisman",
|
76
74
|
homepage: "https://talisman.xyz",
|
77
75
|
license: "UNLICENSED",
|
@@ -90,36 +88,36 @@ var packageJson = {
|
|
90
88
|
"/plugins"
|
91
89
|
],
|
92
90
|
engines: {
|
93
|
-
node: ">=
|
91
|
+
node: ">=18"
|
94
92
|
},
|
95
93
|
scripts: {
|
96
94
|
test: "jest",
|
97
|
-
lint: "eslint
|
95
|
+
lint: "eslint src --max-warnings 0",
|
98
96
|
clean: "rm -rf dist && rm -rf .turbo rm -rf node_modules"
|
99
97
|
},
|
100
98
|
dependencies: {
|
101
|
-
"@talismn/chain-connector": "workspace
|
102
|
-
"@talismn/chain-connector-evm": "workspace
|
103
|
-
"@talismn/chaindata-provider": "workspace
|
104
|
-
"@talismn/token-rates": "workspace
|
105
|
-
"@talismn/util": "workspace
|
99
|
+
"@talismn/chain-connector": "workspace:*",
|
100
|
+
"@talismn/chain-connector-evm": "workspace:*",
|
101
|
+
"@talismn/chaindata-provider": "workspace:*",
|
102
|
+
"@talismn/token-rates": "workspace:*",
|
103
|
+
"@talismn/util": "workspace:*",
|
106
104
|
anylogger: "^1.0.11",
|
107
|
-
dexie: "^3.2.
|
108
|
-
lodash: "
|
109
|
-
"typescript-memoize": "^1.1.0"
|
105
|
+
dexie: "^3.2.3",
|
106
|
+
lodash: "4.17.21"
|
110
107
|
},
|
111
108
|
devDependencies: {
|
112
|
-
"@polkadot/types": "^
|
113
|
-
"@talismn/eslint-config": "workspace
|
114
|
-
"@talismn/tsconfig": "workspace
|
109
|
+
"@polkadot/types": "^10.1.4",
|
110
|
+
"@talismn/eslint-config": "workspace:*",
|
111
|
+
"@talismn/tsconfig": "workspace:*",
|
115
112
|
"@types/jest": "^27.5.1",
|
113
|
+
"@types/lodash": "^4.14.180",
|
116
114
|
eslint: "^8.4.0",
|
117
115
|
jest: "^28.1.0",
|
118
116
|
"ts-jest": "^28.0.2",
|
119
117
|
typescript: "^4.6.4"
|
120
118
|
},
|
121
119
|
peerDependencies: {
|
122
|
-
"@polkadot/types": "
|
120
|
+
"@polkadot/types": "10.x"
|
123
121
|
},
|
124
122
|
preconstruct: {
|
125
123
|
entrypoints: [
|
@@ -137,18 +135,114 @@ var packageJson = {
|
|
137
135
|
|
138
136
|
var log = anylogger__default["default"](packageJson.name);
|
139
137
|
|
140
|
-
|
138
|
+
/**
|
139
|
+
* Wraps a BalanceModule's fetch/subscribe methods with a single `balances` method.
|
140
|
+
* This `balances` method will subscribe if a callback parameter is provided, or otherwise fetch.
|
141
|
+
*/
|
142
|
+
|
143
|
+
async function balances(balanceModule, addressesByToken, callback) {
|
141
144
|
// subscription request
|
142
|
-
if (callback !== undefined) return await balanceModule.subscribeBalances(
|
145
|
+
if (callback !== undefined) return await balanceModule.subscribeBalances(addressesByToken, callback);
|
143
146
|
|
144
147
|
// one-off request
|
145
|
-
return await balanceModule.fetchBalances(
|
148
|
+
return await balanceModule.fetchBalances(addressesByToken);
|
146
149
|
}
|
150
|
+
const createTypeRegistryCache = () => {
|
151
|
+
const typeRegistryCache = new Map();
|
152
|
+
const getOrCreateTypeRegistry = (chainId, metadataRpc) => {
|
153
|
+
// TODO: Delete cache when metadataRpc is different from last time
|
154
|
+
const cached = typeRegistryCache.get(chainId);
|
155
|
+
if (cached) return cached;
|
156
|
+
const typeRegistry = new types.TypeRegistry();
|
157
|
+
if (typeof metadataRpc === "string") {
|
158
|
+
try {
|
159
|
+
const metadata = new types.Metadata(typeRegistry, metadataRpc);
|
160
|
+
metadata.registry.setMetadata(metadata);
|
161
|
+
} catch (cause) {
|
162
|
+
log.warn(new Error(`Failed to set metadata for chain ${chainId}`, {
|
163
|
+
cause
|
164
|
+
}), cause);
|
165
|
+
}
|
166
|
+
}
|
167
|
+
typeRegistryCache.set(chainId, typeRegistry);
|
168
|
+
return typeRegistry;
|
169
|
+
};
|
170
|
+
return {
|
171
|
+
getOrCreateTypeRegistry
|
172
|
+
};
|
173
|
+
};
|
174
|
+
|
175
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
176
|
+
|
177
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
178
|
+
|
179
|
+
/**
|
180
|
+
* The following `Infer*` collection of generic types can be used when you want to
|
181
|
+
* extract one of the generic type arguments from an existing BalanceModule.
|
182
|
+
*
|
183
|
+
* For example, you might want to write a function which can accept any BalanceModule
|
184
|
+
* as an input, and then return the specific TokenType for that module:
|
185
|
+
* function getTokens<T extends AnyBalanceModule>(module: T): InferTokenType<T>
|
186
|
+
*
|
187
|
+
* Or for another example, you might want a function which can take any BalanceModule `type`
|
188
|
+
* string as input, and then return some data associated with that module with the correct type:
|
189
|
+
* function getChainMeta<T extends AnyBalanceModule>(type: InferModuleType<T>): InferChainMeta<T> | undefined
|
190
|
+
*/
|
191
|
+
|
192
|
+
/**
|
193
|
+
* Given a `moduleType` and a `chain` from a chaindataProvider, this function will find the chainMeta
|
194
|
+
* associated with the given balanceModule for the given chain.
|
195
|
+
*/
|
196
|
+
const findChainMeta = (moduleType, chain) => {
|
197
|
+
return (chain?.balanceMetadata ?? []).find(meta => meta.moduleType === moduleType)?.metadata;
|
198
|
+
};
|
147
199
|
const filterMirrorTokens = (balance, i, balances) => {
|
148
|
-
// TODO implement a mirrorOf property, which should be set from chaindata
|
149
200
|
const mirrorOf = balance.token?.mirrorOf;
|
150
201
|
return !mirrorOf || !balances.find(b => b.tokenId === mirrorOf);
|
151
202
|
};
|
203
|
+
const getValidSubscriptionIds = () => {
|
204
|
+
return new Set(localStorage.getItem("TalismanBalancesSubscriptionIds")?.split(",") ?? []);
|
205
|
+
};
|
206
|
+
const createSubscriptionId = () => {
|
207
|
+
// delete current id (if exists)
|
208
|
+
deleteSubscriptionId();
|
209
|
+
|
210
|
+
// create new id
|
211
|
+
const subscriptionId = Date.now().toString();
|
212
|
+
sessionStorage.setItem("TalismanBalancesSubscriptionId", subscriptionId);
|
213
|
+
|
214
|
+
// add to list of current ids
|
215
|
+
const subscriptionIds = getValidSubscriptionIds();
|
216
|
+
subscriptionIds.add(subscriptionId);
|
217
|
+
localStorage.setItem("TalismanBalancesSubscriptionIds", [...subscriptionIds].filter(Boolean).join(","));
|
218
|
+
return subscriptionId;
|
219
|
+
};
|
220
|
+
const deleteSubscriptionId = () => {
|
221
|
+
const subscriptionId = sessionStorage.getItem("TalismanBalancesSubscriptionId");
|
222
|
+
if (!subscriptionId) return;
|
223
|
+
const subscriptionIds = getValidSubscriptionIds();
|
224
|
+
subscriptionIds.delete(subscriptionId);
|
225
|
+
localStorage.setItem("TalismanBalancesSubscriptionIds", [...subscriptionIds].filter(Boolean).join(","));
|
226
|
+
};
|
227
|
+
|
228
|
+
/**
|
229
|
+
* Sets all balance statuses from `live-${string}` to either `live` or `cached`
|
230
|
+
*/
|
231
|
+
const deriveStatuses = (validSubscriptionIds, balances) => balances.map(balance => {
|
232
|
+
if (balance.status === "live" || balance.status === "cache" || balance.status === "stale") return balance;
|
233
|
+
if (validSubscriptionIds.length < 1) return {
|
234
|
+
...balance,
|
235
|
+
status: "cache"
|
236
|
+
};
|
237
|
+
if (!validSubscriptionIds.includes(balance.status.slice("live-".length))) return {
|
238
|
+
...balance,
|
239
|
+
status: "cache"
|
240
|
+
};
|
241
|
+
return {
|
242
|
+
...balance,
|
243
|
+
status: "live"
|
244
|
+
};
|
245
|
+
});
|
152
246
|
|
153
247
|
/**
|
154
248
|
* Used by a variety of balance modules to help encode and decode substrate state calls.
|
@@ -159,7 +253,11 @@ class StorageHelper {
|
|
159
253
|
#module;
|
160
254
|
#method;
|
161
255
|
#parameters;
|
256
|
+
|
257
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
162
258
|
tags = null;
|
259
|
+
|
260
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
163
261
|
constructor(registry, module, method, ...parameters) {
|
164
262
|
this.#registry = registry;
|
165
263
|
this.#module = module;
|
@@ -193,6 +291,8 @@ class StorageHelper {
|
|
193
291
|
get parameters() {
|
194
292
|
return this.#parameters;
|
195
293
|
}
|
294
|
+
|
295
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
196
296
|
tag(tags) {
|
197
297
|
this.tags = tags;
|
198
298
|
return this;
|
@@ -231,34 +331,106 @@ class StorageHelper {
|
|
231
331
|
}
|
232
332
|
}
|
233
333
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
334
|
+
/**
|
335
|
+
* Pass some these into an `RpcStateQueryHelper` in order to easily batch multiple state queries into the one rpc call.
|
336
|
+
*/
|
337
|
+
|
338
|
+
/**
|
339
|
+
* Used by a variety of balance modules to help batch multiple state queries into the one rpc call.
|
340
|
+
*/
|
341
|
+
class RpcStateQueryHelper {
|
342
|
+
#chainConnector;
|
343
|
+
#queries;
|
344
|
+
constructor(chainConnector, queries) {
|
345
|
+
this.#chainConnector = chainConnector;
|
346
|
+
this.#queries = queries;
|
347
|
+
}
|
348
|
+
async subscribe(callback, timeout = false, subscribeMethod = "state_subscribeStorage", responseMethod = "state_storage", unsubscribeMethod = "state_unsubscribeStorage") {
|
349
|
+
const queriesByChain = groupBy__default["default"](this.#queries, "chainId");
|
350
|
+
const subscriptions = Object.entries(queriesByChain).map(([chainId, queries]) => {
|
351
|
+
const params = [queries.map(({
|
352
|
+
stateKey
|
353
|
+
}) => stateKey)];
|
354
|
+
const unsub = this.#chainConnector.subscribe(chainId, subscribeMethod, responseMethod, params, (error, result) => {
|
355
|
+
error ? callback(error) : callback(null, this.#distributeChangesToQueryDecoders.call(this, chainId, result));
|
356
|
+
}, timeout);
|
357
|
+
return () => unsub.then(unsubscribe => unsubscribe(unsubscribeMethod));
|
358
|
+
});
|
359
|
+
return () => subscriptions.forEach(unsubscribe => unsubscribe());
|
360
|
+
}
|
361
|
+
async fetch(method = "state_queryStorageAt") {
|
362
|
+
const queriesByChain = groupBy__default["default"](this.#queries, "chainId");
|
363
|
+
const resultsByChain = await Promise.all(Object.entries(queriesByChain).map(async ([chainId, queries]) => {
|
364
|
+
const params = [queries.map(({
|
365
|
+
stateKey
|
366
|
+
}) => stateKey)];
|
367
|
+
const result = (await this.#chainConnector.send(chainId, method, params))[0];
|
368
|
+
return this.#distributeChangesToQueryDecoders.call(this, chainId, result);
|
369
|
+
}));
|
370
|
+
return resultsByChain.flatMap(result => result);
|
371
|
+
}
|
372
|
+
#distributeChangesToQueryDecoders(chainId, result) {
|
373
|
+
if (typeof result !== "object" || result === null) return [];
|
374
|
+
if (!util.hasOwnProperty(result, "changes") || typeof result.changes !== "object") return [];
|
375
|
+
if (!Array.isArray(result.changes)) return [];
|
376
|
+
return result.changes.flatMap(([reference, change]) => {
|
377
|
+
if (typeof reference !== "string") {
|
378
|
+
log.warn(`Received non-string reference in RPC result: ${reference}`);
|
379
|
+
return [];
|
380
|
+
}
|
381
|
+
if (typeof change !== "string" && change !== null) {
|
382
|
+
log.warn(`Received non-string and non-null change in RPC result: ${reference} | ${change}`);
|
383
|
+
return [];
|
384
|
+
}
|
385
|
+
const query = this.#queries.find(({
|
386
|
+
chainId: cId,
|
387
|
+
stateKey
|
388
|
+
}) => cId === chainId && stateKey === reference);
|
389
|
+
if (!query) {
|
390
|
+
log.warn(`Failed to find query:\n${reference} in\n${this.#queries.map(({
|
391
|
+
stateKey
|
392
|
+
}) => stateKey)}`);
|
393
|
+
return [];
|
394
|
+
}
|
395
|
+
return [query.decodeResult(change)];
|
396
|
+
});
|
397
|
+
}
|
256
398
|
}
|
257
399
|
|
400
|
+
/**
|
401
|
+
* `BalanceTypes` is an automatically determined sub-selection of `PluginBalanceTypes`.
|
402
|
+
*
|
403
|
+
* It is the same list, but with any invalid `BalanceType` definitions filtered out.
|
404
|
+
*/
|
405
|
+
|
406
|
+
/**
|
407
|
+
* The `BalanceJson` sum type, which is a union of all of the possible `BalanceTypes`.
|
408
|
+
*
|
409
|
+
* Each variant comes from a plugin in use by the consuming app.
|
410
|
+
*
|
411
|
+
* For example, in an app with the `substrate-native`, `evm-native`, `substrate-orml` and `evm-erc20` plugins:
|
412
|
+
*
|
413
|
+
* type BalanceJson = SubNativeBalance | EvmNativeBalance | SubOrmlBalance | EvmErc20Balance
|
414
|
+
*
|
415
|
+
* If `BalanceTypes` is empty then `BalanceJson` will fall back to the common `IBalance` interface, which every balance must implement.
|
416
|
+
*/
|
417
|
+
|
418
|
+
/** A collection of `BalanceJson` objects */
|
419
|
+
|
420
|
+
const BalanceStatusLive = subscriptionId => `live-${subscriptionId}`;
|
421
|
+
|
422
|
+
/** `IBalance` is a common interface which all balance types must implement. */
|
423
|
+
|
424
|
+
/** An unlabelled amount of a balance */
|
425
|
+
|
426
|
+
/** A labelled amount of a balance */
|
427
|
+
|
428
|
+
/** A labelled locked amount of a balance */
|
429
|
+
|
258
430
|
function excludeFromTransferableAmount(locks) {
|
259
431
|
if (typeof locks === "string") return BigInt(locks);
|
260
432
|
if (!Array.isArray(locks)) locks = [locks];
|
261
|
-
return locks.filter(lock => lock.includeInTransferable !== true).map(lock => BigInt(lock.amount)).reduce((max, lock) => util.BigMath.max(max, lock),
|
433
|
+
return locks.filter(lock => lock.includeInTransferable !== true).map(lock => BigInt(lock.amount)).reduce((max, lock) => util.BigMath.max(max, lock), 0n);
|
262
434
|
}
|
263
435
|
function excludeFromFeePayableLocks(locks) {
|
264
436
|
if (typeof locks === "string") return [];
|
@@ -269,31 +441,29 @@ function excludeFromFeePayableLocks(locks) {
|
|
269
441
|
/** A labelled extra amount of a balance */
|
270
442
|
|
271
443
|
function includeInTotalExtraAmount(extra) {
|
272
|
-
if (!extra) return
|
444
|
+
if (!extra) return 0n;
|
273
445
|
if (!Array.isArray(extra)) extra = [extra];
|
274
|
-
return extra.filter(extra => extra.includeInTotal).map(extra => BigInt(extra.amount)).reduce((a, b) => a + b,
|
446
|
+
return extra.filter(extra => extra.includeInTotal).map(extra => BigInt(extra.amount)).reduce((a, b) => a + b, 0n);
|
275
447
|
}
|
276
448
|
|
277
449
|
/** Used by plugins to help define their custom `BalanceType` */
|
278
450
|
|
279
|
-
var _dec, _dec2, _dec3, _class, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _dec10, _class2, _dec11, _class3, _dec12, _dec13, _dec14, _dec15, _dec16, _dec17, _dec18, _class4;
|
280
|
-
|
281
451
|
/**
|
282
452
|
* Have the importing library define its Token and BalanceJson enums (as a sum type of all plugins) and pass them into some
|
283
453
|
* internal global typescript context, which is then picked up on by this module.
|
284
454
|
*/
|
285
455
|
|
286
456
|
/** A utility type used to extract the underlying `BalanceType` of a specific source from a generalised `BalanceJson` */
|
287
|
-
|
457
|
+
/** TODO: Remove this in favour of a frontend-friendly `ChaindataProvider` */
|
288
458
|
/**
|
289
459
|
* A collection of balances.
|
290
460
|
*/
|
291
|
-
|
461
|
+
class Balances {
|
292
462
|
//
|
293
463
|
// Properties
|
294
464
|
//
|
295
465
|
|
296
|
-
#balances =
|
466
|
+
#balances = [];
|
297
467
|
|
298
468
|
//
|
299
469
|
// Methods
|
@@ -301,7 +471,7 @@ let Balances = (_dec = typescriptMemoize.Memoize(), _dec2 = typescriptMemoize.Me
|
|
301
471
|
|
302
472
|
constructor(balances, hydrate) {
|
303
473
|
// handle Balances (convert to Balance[])
|
304
|
-
if (balances instanceof Balances) return new Balances(
|
474
|
+
if (balances instanceof Balances) return new Balances(balances.each, hydrate);
|
305
475
|
|
306
476
|
// handle Balance (convert to Balance[])
|
307
477
|
if (balances instanceof Balance) return new Balances([balances], hydrate);
|
@@ -316,19 +486,19 @@ let Balances = (_dec = typescriptMemoize.Memoize(), _dec2 = typescriptMemoize.Me
|
|
316
486
|
if (!util.isArrayOf(balances, Balance)) return new Balances(balances.map(storage => new Balance(storage)), hydrate);
|
317
487
|
|
318
488
|
// handle Balance[]
|
319
|
-
this.#balances =
|
489
|
+
this.#balances = balances;
|
320
490
|
if (hydrate !== undefined) this.hydrate(hydrate);
|
321
491
|
}
|
322
492
|
|
323
493
|
/**
|
324
494
|
* Calling toJSON on a collection of balances will return the underlying BalanceJsonList.
|
325
495
|
*/
|
326
|
-
toJSON = () => Object.fromEntries(
|
496
|
+
toJSON = () => Object.fromEntries(this.#balances.map(balance => {
|
327
497
|
try {
|
328
|
-
return [id, balance.toJSON()];
|
498
|
+
return [balance.id, balance.toJSON()];
|
329
499
|
} catch (error) {
|
330
500
|
log.error("Failed to convert balance to JSON", error, {
|
331
|
-
id,
|
501
|
+
id: balance.id,
|
332
502
|
balance
|
333
503
|
});
|
334
504
|
return null;
|
@@ -348,7 +518,7 @@ let Balances = (_dec = typescriptMemoize.Memoize(), _dec2 = typescriptMemoize.Me
|
|
348
518
|
*/
|
349
519
|
[Symbol.iterator] = () =>
|
350
520
|
// Create an array of the balances in this collection and return the result of its iterator.
|
351
|
-
|
521
|
+
this.#balances[Symbol.iterator]();
|
352
522
|
|
353
523
|
/**
|
354
524
|
* Hydrates all balances in this collection.
|
@@ -356,7 +526,7 @@ let Balances = (_dec = typescriptMemoize.Memoize(), _dec2 = typescriptMemoize.Me
|
|
356
526
|
* @param sources - The sources to hydrate from.
|
357
527
|
*/
|
358
528
|
hydrate = sources => {
|
359
|
-
|
529
|
+
this.#balances.map(balance => balance.hydrate(sources));
|
360
530
|
};
|
361
531
|
|
362
532
|
/**
|
@@ -365,7 +535,7 @@ let Balances = (_dec = typescriptMemoize.Memoize(), _dec2 = typescriptMemoize.Me
|
|
365
535
|
* @param id - The id of the balance to fetch.
|
366
536
|
* @returns The balance if one exists, or none.
|
367
537
|
*/
|
368
|
-
get = id => this.#balances
|
538
|
+
get = id => this.#balances.find(balance => balance.id === id) ?? null;
|
369
539
|
|
370
540
|
/**
|
371
541
|
* Retrieve balances from this collection by search query.
|
@@ -384,6 +554,27 @@ let Balances = (_dec = typescriptMemoize.Memoize(), _dec2 = typescriptMemoize.Me
|
|
384
554
|
return new Balances([...this].filter(filter));
|
385
555
|
};
|
386
556
|
|
557
|
+
/**
|
558
|
+
* Filters this collection to exclude token balances where the token has a `mirrorOf` field
|
559
|
+
* and another balance exists in this collection for the token specified by the `mirrorOf` field.
|
560
|
+
*/
|
561
|
+
filterMirrorTokens = () => new Balances([...this].filter(filterMirrorTokens));
|
562
|
+
|
563
|
+
/**
|
564
|
+
* Filters this collection to only include balances which are not zero.
|
565
|
+
*/
|
566
|
+
filterNonZero = type => {
|
567
|
+
const filter = balance => balance[type].planck > 0n;
|
568
|
+
return this.find(filter);
|
569
|
+
};
|
570
|
+
/**
|
571
|
+
* Filters this collection to only include balances which are not zero AND have a fiat conversion rate.
|
572
|
+
*/
|
573
|
+
filterNonZeroFiat = (type, currency) => {
|
574
|
+
const filter = balance => (balance[type].fiat(currency) ?? 0) > 0;
|
575
|
+
return this.find(filter);
|
576
|
+
};
|
577
|
+
|
387
578
|
/**
|
388
579
|
* Add some balances to this collection.
|
389
580
|
* Added balances take priority over existing balances.
|
@@ -398,10 +589,8 @@ let Balances = (_dec = typescriptMemoize.Memoize(), _dec2 = typescriptMemoize.Me
|
|
398
589
|
if (balances instanceof Balance) return this.add(new Balances(balances));
|
399
590
|
|
400
591
|
// merge balances
|
401
|
-
const mergedBalances =
|
402
|
-
|
403
|
-
};
|
404
|
-
[...balances].forEach(balance => mergedBalances[balance.id] = balance);
|
592
|
+
const mergedBalances = Object.fromEntries(this.#balances.map(balance => [balance.id, balance]));
|
593
|
+
balances.each.forEach(balance => mergedBalances[balance.id] = balance);
|
405
594
|
|
406
595
|
// return new balances
|
407
596
|
return new Balances(Object.values(mergedBalances));
|
@@ -419,25 +608,23 @@ let Balances = (_dec = typescriptMemoize.Memoize(), _dec2 = typescriptMemoize.Me
|
|
419
608
|
// handle single id
|
420
609
|
if (!Array.isArray(ids)) return this.remove([ids]);
|
421
610
|
|
422
|
-
// merge balances
|
423
|
-
|
424
|
-
...this.#balances
|
425
|
-
};
|
426
|
-
ids.forEach(id => delete removedBalances[id]);
|
427
|
-
|
428
|
-
// return new balances
|
429
|
-
return new Balances(Object.values(removedBalances));
|
611
|
+
// merge and return new balances
|
612
|
+
return new Balances(this.#balances.filter(balance => !ids.includes(balance.id)));
|
430
613
|
};
|
431
614
|
|
432
615
|
// TODO: Add some more useful aggregator methods
|
433
616
|
|
617
|
+
get each() {
|
618
|
+
return [...this];
|
619
|
+
}
|
620
|
+
|
434
621
|
/**
|
435
622
|
* Get an array of balances in this collection, sorted by chain sortIndex.
|
436
623
|
*
|
437
624
|
* @returns A sorted array of the balances in this collection.
|
438
625
|
*/
|
439
626
|
get sorted() {
|
440
|
-
return [...this].sort((a, b) => ((a.chain || a.evmNetwork)?.sortIndex
|
627
|
+
return [...this].sort((a, b) => ((a.chain || a.evmNetwork)?.sortIndex ?? Number.MAX_SAFE_INTEGER) - ((b.chain || b.evmNetwork)?.sortIndex ?? Number.MAX_SAFE_INTEGER));
|
441
628
|
}
|
442
629
|
|
443
630
|
/**
|
@@ -460,12 +647,12 @@ let Balances = (_dec = typescriptMemoize.Memoize(), _dec2 = typescriptMemoize.Me
|
|
460
647
|
get sum() {
|
461
648
|
return new SumBalancesFormatter(this);
|
462
649
|
}
|
463
|
-
}
|
650
|
+
}
|
464
651
|
|
465
652
|
/**
|
466
653
|
* An individual balance.
|
467
654
|
*/
|
468
|
-
|
655
|
+
class Balance {
|
469
656
|
//
|
470
657
|
// Properties
|
471
658
|
//
|
@@ -479,7 +666,6 @@ let Balance = (_dec4 = typescriptMemoize.Memoize(), _dec5 = typescriptMemoize.Me
|
|
479
666
|
//
|
480
667
|
|
481
668
|
constructor(storage, hydrate) {
|
482
|
-
this.#format = memoize__default["default"](this.#format);
|
483
669
|
this.#storage = storage;
|
484
670
|
if (hydrate !== undefined) this.hydrate(hydrate);
|
485
671
|
}
|
@@ -511,13 +697,14 @@ let Balance = (_dec4 = typescriptMemoize.Memoize(), _dec5 = typescriptMemoize.Me
|
|
511
697
|
get id() {
|
512
698
|
const {
|
513
699
|
source,
|
700
|
+
subSource,
|
514
701
|
address,
|
515
702
|
chainId,
|
516
703
|
evmNetworkId,
|
517
704
|
tokenId
|
518
705
|
} = this.#storage;
|
519
706
|
const locationId = chainId !== undefined ? chainId : evmNetworkId;
|
520
|
-
return
|
707
|
+
return [source, address, locationId, tokenId, subSource].filter(Boolean).join("-");
|
521
708
|
}
|
522
709
|
get source() {
|
523
710
|
return this.#storage.source;
|
@@ -566,17 +753,43 @@ let Balance = (_dec4 = typescriptMemoize.Memoize(), _dec5 = typescriptMemoize.Me
|
|
566
753
|
}
|
567
754
|
/** The non-reserved balance of this token. Includes the frozen amount. Is included in the total. */
|
568
755
|
get free() {
|
569
|
-
return this.#format(typeof this.#storage.free === "string" ? BigInt(this.#storage.free) : Array.isArray(this.#storage.free) ? this.#storage.free.map(reserve => BigInt(reserve.amount)).reduce((a, b) => a + b,
|
756
|
+
return this.#format(typeof this.#storage.free === "string" ? BigInt(this.#storage.free) : Array.isArray(this.#storage.free) ? this.#storage.free.map(reserve => BigInt(reserve.amount)).reduce((a, b) => a + b, 0n) : BigInt(this.#storage.free?.amount || "0"));
|
570
757
|
}
|
571
758
|
/** The reserved balance of this token. Is included in the total. */
|
572
759
|
get reserved() {
|
573
|
-
return this.#format(typeof this.#storage.reserves === "string" ? BigInt(this.#storage.reserves) : Array.isArray(this.#storage.reserves) ? this.#storage.reserves.map(reserve => BigInt(reserve.amount)).reduce((a, b) => a + b,
|
760
|
+
return this.#format(typeof this.#storage.reserves === "string" ? BigInt(this.#storage.reserves) : Array.isArray(this.#storage.reserves) ? this.#storage.reserves.map(reserve => BigInt(reserve.amount)).reduce((a, b) => a + b, 0n) : BigInt(this.#storage.reserves?.amount || "0"));
|
761
|
+
}
|
762
|
+
get reserves() {
|
763
|
+
return (Array.isArray(this.#storage.reserves) ? this.#storage.reserves : [this.#storage.reserves]).flatMap(reserve => {
|
764
|
+
if (reserve === undefined) return [];
|
765
|
+
if (typeof reserve === "string") return {
|
766
|
+
label: "reserved",
|
767
|
+
amount: this.#format(reserve)
|
768
|
+
};
|
769
|
+
return {
|
770
|
+
...reserve,
|
771
|
+
amount: this.#format(reserve.amount)
|
772
|
+
};
|
773
|
+
});
|
574
774
|
}
|
575
775
|
/** The frozen balance of this token. Is included in the free amount. */
|
576
776
|
get locked() {
|
577
|
-
return this.#format(typeof this.#storage.locks === "string" ? BigInt(this.#storage.locks) : Array.isArray(this.#storage.locks) ? this.#storage.locks.map(lock => BigInt(lock.amount)).reduce((a, b) => util.BigMath.max(a, b),
|
777
|
+
return this.#format(typeof this.#storage.locks === "string" ? BigInt(this.#storage.locks) : Array.isArray(this.#storage.locks) ? this.#storage.locks.map(lock => BigInt(lock.amount)).reduce((a, b) => util.BigMath.max(a, b), 0n) : BigInt(this.#storage.locks?.amount || "0"));
|
778
|
+
}
|
779
|
+
get locks() {
|
780
|
+
return (Array.isArray(this.#storage.locks) ? this.#storage.locks : [this.#storage.locks]).flatMap(lock => {
|
781
|
+
if (lock === undefined) return [];
|
782
|
+
if (typeof lock === "string") return {
|
783
|
+
label: "other",
|
784
|
+
amount: this.#format(lock)
|
785
|
+
};
|
786
|
+
return {
|
787
|
+
...lock,
|
788
|
+
amount: this.#format(lock.amount)
|
789
|
+
};
|
790
|
+
});
|
578
791
|
}
|
579
|
-
/** @
|
792
|
+
/** @deprecated Use balance.locked */
|
580
793
|
get frozen() {
|
581
794
|
return this.locked;
|
582
795
|
}
|
@@ -589,7 +802,7 @@ let Balance = (_dec4 = typescriptMemoize.Memoize(), _dec5 = typescriptMemoize.Me
|
|
589
802
|
const excludeAmount = excludeFromTransferableAmount(this.#storage.locks);
|
590
803
|
|
591
804
|
// subtract the lock from the free amount (but don't go below 0)
|
592
|
-
return this.#format(util.BigMath.max(this.free.planck - excludeAmount,
|
805
|
+
return this.#format(util.BigMath.max(this.free.planck - excludeAmount, 0n));
|
593
806
|
}
|
594
807
|
/** The feePayable balance of this token. Is generally the free amount - the feeFrozen amount. */
|
595
808
|
get feePayable() {
|
@@ -597,13 +810,13 @@ let Balance = (_dec4 = typescriptMemoize.Memoize(), _dec5 = typescriptMemoize.Me
|
|
597
810
|
if (!this.#storage.locks) return this.free;
|
598
811
|
|
599
812
|
// find the largest lock which can't be used to pay tx fees
|
600
|
-
const excludeAmount = excludeFromFeePayableLocks(this.#storage.locks).map(lock => BigInt(lock.amount)).reduce((max, lock) => util.BigMath.max(max, lock),
|
813
|
+
const excludeAmount = excludeFromFeePayableLocks(this.#storage.locks).map(lock => BigInt(lock.amount)).reduce((max, lock) => util.BigMath.max(max, lock), 0n);
|
601
814
|
|
602
815
|
// subtract the lock from the free amount (but don't go below 0)
|
603
|
-
return this.#format(util.BigMath.max(this.free.planck - excludeAmount,
|
816
|
+
return this.#format(util.BigMath.max(this.free.planck - excludeAmount, 0n));
|
604
817
|
}
|
605
|
-
}
|
606
|
-
|
818
|
+
}
|
819
|
+
class BalanceFormatter {
|
607
820
|
#planck;
|
608
821
|
#decimals;
|
609
822
|
#fiatRatios;
|
@@ -611,7 +824,6 @@ let BalanceFormatter = (_dec11 = typescriptMemoize.Memoize(), (_class3 = class B
|
|
611
824
|
this.#planck = typeof planck === "bigint" ? planck.toString() : planck ?? "0";
|
612
825
|
this.#decimals = decimals || 0;
|
613
826
|
this.#fiatRatios = fiatRatios || null;
|
614
|
-
this.fiat = memoize__default["default"](this.fiat);
|
615
827
|
}
|
616
828
|
toJSON = () => this.#planck;
|
617
829
|
get planck() {
|
@@ -626,26 +838,66 @@ let BalanceFormatter = (_dec11 = typescriptMemoize.Memoize(), (_class3 = class B
|
|
626
838
|
if (!ratio) return null;
|
627
839
|
return parseFloat(this.tokens) * ratio;
|
628
840
|
}
|
629
|
-
}
|
630
|
-
|
841
|
+
}
|
842
|
+
class PlanckSumBalancesFormatter {
|
843
|
+
#balances;
|
844
|
+
constructor(balances) {
|
845
|
+
this.#balances = balances;
|
846
|
+
}
|
847
|
+
#sum = balanceField => {
|
848
|
+
// a function to get a planck amount from a balance
|
849
|
+
const planck = balance => balance[balanceField].planck ?? 0n;
|
850
|
+
return this.#balances.filterMirrorTokens().each.reduce(
|
851
|
+
// add the total amount to the planck amount of each balance
|
852
|
+
(total, balance) => total + planck(balance),
|
853
|
+
// start with a total of 0
|
854
|
+
0n);
|
855
|
+
};
|
856
|
+
|
857
|
+
/**
|
858
|
+
* The total balance of these tokens. Includes the free and the reserved amount.
|
859
|
+
*/
|
860
|
+
get total() {
|
861
|
+
return this.#sum("total");
|
862
|
+
}
|
863
|
+
/** The non-reserved balance of these tokens. Includes the frozen amount. Is included in the total. */
|
864
|
+
get free() {
|
865
|
+
return this.#sum("free");
|
866
|
+
}
|
867
|
+
/** The reserved balance of these tokens. Is included in the total. */
|
868
|
+
get reserved() {
|
869
|
+
return this.#sum("reserved");
|
870
|
+
}
|
871
|
+
/** The frozen balance of these tokens. Is included in the free amount. */
|
872
|
+
get locked() {
|
873
|
+
return this.#sum("locked");
|
874
|
+
}
|
875
|
+
/** @deprecated Use balances.locked */
|
876
|
+
get frozen() {
|
877
|
+
return this.locked;
|
878
|
+
}
|
879
|
+
/** The transferable balance of these tokens. Is generally the free amount - the miscFrozen amount. */
|
880
|
+
get transferable() {
|
881
|
+
return this.#sum("transferable");
|
882
|
+
}
|
883
|
+
/** The feePayable balance of these tokens. Is generally the free amount - the feeFrozen amount. */
|
884
|
+
get feePayable() {
|
885
|
+
return this.#sum("feePayable");
|
886
|
+
}
|
887
|
+
}
|
888
|
+
class FiatSumBalancesFormatter {
|
631
889
|
#balances;
|
632
890
|
#currency;
|
633
891
|
constructor(balances, currency) {
|
634
892
|
this.#balances = balances;
|
635
893
|
this.#currency = currency;
|
636
|
-
this.#sum = memoize__default["default"](this.#sum);
|
637
894
|
}
|
638
895
|
#sum = balanceField => {
|
639
896
|
// a function to get a fiat amount from a balance
|
640
|
-
const fiat = balance => balance[balanceField].fiat(this.#currency)
|
641
|
-
|
642
|
-
//
|
643
|
-
|
644
|
-
return [...this.#balances].filter(filterMirrorTokens).reduce((total, balance) => sum(
|
645
|
-
// add the total amount...
|
646
|
-
total,
|
647
|
-
// ...to the fiat amount of each balance
|
648
|
-
fiat(balance)),
|
897
|
+
const fiat = balance => balance[balanceField].fiat(this.#currency) ?? 0;
|
898
|
+
return this.#balances.filterMirrorTokens().each.reduce(
|
899
|
+
// add the total amount to the fiat amount of each balance
|
900
|
+
(total, balance) => total + fiat(balance),
|
649
901
|
// start with a total of 0
|
650
902
|
0);
|
651
903
|
};
|
@@ -668,7 +920,7 @@ let FiatSumBalancesFormatter = (_dec12 = typescriptMemoize.Memoize(), _dec13 = t
|
|
668
920
|
get locked() {
|
669
921
|
return this.#sum("locked");
|
670
922
|
}
|
671
|
-
/** @deprecated
|
923
|
+
/** @deprecated Use balances.locked */
|
672
924
|
get frozen() {
|
673
925
|
return this.locked;
|
674
926
|
}
|
@@ -680,12 +932,14 @@ let FiatSumBalancesFormatter = (_dec12 = typescriptMemoize.Memoize(), _dec13 = t
|
|
680
932
|
get feePayable() {
|
681
933
|
return this.#sum("feePayable");
|
682
934
|
}
|
683
|
-
}
|
935
|
+
}
|
684
936
|
class SumBalancesFormatter {
|
685
937
|
#balances;
|
686
938
|
constructor(balances) {
|
687
939
|
this.#balances = balances;
|
688
|
-
|
940
|
+
}
|
941
|
+
get planck() {
|
942
|
+
return new PlanckSumBalancesFormatter(this.#balances);
|
689
943
|
}
|
690
944
|
fiat(currency) {
|
691
945
|
return new FiatSumBalancesFormatter(this.#balances, currency);
|
@@ -694,15 +948,24 @@ class SumBalancesFormatter {
|
|
694
948
|
|
695
949
|
exports.Balance = Balance;
|
696
950
|
exports.BalanceFormatter = BalanceFormatter;
|
951
|
+
exports.BalanceStatusLive = BalanceStatusLive;
|
697
952
|
exports.Balances = Balances;
|
698
953
|
exports.DefaultBalanceModule = DefaultBalanceModule;
|
699
954
|
exports.FiatSumBalancesFormatter = FiatSumBalancesFormatter;
|
955
|
+
exports.PlanckSumBalancesFormatter = PlanckSumBalancesFormatter;
|
956
|
+
exports.RpcStateQueryHelper = RpcStateQueryHelper;
|
700
957
|
exports.StorageHelper = StorageHelper;
|
701
958
|
exports.SumBalancesFormatter = SumBalancesFormatter;
|
702
959
|
exports.TalismanBalancesDatabase = TalismanBalancesDatabase;
|
703
960
|
exports.balances = balances;
|
961
|
+
exports.createSubscriptionId = createSubscriptionId;
|
962
|
+
exports.createTypeRegistryCache = createTypeRegistryCache;
|
704
963
|
exports.db = db;
|
964
|
+
exports.deleteSubscriptionId = deleteSubscriptionId;
|
965
|
+
exports.deriveStatuses = deriveStatuses;
|
705
966
|
exports.excludeFromFeePayableLocks = excludeFromFeePayableLocks;
|
706
967
|
exports.excludeFromTransferableAmount = excludeFromTransferableAmount;
|
707
968
|
exports.filterMirrorTokens = filterMirrorTokens;
|
969
|
+
exports.findChainMeta = findChainMeta;
|
970
|
+
exports.getValidSubscriptionIds = getValidSubscriptionIds;
|
708
971
|
exports.includeInTotalExtraAmount = includeInTotalExtraAmount;
|