@talismn/balances 0.0.0-pr709-20230418130154 → 0.0.0-pr716-20230419110638
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 +12 -5
- package/dist/declarations/src/helpers.d.ts +20 -1
- package/dist/declarations/src/types/balances.d.ts +48 -2
- package/dist/declarations/src/types/balancetypes.d.ts +6 -0
- package/dist/talismn-balances.cjs.dev.js +212 -36
- package/dist/talismn-balances.cjs.prod.js +212 -36
- package/dist/talismn-balances.esm.js +210 -37
- package/package.json +14 -12
@@ -4,11 +4,13 @@ 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');
|
8
|
+
var groupBy = require('lodash/groupBy');
|
9
|
+
var anylogger = require('anylogger');
|
9
10
|
|
10
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
11
12
|
|
13
|
+
var groupBy__default = /*#__PURE__*/_interopDefault(groupBy);
|
12
14
|
var anylogger__default = /*#__PURE__*/_interopDefault(anylogger);
|
13
15
|
|
14
16
|
// TODO: Document default balances module purpose/usage
|
@@ -67,7 +69,7 @@ const db = new TalismanBalancesDatabase();
|
|
67
69
|
|
68
70
|
var packageJson = {
|
69
71
|
name: "@talismn/balances",
|
70
|
-
version: "0.0.0-
|
72
|
+
version: "0.0.0-pr716-20230419110638",
|
71
73
|
author: "Talisman",
|
72
74
|
homepage: "https://talisman.xyz",
|
73
75
|
license: "UNLICENSED",
|
@@ -90,30 +92,32 @@ var packageJson = {
|
|
90
92
|
},
|
91
93
|
scripts: {
|
92
94
|
test: "jest",
|
93
|
-
lint: "eslint
|
95
|
+
lint: "eslint src --max-warnings 0",
|
94
96
|
clean: "rm -rf dist && rm -rf .turbo rm -rf node_modules"
|
95
97
|
},
|
96
98
|
dependencies: {
|
97
|
-
"@talismn/chain-connector": "workspace
|
98
|
-
"@talismn/chain-connector-evm": "workspace
|
99
|
-
"@talismn/chaindata-provider": "workspace
|
100
|
-
"@talismn/token-rates": "workspace
|
101
|
-
"@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:*",
|
102
104
|
anylogger: "^1.0.11",
|
103
|
-
dexie: "^3.2.3"
|
105
|
+
dexie: "^3.2.3",
|
106
|
+
lodash: "4.17.21"
|
104
107
|
},
|
105
108
|
devDependencies: {
|
106
|
-
"@polkadot/types": "^
|
107
|
-
"@talismn/eslint-config": "workspace
|
108
|
-
"@talismn/tsconfig": "workspace
|
109
|
+
"@polkadot/types": "^10.1.4",
|
110
|
+
"@talismn/eslint-config": "workspace:*",
|
111
|
+
"@talismn/tsconfig": "workspace:*",
|
109
112
|
"@types/jest": "^27.5.1",
|
113
|
+
"@types/lodash": "^4.14.180",
|
110
114
|
eslint: "^8.4.0",
|
111
115
|
jest: "^28.1.0",
|
112
116
|
"ts-jest": "^28.0.2",
|
113
117
|
typescript: "^4.6.4"
|
114
118
|
},
|
115
119
|
peerDependencies: {
|
116
|
-
"@polkadot/types": "
|
120
|
+
"@polkadot/types": "10.x"
|
117
121
|
},
|
118
122
|
preconstruct: {
|
119
123
|
entrypoints: [
|
@@ -146,8 +150,14 @@ const createTypeRegistryCache = () => {
|
|
146
150
|
if (cached) return cached;
|
147
151
|
const typeRegistry = new types.TypeRegistry();
|
148
152
|
if (typeof metadataRpc === "string") {
|
149
|
-
|
150
|
-
|
153
|
+
try {
|
154
|
+
const metadata = new types.Metadata(typeRegistry, metadataRpc);
|
155
|
+
metadata.registry.setMetadata(metadata);
|
156
|
+
} catch (cause) {
|
157
|
+
log.warn(new Error(`Failed to set metadata for chain ${chainId}`, {
|
158
|
+
cause
|
159
|
+
}), cause);
|
160
|
+
}
|
151
161
|
}
|
152
162
|
typeRegistryCache.set(chainId, typeRegistry);
|
153
163
|
return typeRegistry;
|
@@ -214,7 +224,11 @@ class StorageHelper {
|
|
214
224
|
#module;
|
215
225
|
#method;
|
216
226
|
#parameters;
|
227
|
+
|
228
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
217
229
|
tags = null;
|
230
|
+
|
231
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
218
232
|
constructor(registry, module, method, ...parameters) {
|
219
233
|
this.#registry = registry;
|
220
234
|
this.#module = module;
|
@@ -248,6 +262,8 @@ class StorageHelper {
|
|
248
262
|
get parameters() {
|
249
263
|
return this.#parameters;
|
250
264
|
}
|
265
|
+
|
266
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
251
267
|
tag(tags) {
|
252
268
|
this.tags = tags;
|
253
269
|
return this;
|
@@ -286,11 +302,77 @@ class StorageHelper {
|
|
286
302
|
}
|
287
303
|
}
|
288
304
|
|
305
|
+
/**
|
306
|
+
* Pass some these into an `RpcStateQueryHelper` in order to easily batch multiple state queries into the one rpc call.
|
307
|
+
*/
|
308
|
+
|
309
|
+
/**
|
310
|
+
* Used by a variety of balance modules to help batch multiple state queries into the one rpc call.
|
311
|
+
*/
|
312
|
+
class RpcStateQueryHelper {
|
313
|
+
#chainConnector;
|
314
|
+
#queries;
|
315
|
+
constructor(chainConnector, queries) {
|
316
|
+
this.#chainConnector = chainConnector;
|
317
|
+
this.#queries = queries;
|
318
|
+
}
|
319
|
+
async subscribe(callback, timeout = false, subscribeMethod = "state_subscribeStorage", responseMethod = "state_storage", unsubscribeMethod = "state_unsubscribeStorage") {
|
320
|
+
const queriesByChain = groupBy__default["default"](this.#queries, "chainId");
|
321
|
+
const subscriptions = Object.entries(queriesByChain).map(([chainId, queries]) => {
|
322
|
+
const params = [queries.map(({
|
323
|
+
stateKey
|
324
|
+
}) => stateKey)];
|
325
|
+
const unsub = this.#chainConnector.subscribe(chainId, subscribeMethod, responseMethod, params, (error, result) => {
|
326
|
+
error ? callback(error) : callback(null, this.#distributeChangesToQueryDecoders.call(this, chainId, result));
|
327
|
+
}, timeout);
|
328
|
+
return () => unsub.then(unsubscribe => unsubscribe(unsubscribeMethod));
|
329
|
+
});
|
330
|
+
return () => subscriptions.forEach(unsubscribe => unsubscribe());
|
331
|
+
}
|
332
|
+
async fetch(method = "state_queryStorageAt") {
|
333
|
+
const queriesByChain = groupBy__default["default"](this.#queries, "chainId");
|
334
|
+
const resultsByChain = await Promise.all(Object.entries(queriesByChain).map(async ([chainId, queries]) => {
|
335
|
+
const params = [queries.map(({
|
336
|
+
stateKey
|
337
|
+
}) => stateKey)];
|
338
|
+
const result = (await this.#chainConnector.send(chainId, method, params))[0];
|
339
|
+
return this.#distributeChangesToQueryDecoders.call(this, chainId, result);
|
340
|
+
}));
|
341
|
+
return resultsByChain.flatMap(result => result);
|
342
|
+
}
|
343
|
+
#distributeChangesToQueryDecoders(chainId, result) {
|
344
|
+
if (typeof result !== "object" || result === null) return [];
|
345
|
+
if (!util.hasOwnProperty(result, "changes") || typeof result.changes !== "object") return [];
|
346
|
+
if (!Array.isArray(result.changes)) return [];
|
347
|
+
return result.changes.flatMap(([reference, change]) => {
|
348
|
+
if (typeof reference !== "string") {
|
349
|
+
log.warn(`Received non-string reference in RPC result: ${reference}`);
|
350
|
+
return [];
|
351
|
+
}
|
352
|
+
if (typeof change !== "string" && change !== null) {
|
353
|
+
log.warn(`Received non-string and non-null change in RPC result: ${reference} | ${change}`);
|
354
|
+
return [];
|
355
|
+
}
|
356
|
+
const query = this.#queries.find(({
|
357
|
+
chainId: cId,
|
358
|
+
stateKey
|
359
|
+
}) => cId === chainId && stateKey === reference);
|
360
|
+
if (!query) {
|
361
|
+
log.warn(`Failed to find query:\n${reference} in\n${this.#queries.map(({
|
362
|
+
stateKey
|
363
|
+
}) => stateKey)}`);
|
364
|
+
return [];
|
365
|
+
}
|
366
|
+
return [query.decodeResult(change)];
|
367
|
+
});
|
368
|
+
}
|
369
|
+
}
|
370
|
+
|
289
371
|
const BalanceStatusLive = subscriptionId => `live-${subscriptionId}`;
|
290
372
|
function excludeFromTransferableAmount(locks) {
|
291
373
|
if (typeof locks === "string") return BigInt(locks);
|
292
374
|
if (!Array.isArray(locks)) locks = [locks];
|
293
|
-
return locks.filter(lock => lock.includeInTransferable !== true).map(lock => BigInt(lock.amount)).reduce((max, lock) => util.BigMath.max(max, lock),
|
375
|
+
return locks.filter(lock => lock.includeInTransferable !== true).map(lock => BigInt(lock.amount)).reduce((max, lock) => util.BigMath.max(max, lock), 0n);
|
294
376
|
}
|
295
377
|
function excludeFromFeePayableLocks(locks) {
|
296
378
|
if (typeof locks === "string") return [];
|
@@ -301,9 +383,9 @@ function excludeFromFeePayableLocks(locks) {
|
|
301
383
|
/** A labelled extra amount of a balance */
|
302
384
|
|
303
385
|
function includeInTotalExtraAmount(extra) {
|
304
|
-
if (!extra) return
|
386
|
+
if (!extra) return 0n;
|
305
387
|
if (!Array.isArray(extra)) extra = [extra];
|
306
|
-
return extra.filter(extra => extra.includeInTotal).map(extra => BigInt(extra.amount)).reduce((a, b) => a + b,
|
388
|
+
return extra.filter(extra => extra.includeInTotal).map(extra => BigInt(extra.amount)).reduce((a, b) => a + b, 0n);
|
307
389
|
}
|
308
390
|
|
309
391
|
/** Used by plugins to help define their custom `BalanceType` */
|
@@ -414,6 +496,27 @@ class Balances {
|
|
414
496
|
return new Balances([...this].filter(filter));
|
415
497
|
};
|
416
498
|
|
499
|
+
/**
|
500
|
+
* Filters this collection to exclude token balances where the token has a `mirrorOf` field
|
501
|
+
* and another balance exists in this collection for the token specified by the `mirrorOf` field.
|
502
|
+
*/
|
503
|
+
filterMirrorTokens = () => new Balances([...this].filter(filterMirrorTokens));
|
504
|
+
|
505
|
+
/**
|
506
|
+
* Filters this collection to only include balances which are not zero.
|
507
|
+
*/
|
508
|
+
filterNonZero = type => {
|
509
|
+
const filter = balance => balance[type].planck > 0n;
|
510
|
+
return this.find(filter);
|
511
|
+
};
|
512
|
+
/**
|
513
|
+
* Filters this collection to only include balances which are not zero AND have a fiat conversion rate.
|
514
|
+
*/
|
515
|
+
filterNonZeroFiat = (type, currency) => {
|
516
|
+
const filter = balance => (balance[type].fiat(currency) ?? 0) > 0;
|
517
|
+
return this.find(filter);
|
518
|
+
};
|
519
|
+
|
417
520
|
/**
|
418
521
|
* Add some balances to this collection.
|
419
522
|
* Added balances take priority over existing balances.
|
@@ -536,13 +639,14 @@ class Balance {
|
|
536
639
|
get id() {
|
537
640
|
const {
|
538
641
|
source,
|
642
|
+
subSource,
|
539
643
|
address,
|
540
644
|
chainId,
|
541
645
|
evmNetworkId,
|
542
646
|
tokenId
|
543
647
|
} = this.#storage;
|
544
648
|
const locationId = chainId !== undefined ? chainId : evmNetworkId;
|
545
|
-
return
|
649
|
+
return [source, address, locationId, tokenId, subSource].filter(Boolean).join("-");
|
546
650
|
}
|
547
651
|
get source() {
|
548
652
|
return this.#storage.source;
|
@@ -591,17 +695,43 @@ class Balance {
|
|
591
695
|
}
|
592
696
|
/** The non-reserved balance of this token. Includes the frozen amount. Is included in the total. */
|
593
697
|
get free() {
|
594
|
-
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,
|
698
|
+
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"));
|
595
699
|
}
|
596
700
|
/** The reserved balance of this token. Is included in the total. */
|
597
701
|
get reserved() {
|
598
|
-
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,
|
702
|
+
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"));
|
703
|
+
}
|
704
|
+
get reserves() {
|
705
|
+
return (Array.isArray(this.#storage.reserves) ? this.#storage.reserves : [this.#storage.reserves]).flatMap(reserve => {
|
706
|
+
if (reserve === undefined) return [];
|
707
|
+
if (typeof reserve === "string") return {
|
708
|
+
label: "reserved",
|
709
|
+
amount: this.#format(reserve)
|
710
|
+
};
|
711
|
+
return {
|
712
|
+
...reserve,
|
713
|
+
amount: this.#format(reserve.amount)
|
714
|
+
};
|
715
|
+
});
|
599
716
|
}
|
600
717
|
/** The frozen balance of this token. Is included in the free amount. */
|
601
718
|
get locked() {
|
602
|
-
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),
|
719
|
+
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"));
|
720
|
+
}
|
721
|
+
get locks() {
|
722
|
+
return (Array.isArray(this.#storage.locks) ? this.#storage.locks : [this.#storage.locks]).flatMap(lock => {
|
723
|
+
if (lock === undefined) return [];
|
724
|
+
if (typeof lock === "string") return {
|
725
|
+
label: "other",
|
726
|
+
amount: this.#format(lock)
|
727
|
+
};
|
728
|
+
return {
|
729
|
+
...lock,
|
730
|
+
amount: this.#format(lock.amount)
|
731
|
+
};
|
732
|
+
});
|
603
733
|
}
|
604
|
-
/** @
|
734
|
+
/** @deprecated Use balance.locked */
|
605
735
|
get frozen() {
|
606
736
|
return this.locked;
|
607
737
|
}
|
@@ -614,7 +744,7 @@ class Balance {
|
|
614
744
|
const excludeAmount = excludeFromTransferableAmount(this.#storage.locks);
|
615
745
|
|
616
746
|
// subtract the lock from the free amount (but don't go below 0)
|
617
|
-
return this.#format(util.BigMath.max(this.free.planck - excludeAmount,
|
747
|
+
return this.#format(util.BigMath.max(this.free.planck - excludeAmount, 0n));
|
618
748
|
}
|
619
749
|
/** The feePayable balance of this token. Is generally the free amount - the feeFrozen amount. */
|
620
750
|
get feePayable() {
|
@@ -622,10 +752,10 @@ class Balance {
|
|
622
752
|
if (!this.#storage.locks) return this.free;
|
623
753
|
|
624
754
|
// find the largest lock which can't be used to pay tx fees
|
625
|
-
const excludeAmount = excludeFromFeePayableLocks(this.#storage.locks).map(lock => BigInt(lock.amount)).reduce((max, lock) => util.BigMath.max(max, lock),
|
755
|
+
const excludeAmount = excludeFromFeePayableLocks(this.#storage.locks).map(lock => BigInt(lock.amount)).reduce((max, lock) => util.BigMath.max(max, lock), 0n);
|
626
756
|
|
627
757
|
// subtract the lock from the free amount (but don't go below 0)
|
628
|
-
return this.#format(util.BigMath.max(this.free.planck - excludeAmount,
|
758
|
+
return this.#format(util.BigMath.max(this.free.planck - excludeAmount, 0n));
|
629
759
|
}
|
630
760
|
}
|
631
761
|
class BalanceFormatter {
|
@@ -651,6 +781,52 @@ class BalanceFormatter {
|
|
651
781
|
return parseFloat(this.tokens) * ratio;
|
652
782
|
}
|
653
783
|
}
|
784
|
+
class PlanckSumBalancesFormatter {
|
785
|
+
#balances;
|
786
|
+
constructor(balances) {
|
787
|
+
this.#balances = balances;
|
788
|
+
}
|
789
|
+
#sum = balanceField => {
|
790
|
+
// a function to get a planck amount from a balance
|
791
|
+
const planck = balance => balance[balanceField].planck ?? 0n;
|
792
|
+
return this.#balances.filterMirrorTokens().each.reduce(
|
793
|
+
// add the total amount to the planck amount of each balance
|
794
|
+
(total, balance) => total + planck(balance),
|
795
|
+
// start with a total of 0
|
796
|
+
0n);
|
797
|
+
};
|
798
|
+
|
799
|
+
/**
|
800
|
+
* The total balance of these tokens. Includes the free and the reserved amount.
|
801
|
+
*/
|
802
|
+
get total() {
|
803
|
+
return this.#sum("total");
|
804
|
+
}
|
805
|
+
/** The non-reserved balance of these tokens. Includes the frozen amount. Is included in the total. */
|
806
|
+
get free() {
|
807
|
+
return this.#sum("free");
|
808
|
+
}
|
809
|
+
/** The reserved balance of these tokens. Is included in the total. */
|
810
|
+
get reserved() {
|
811
|
+
return this.#sum("reserved");
|
812
|
+
}
|
813
|
+
/** The frozen balance of these tokens. Is included in the free amount. */
|
814
|
+
get locked() {
|
815
|
+
return this.#sum("locked");
|
816
|
+
}
|
817
|
+
/** @deprecated Use balances.locked */
|
818
|
+
get frozen() {
|
819
|
+
return this.locked;
|
820
|
+
}
|
821
|
+
/** The transferable balance of these tokens. Is generally the free amount - the miscFrozen amount. */
|
822
|
+
get transferable() {
|
823
|
+
return this.#sum("transferable");
|
824
|
+
}
|
825
|
+
/** The feePayable balance of these tokens. Is generally the free amount - the feeFrozen amount. */
|
826
|
+
get feePayable() {
|
827
|
+
return this.#sum("feePayable");
|
828
|
+
}
|
829
|
+
}
|
654
830
|
class FiatSumBalancesFormatter {
|
655
831
|
#balances;
|
656
832
|
#currency;
|
@@ -660,15 +836,10 @@ class FiatSumBalancesFormatter {
|
|
660
836
|
}
|
661
837
|
#sum = balanceField => {
|
662
838
|
// a function to get a fiat amount from a balance
|
663
|
-
const fiat = balance => balance[balanceField].fiat(this.#currency)
|
664
|
-
|
665
|
-
//
|
666
|
-
|
667
|
-
return [...this.#balances].filter(filterMirrorTokens).reduce((total, balance) => sum(
|
668
|
-
// add the total amount...
|
669
|
-
total,
|
670
|
-
// ...to the fiat amount of each balance
|
671
|
-
fiat(balance)),
|
839
|
+
const fiat = balance => balance[balanceField].fiat(this.#currency) ?? 0;
|
840
|
+
return this.#balances.filterMirrorTokens().each.reduce(
|
841
|
+
// add the total amount to the fiat amount of each balance
|
842
|
+
(total, balance) => total + fiat(balance),
|
672
843
|
// start with a total of 0
|
673
844
|
0);
|
674
845
|
};
|
@@ -691,7 +862,7 @@ class FiatSumBalancesFormatter {
|
|
691
862
|
get locked() {
|
692
863
|
return this.#sum("locked");
|
693
864
|
}
|
694
|
-
/** @deprecated
|
865
|
+
/** @deprecated Use balances.locked */
|
695
866
|
get frozen() {
|
696
867
|
return this.locked;
|
697
868
|
}
|
@@ -709,6 +880,9 @@ class SumBalancesFormatter {
|
|
709
880
|
constructor(balances) {
|
710
881
|
this.#balances = balances;
|
711
882
|
}
|
883
|
+
get planck() {
|
884
|
+
return new PlanckSumBalancesFormatter(this.#balances);
|
885
|
+
}
|
712
886
|
fiat(currency) {
|
713
887
|
return new FiatSumBalancesFormatter(this.#balances, currency);
|
714
888
|
}
|
@@ -720,6 +894,8 @@ exports.BalanceStatusLive = BalanceStatusLive;
|
|
720
894
|
exports.Balances = Balances;
|
721
895
|
exports.DefaultBalanceModule = DefaultBalanceModule;
|
722
896
|
exports.FiatSumBalancesFormatter = FiatSumBalancesFormatter;
|
897
|
+
exports.PlanckSumBalancesFormatter = PlanckSumBalancesFormatter;
|
898
|
+
exports.RpcStateQueryHelper = RpcStateQueryHelper;
|
723
899
|
exports.StorageHelper = StorageHelper;
|
724
900
|
exports.SumBalancesFormatter = SumBalancesFormatter;
|
725
901
|
exports.TalismanBalancesDatabase = TalismanBalancesDatabase;
|