@talismn/balances 0.0.0-pr672-20230404063840 → 0.0.0-pr677-20230413171850
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 +21 -6
- package/dist/declarations/src/helpers.d.ts +28 -2
- package/dist/declarations/src/types/balances.d.ts +12 -0
- package/dist/declarations/src/types/balancetypes.d.ts +9 -1
- package/dist/talismn-balances.cjs.dev.js +164 -8
- package/dist/talismn-balances.cjs.prod.js +164 -8
- package/dist/talismn-balances.esm.js +158 -9
- package/package.json +11 -9
package/CHANGELOG.md
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
# @talismn/balances
|
2
2
|
|
3
|
-
## 0.0.0-
|
3
|
+
## 0.0.0-pr677-20230413171850
|
4
|
+
|
5
|
+
### Patch Changes
|
6
|
+
|
7
|
+
- fb8ee962: feat: proxy dapp websocket requests to talisman wallet backend when available
|
8
|
+
- 306e7160: feat: crowdloan and nom pool balances
|
9
|
+
- Updated dependencies [fb8ee962]
|
10
|
+
- Updated dependencies [c898da98]
|
11
|
+
- Updated dependencies [306e7160]
|
12
|
+
- @talismn/chain-connector@0.0.0-pr677-20230413171850
|
13
|
+
- @talismn/chain-connector-evm@0.0.0-pr677-20230413171850
|
14
|
+
- @talismn/util@0.0.0-pr677-20230413171850
|
15
|
+
- @talismn/chaindata-provider@0.0.0-pr677-20230413171850
|
16
|
+
- @talismn/token-rates@0.0.0-pr677-20230413171850
|
17
|
+
|
18
|
+
## 0.4.0
|
4
19
|
|
5
20
|
### Patch Changes
|
6
21
|
|
@@ -11,11 +26,11 @@
|
|
11
26
|
- Updated dependencies [6643a4e4]
|
12
27
|
- Updated dependencies [79f6ccf6]
|
13
28
|
- Updated dependencies [c24dc1fb]
|
14
|
-
- @talismn/chain-connector@0.
|
15
|
-
- @talismn/util@0.
|
16
|
-
- @talismn/token-rates@0.
|
17
|
-
- @talismn/chaindata-provider@0.
|
18
|
-
- @talismn/chain-connector-evm@0.
|
29
|
+
- @talismn/chain-connector@0.4.3
|
30
|
+
- @talismn/util@0.1.8
|
31
|
+
- @talismn/token-rates@0.1.15
|
32
|
+
- @talismn/chaindata-provider@0.4.3
|
33
|
+
- @talismn/chain-connector-evm@0.4.3
|
19
34
|
|
20
35
|
## 0.3.3
|
21
36
|
|
@@ -1,17 +1,26 @@
|
|
1
1
|
import type { Registry } from "@polkadot/types-codec/types";
|
2
|
+
import { ChainConnector } from "@talismn/chain-connector";
|
2
3
|
import { ChainId } from "@talismn/chaindata-provider";
|
3
4
|
import { BalanceModule, DefaultChainMeta, DefaultModuleConfig, DefaultTransferParams, ExtendableChainMeta, ExtendableModuleConfig, ExtendableTokenType, ExtendableTransferParams } from "./BalanceModule";
|
4
|
-
import { AddressesByToken, Balance, Balances, SubscriptionCallback, UnsubscribeFn } from "./types";
|
5
|
+
import { AddressesByToken, Balance, BalanceJson, Balances, SubscriptionCallback, UnsubscribeFn } from "./types";
|
5
6
|
/**
|
6
7
|
* Wraps a BalanceModule's fetch/subscribe methods with a single `balances` method.
|
7
8
|
* This `balances` method will subscribe if a callback parameter is provided, or otherwise fetch.
|
8
9
|
*/
|
9
10
|
export declare function balances<TModuleType extends string, TTokenType extends ExtendableTokenType, TChainMeta extends ExtendableChainMeta = DefaultChainMeta, TModuleConfig extends ExtendableModuleConfig = DefaultModuleConfig, TTransferParams extends ExtendableTransferParams = DefaultTransferParams>(balanceModule: BalanceModule<TModuleType, TTokenType, TChainMeta, TModuleConfig, TTransferParams>, addressesByToken: AddressesByToken<TTokenType>): Promise<Balances>;
|
10
11
|
export declare function balances<TModuleType extends string, TTokenType extends ExtendableTokenType, TChainMeta extends ExtendableChainMeta = DefaultChainMeta, TModuleConfig extends ExtendableModuleConfig = DefaultModuleConfig, TTransferParams extends ExtendableTransferParams = DefaultTransferParams>(balanceModule: BalanceModule<TModuleType, TTokenType, TChainMeta, TModuleConfig, TTransferParams>, addressesByToken: AddressesByToken<TTokenType>, callback: SubscriptionCallback<Balances>): Promise<UnsubscribeFn>;
|
12
|
+
export type GetOrCreateTypeRegistry = (chainId: ChainId, metadataRpc?: `0x${string}`) => Registry;
|
11
13
|
export declare const createTypeRegistryCache: () => {
|
12
|
-
getOrCreateTypeRegistry:
|
14
|
+
getOrCreateTypeRegistry: GetOrCreateTypeRegistry;
|
13
15
|
};
|
14
16
|
export declare const filterMirrorTokens: (balance: Balance, i: number, balances: Balance[]) => boolean;
|
17
|
+
export declare const getValidSubscriptionIds: () => Set<string>;
|
18
|
+
export declare const createSubscriptionId: () => string;
|
19
|
+
export declare const deleteSubscriptionId: () => void;
|
20
|
+
/**
|
21
|
+
* Sets all balance statuses from `live-${string}` to either `live` or `cached`
|
22
|
+
*/
|
23
|
+
export declare const deriveStatuses: (validSubscriptionIds: string[], balances: BalanceJson[]) => BalanceJson[];
|
15
24
|
/**
|
16
25
|
* Used by a variety of balance modules to help encode and decode substrate state calls.
|
17
26
|
*/
|
@@ -26,3 +35,20 @@ export declare class StorageHelper {
|
|
26
35
|
tag(tags: any): this;
|
27
36
|
decode(input?: string | null): import("@polkadot/types-codec/types").Codec | undefined;
|
28
37
|
}
|
38
|
+
/**
|
39
|
+
* Pass some these into an `RpcStateQueryHelper` in order to easily batch multiple state queries into the one rpc call.
|
40
|
+
*/
|
41
|
+
export type RpcStateQuery<T> = {
|
42
|
+
chainId: string;
|
43
|
+
stateKey: string;
|
44
|
+
decodeResult: (change: string | null) => T;
|
45
|
+
};
|
46
|
+
/**
|
47
|
+
* Used by a variety of balance modules to help batch multiple state queries into the one rpc call.
|
48
|
+
*/
|
49
|
+
export declare class RpcStateQueryHelper<T> {
|
50
|
+
#private;
|
51
|
+
constructor(chainConnector: ChainConnector, queries: Array<RpcStateQuery<T>>);
|
52
|
+
subscribe(callback: SubscriptionCallback<T[]>, timeout?: number | false, subscribeMethod?: string, responseMethod?: string, unsubscribeMethod?: string): Promise<UnsubscribeFn>;
|
53
|
+
fetch(method?: string): Promise<T[]>;
|
54
|
+
}
|
@@ -134,8 +134,20 @@ export declare class Balance {
|
|
134
134
|
get free(): BalanceFormatter;
|
135
135
|
/** The reserved balance of this token. Is included in the total. */
|
136
136
|
get reserved(): BalanceFormatter;
|
137
|
+
get reserves(): {
|
138
|
+
amount: BalanceFormatter;
|
139
|
+
label: string;
|
140
|
+
meta?: unknown;
|
141
|
+
}[];
|
137
142
|
/** The frozen balance of this token. Is included in the free amount. */
|
138
143
|
get locked(): BalanceFormatter;
|
144
|
+
get locks(): {
|
145
|
+
amount: BalanceFormatter;
|
146
|
+
label: string;
|
147
|
+
meta?: unknown;
|
148
|
+
includeInTransferable?: boolean | undefined;
|
149
|
+
excludeFromFeePayable?: boolean | undefined;
|
150
|
+
}[];
|
139
151
|
/** @depreacted - use balance.locked */
|
140
152
|
get frozen(): BalanceFormatter;
|
141
153
|
/** The transferable balance of this token. Is generally the free amount - the miscFrozen amount. */
|
@@ -23,11 +23,18 @@ export type BalanceTypes = {
|
|
23
23
|
export type BalanceJson = BalanceTypes[keyof BalanceTypes] extends never ? IBalance : BalanceTypes[keyof BalanceTypes];
|
24
24
|
/** A collection of `BalanceJson` objects */
|
25
25
|
export type BalanceJsonList = Record<string, BalanceJson>;
|
26
|
-
export type
|
26
|
+
export type BalanceStatusLive = `live-${string}`;
|
27
|
+
export declare const BalanceStatusLive: (subscriptionId: string) => BalanceStatusLive;
|
28
|
+
export type BalanceStatus = BalanceStatusLive | "live" | "cache" | "stale";
|
27
29
|
/** `IBalance` is a common interface which all balance types must implement. */
|
28
30
|
export type IBalance = {
|
29
31
|
/** The module that this balance was retrieved by */
|
30
32
|
source: string;
|
33
|
+
/**
|
34
|
+
* For modules which fetch balances via module sources, this is the sub-source
|
35
|
+
* e.g. `staking` or `crowdloans`
|
36
|
+
**/
|
37
|
+
subSource?: string;
|
31
38
|
/** Has this balance never been fetched, or is it from a cache, or is it up to date? */
|
32
39
|
status: BalanceStatus;
|
33
40
|
/** The address of the account which owns this balance */
|
@@ -57,6 +64,7 @@ export type Amount = string;
|
|
57
64
|
export type AmountWithLabel<TLabel extends string> = {
|
58
65
|
label: TLabel;
|
59
66
|
amount: Amount;
|
67
|
+
meta?: unknown;
|
60
68
|
};
|
61
69
|
/** A labelled locked amount of a balance */
|
62
70
|
export type LockedAmount<TLabel extends string> = AmountWithLabel<TLabel> & {
|
@@ -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-pr677-20230413171850",
|
71
73
|
author: "Talisman",
|
72
74
|
homepage: "https://talisman.xyz",
|
73
75
|
license: "UNLICENSED",
|
@@ -100,20 +102,22 @@ var packageJson = {
|
|
100
102
|
"@talismn/token-rates": "workspace:^",
|
101
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": "^
|
109
|
+
"@polkadot/types": "^10.1.4",
|
107
110
|
"@talismn/eslint-config": "workspace:^",
|
108
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
|
+
}));
|
160
|
+
}
|
151
161
|
}
|
152
162
|
typeRegistryCache.set(chainId, typeRegistry);
|
153
163
|
return typeRegistry;
|
@@ -161,6 +171,49 @@ const filterMirrorTokens = (balance, i, balances) => {
|
|
161
171
|
const mirrorOf = balance.token?.mirrorOf;
|
162
172
|
return !mirrorOf || !balances.find(b => b.tokenId === mirrorOf);
|
163
173
|
};
|
174
|
+
const getValidSubscriptionIds = () => {
|
175
|
+
return new Set(localStorage.getItem("TalismanBalancesSubscriptionIds")?.split(",") ?? []);
|
176
|
+
};
|
177
|
+
const createSubscriptionId = () => {
|
178
|
+
// delete current id (if exists)
|
179
|
+
deleteSubscriptionId();
|
180
|
+
|
181
|
+
// create new id
|
182
|
+
const subscriptionId = Date.now().toString();
|
183
|
+
sessionStorage.setItem("TalismanBalancesSubscriptionId", subscriptionId);
|
184
|
+
|
185
|
+
// add to list of current ids
|
186
|
+
const subscriptionIds = getValidSubscriptionIds();
|
187
|
+
subscriptionIds.add(subscriptionId);
|
188
|
+
localStorage.setItem("TalismanBalancesSubscriptionIds", [...subscriptionIds].filter(Boolean).join(","));
|
189
|
+
return subscriptionId;
|
190
|
+
};
|
191
|
+
const deleteSubscriptionId = () => {
|
192
|
+
const subscriptionId = sessionStorage.getItem("TalismanBalancesSubscriptionId");
|
193
|
+
if (!subscriptionId) return;
|
194
|
+
const subscriptionIds = getValidSubscriptionIds();
|
195
|
+
subscriptionIds.delete(subscriptionId);
|
196
|
+
localStorage.setItem("TalismanBalancesSubscriptionIds", [...subscriptionIds].filter(Boolean).join(","));
|
197
|
+
};
|
198
|
+
|
199
|
+
/**
|
200
|
+
* Sets all balance statuses from `live-${string}` to either `live` or `cached`
|
201
|
+
*/
|
202
|
+
const deriveStatuses = (validSubscriptionIds, balances) => balances.map(balance => {
|
203
|
+
if (balance.status === "live" || balance.status === "cache" || balance.status === "stale") return balance;
|
204
|
+
if (validSubscriptionIds.length < 1) return {
|
205
|
+
...balance,
|
206
|
+
status: "cache"
|
207
|
+
};
|
208
|
+
if (!validSubscriptionIds.includes(balance.status.slice("live-".length))) return {
|
209
|
+
...balance,
|
210
|
+
status: "cache"
|
211
|
+
};
|
212
|
+
return {
|
213
|
+
...balance,
|
214
|
+
status: "live"
|
215
|
+
};
|
216
|
+
});
|
164
217
|
|
165
218
|
/**
|
166
219
|
* Used by a variety of balance modules to help encode and decode substrate state calls.
|
@@ -243,6 +296,76 @@ class StorageHelper {
|
|
243
296
|
}
|
244
297
|
}
|
245
298
|
|
299
|
+
/**
|
300
|
+
* Pass some these into an `RpcStateQueryHelper` in order to easily batch multiple state queries into the one rpc call.
|
301
|
+
*/
|
302
|
+
|
303
|
+
/**
|
304
|
+
* Used by a variety of balance modules to help batch multiple state queries into the one rpc call.
|
305
|
+
*/
|
306
|
+
class RpcStateQueryHelper {
|
307
|
+
#chainConnector;
|
308
|
+
#queries;
|
309
|
+
constructor(chainConnector, queries) {
|
310
|
+
this.#chainConnector = chainConnector;
|
311
|
+
this.#queries = queries;
|
312
|
+
}
|
313
|
+
async subscribe(callback, timeout = false, subscribeMethod = "state_subscribeStorage", responseMethod = "state_storage", unsubscribeMethod = "state_unsubscribeStorage") {
|
314
|
+
const queriesByChain = groupBy__default["default"](this.#queries, "chainId");
|
315
|
+
const subscriptions = Object.entries(queriesByChain).map(([chainId, queries]) => {
|
316
|
+
const params = [queries.map(({
|
317
|
+
stateKey
|
318
|
+
}) => stateKey)];
|
319
|
+
const unsubscribe = this.#chainConnector.subscribe(chainId, subscribeMethod, responseMethod, params, (error, result) => {
|
320
|
+
error ? callback(error) : callback(null, this.#distributeChangesToQueryDecoders.call(this, chainId, result));
|
321
|
+
}, timeout);
|
322
|
+
return () => unsubscribe(unsubscribeMethod);
|
323
|
+
}).map(subscription => subscription.catch(error => {
|
324
|
+
log.warn(`Failed to create subscription: ${error.message}`);
|
325
|
+
return () => {};
|
326
|
+
}));
|
327
|
+
return () => subscriptions.forEach(subscription => subscription.then(unsubscribe => unsubscribe()));
|
328
|
+
}
|
329
|
+
async fetch(method = "state_queryStorageAt") {
|
330
|
+
const queriesByChain = groupBy__default["default"](this.#queries, "chainId");
|
331
|
+
const resultsByChain = await Promise.all(Object.entries(queriesByChain).map(async ([chainId, queries]) => {
|
332
|
+
const params = [queries.map(({
|
333
|
+
stateKey
|
334
|
+
}) => stateKey)];
|
335
|
+
const result = (await this.#chainConnector.send(chainId, method, params))[0];
|
336
|
+
return this.#distributeChangesToQueryDecoders.call(this, chainId, result);
|
337
|
+
}));
|
338
|
+
return resultsByChain.flatMap(result => result);
|
339
|
+
}
|
340
|
+
#distributeChangesToQueryDecoders(chainId, result) {
|
341
|
+
if (typeof result !== "object" || result === null) return [];
|
342
|
+
if (!util.hasOwnProperty(result, "changes") || typeof result.changes !== "object") return [];
|
343
|
+
if (!Array.isArray(result.changes)) return [];
|
344
|
+
return result.changes.flatMap(([reference, change]) => {
|
345
|
+
if (typeof reference !== "string") {
|
346
|
+
log.warn(`Received non-string reference in RPC result: ${reference}`);
|
347
|
+
return [];
|
348
|
+
}
|
349
|
+
if (typeof change !== "string" && change !== null) {
|
350
|
+
log.warn(`Received non-string and non-null change in RPC result: ${reference} | ${change}`);
|
351
|
+
return [];
|
352
|
+
}
|
353
|
+
const query = this.#queries.find(({
|
354
|
+
chainId: cId,
|
355
|
+
stateKey
|
356
|
+
}) => cId === chainId && stateKey === reference);
|
357
|
+
if (!query) {
|
358
|
+
log.warn(`Failed to find query:\n${reference} in\n${this.#queries.map(({
|
359
|
+
stateKey
|
360
|
+
}) => stateKey)}`);
|
361
|
+
return [];
|
362
|
+
}
|
363
|
+
return query.decodeResult(change);
|
364
|
+
});
|
365
|
+
}
|
366
|
+
}
|
367
|
+
|
368
|
+
const BalanceStatusLive = subscriptionId => `live-${subscriptionId}`;
|
246
369
|
function excludeFromTransferableAmount(locks) {
|
247
370
|
if (typeof locks === "string") return BigInt(locks);
|
248
371
|
if (!Array.isArray(locks)) locks = [locks];
|
@@ -492,13 +615,14 @@ class Balance {
|
|
492
615
|
get id() {
|
493
616
|
const {
|
494
617
|
source,
|
618
|
+
subSource,
|
495
619
|
address,
|
496
620
|
chainId,
|
497
621
|
evmNetworkId,
|
498
622
|
tokenId
|
499
623
|
} = this.#storage;
|
500
624
|
const locationId = chainId !== undefined ? chainId : evmNetworkId;
|
501
|
-
return
|
625
|
+
return [source, address, locationId, tokenId, subSource].filter(Boolean).join("-");
|
502
626
|
}
|
503
627
|
get source() {
|
504
628
|
return this.#storage.source;
|
@@ -553,10 +677,36 @@ class Balance {
|
|
553
677
|
get reserved() {
|
554
678
|
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, BigInt("0")) : BigInt(this.#storage.reserves?.amount || "0"));
|
555
679
|
}
|
680
|
+
get reserves() {
|
681
|
+
return (Array.isArray(this.#storage.reserves) ? this.#storage.reserves : [this.#storage.reserves]).flatMap(reserve => {
|
682
|
+
if (reserve === undefined) return [];
|
683
|
+
if (typeof reserve === "string") return {
|
684
|
+
label: "other",
|
685
|
+
amount: this.#format(reserve)
|
686
|
+
};
|
687
|
+
return {
|
688
|
+
...reserve,
|
689
|
+
amount: this.#format(reserve.amount)
|
690
|
+
};
|
691
|
+
});
|
692
|
+
}
|
556
693
|
/** The frozen balance of this token. Is included in the free amount. */
|
557
694
|
get locked() {
|
558
695
|
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), BigInt("0")) : BigInt(this.#storage.locks?.amount || "0"));
|
559
696
|
}
|
697
|
+
get locks() {
|
698
|
+
return (Array.isArray(this.#storage.locks) ? this.#storage.locks : [this.#storage.locks]).flatMap(lock => {
|
699
|
+
if (lock === undefined) return [];
|
700
|
+
if (typeof lock === "string") return {
|
701
|
+
label: "other",
|
702
|
+
amount: this.#format(lock)
|
703
|
+
};
|
704
|
+
return {
|
705
|
+
...lock,
|
706
|
+
amount: this.#format(lock.amount)
|
707
|
+
};
|
708
|
+
});
|
709
|
+
}
|
560
710
|
/** @depreacted - use balance.locked */
|
561
711
|
get frozen() {
|
562
712
|
return this.locked;
|
@@ -672,16 +822,22 @@ class SumBalancesFormatter {
|
|
672
822
|
|
673
823
|
exports.Balance = Balance;
|
674
824
|
exports.BalanceFormatter = BalanceFormatter;
|
825
|
+
exports.BalanceStatusLive = BalanceStatusLive;
|
675
826
|
exports.Balances = Balances;
|
676
827
|
exports.DefaultBalanceModule = DefaultBalanceModule;
|
677
828
|
exports.FiatSumBalancesFormatter = FiatSumBalancesFormatter;
|
829
|
+
exports.RpcStateQueryHelper = RpcStateQueryHelper;
|
678
830
|
exports.StorageHelper = StorageHelper;
|
679
831
|
exports.SumBalancesFormatter = SumBalancesFormatter;
|
680
832
|
exports.TalismanBalancesDatabase = TalismanBalancesDatabase;
|
681
833
|
exports.balances = balances;
|
834
|
+
exports.createSubscriptionId = createSubscriptionId;
|
682
835
|
exports.createTypeRegistryCache = createTypeRegistryCache;
|
683
836
|
exports.db = db;
|
837
|
+
exports.deleteSubscriptionId = deleteSubscriptionId;
|
838
|
+
exports.deriveStatuses = deriveStatuses;
|
684
839
|
exports.excludeFromFeePayableLocks = excludeFromFeePayableLocks;
|
685
840
|
exports.excludeFromTransferableAmount = excludeFromTransferableAmount;
|
686
841
|
exports.filterMirrorTokens = filterMirrorTokens;
|
842
|
+
exports.getValidSubscriptionIds = getValidSubscriptionIds;
|
687
843
|
exports.includeInTotalExtraAmount = includeInTotalExtraAmount;
|
@@ -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-pr677-20230413171850",
|
71
73
|
author: "Talisman",
|
72
74
|
homepage: "https://talisman.xyz",
|
73
75
|
license: "UNLICENSED",
|
@@ -100,20 +102,22 @@ var packageJson = {
|
|
100
102
|
"@talismn/token-rates": "workspace:^",
|
101
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": "^
|
109
|
+
"@polkadot/types": "^10.1.4",
|
107
110
|
"@talismn/eslint-config": "workspace:^",
|
108
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
|
+
}));
|
160
|
+
}
|
151
161
|
}
|
152
162
|
typeRegistryCache.set(chainId, typeRegistry);
|
153
163
|
return typeRegistry;
|
@@ -161,6 +171,49 @@ const filterMirrorTokens = (balance, i, balances) => {
|
|
161
171
|
const mirrorOf = balance.token?.mirrorOf;
|
162
172
|
return !mirrorOf || !balances.find(b => b.tokenId === mirrorOf);
|
163
173
|
};
|
174
|
+
const getValidSubscriptionIds = () => {
|
175
|
+
return new Set(localStorage.getItem("TalismanBalancesSubscriptionIds")?.split(",") ?? []);
|
176
|
+
};
|
177
|
+
const createSubscriptionId = () => {
|
178
|
+
// delete current id (if exists)
|
179
|
+
deleteSubscriptionId();
|
180
|
+
|
181
|
+
// create new id
|
182
|
+
const subscriptionId = Date.now().toString();
|
183
|
+
sessionStorage.setItem("TalismanBalancesSubscriptionId", subscriptionId);
|
184
|
+
|
185
|
+
// add to list of current ids
|
186
|
+
const subscriptionIds = getValidSubscriptionIds();
|
187
|
+
subscriptionIds.add(subscriptionId);
|
188
|
+
localStorage.setItem("TalismanBalancesSubscriptionIds", [...subscriptionIds].filter(Boolean).join(","));
|
189
|
+
return subscriptionId;
|
190
|
+
};
|
191
|
+
const deleteSubscriptionId = () => {
|
192
|
+
const subscriptionId = sessionStorage.getItem("TalismanBalancesSubscriptionId");
|
193
|
+
if (!subscriptionId) return;
|
194
|
+
const subscriptionIds = getValidSubscriptionIds();
|
195
|
+
subscriptionIds.delete(subscriptionId);
|
196
|
+
localStorage.setItem("TalismanBalancesSubscriptionIds", [...subscriptionIds].filter(Boolean).join(","));
|
197
|
+
};
|
198
|
+
|
199
|
+
/**
|
200
|
+
* Sets all balance statuses from `live-${string}` to either `live` or `cached`
|
201
|
+
*/
|
202
|
+
const deriveStatuses = (validSubscriptionIds, balances) => balances.map(balance => {
|
203
|
+
if (balance.status === "live" || balance.status === "cache" || balance.status === "stale") return balance;
|
204
|
+
if (validSubscriptionIds.length < 1) return {
|
205
|
+
...balance,
|
206
|
+
status: "cache"
|
207
|
+
};
|
208
|
+
if (!validSubscriptionIds.includes(balance.status.slice("live-".length))) return {
|
209
|
+
...balance,
|
210
|
+
status: "cache"
|
211
|
+
};
|
212
|
+
return {
|
213
|
+
...balance,
|
214
|
+
status: "live"
|
215
|
+
};
|
216
|
+
});
|
164
217
|
|
165
218
|
/**
|
166
219
|
* Used by a variety of balance modules to help encode and decode substrate state calls.
|
@@ -243,6 +296,76 @@ class StorageHelper {
|
|
243
296
|
}
|
244
297
|
}
|
245
298
|
|
299
|
+
/**
|
300
|
+
* Pass some these into an `RpcStateQueryHelper` in order to easily batch multiple state queries into the one rpc call.
|
301
|
+
*/
|
302
|
+
|
303
|
+
/**
|
304
|
+
* Used by a variety of balance modules to help batch multiple state queries into the one rpc call.
|
305
|
+
*/
|
306
|
+
class RpcStateQueryHelper {
|
307
|
+
#chainConnector;
|
308
|
+
#queries;
|
309
|
+
constructor(chainConnector, queries) {
|
310
|
+
this.#chainConnector = chainConnector;
|
311
|
+
this.#queries = queries;
|
312
|
+
}
|
313
|
+
async subscribe(callback, timeout = false, subscribeMethod = "state_subscribeStorage", responseMethod = "state_storage", unsubscribeMethod = "state_unsubscribeStorage") {
|
314
|
+
const queriesByChain = groupBy__default["default"](this.#queries, "chainId");
|
315
|
+
const subscriptions = Object.entries(queriesByChain).map(([chainId, queries]) => {
|
316
|
+
const params = [queries.map(({
|
317
|
+
stateKey
|
318
|
+
}) => stateKey)];
|
319
|
+
const unsubscribe = this.#chainConnector.subscribe(chainId, subscribeMethod, responseMethod, params, (error, result) => {
|
320
|
+
error ? callback(error) : callback(null, this.#distributeChangesToQueryDecoders.call(this, chainId, result));
|
321
|
+
}, timeout);
|
322
|
+
return () => unsubscribe(unsubscribeMethod);
|
323
|
+
}).map(subscription => subscription.catch(error => {
|
324
|
+
log.warn(`Failed to create subscription: ${error.message}`);
|
325
|
+
return () => {};
|
326
|
+
}));
|
327
|
+
return () => subscriptions.forEach(subscription => subscription.then(unsubscribe => unsubscribe()));
|
328
|
+
}
|
329
|
+
async fetch(method = "state_queryStorageAt") {
|
330
|
+
const queriesByChain = groupBy__default["default"](this.#queries, "chainId");
|
331
|
+
const resultsByChain = await Promise.all(Object.entries(queriesByChain).map(async ([chainId, queries]) => {
|
332
|
+
const params = [queries.map(({
|
333
|
+
stateKey
|
334
|
+
}) => stateKey)];
|
335
|
+
const result = (await this.#chainConnector.send(chainId, method, params))[0];
|
336
|
+
return this.#distributeChangesToQueryDecoders.call(this, chainId, result);
|
337
|
+
}));
|
338
|
+
return resultsByChain.flatMap(result => result);
|
339
|
+
}
|
340
|
+
#distributeChangesToQueryDecoders(chainId, result) {
|
341
|
+
if (typeof result !== "object" || result === null) return [];
|
342
|
+
if (!util.hasOwnProperty(result, "changes") || typeof result.changes !== "object") return [];
|
343
|
+
if (!Array.isArray(result.changes)) return [];
|
344
|
+
return result.changes.flatMap(([reference, change]) => {
|
345
|
+
if (typeof reference !== "string") {
|
346
|
+
log.warn(`Received non-string reference in RPC result: ${reference}`);
|
347
|
+
return [];
|
348
|
+
}
|
349
|
+
if (typeof change !== "string" && change !== null) {
|
350
|
+
log.warn(`Received non-string and non-null change in RPC result: ${reference} | ${change}`);
|
351
|
+
return [];
|
352
|
+
}
|
353
|
+
const query = this.#queries.find(({
|
354
|
+
chainId: cId,
|
355
|
+
stateKey
|
356
|
+
}) => cId === chainId && stateKey === reference);
|
357
|
+
if (!query) {
|
358
|
+
log.warn(`Failed to find query:\n${reference} in\n${this.#queries.map(({
|
359
|
+
stateKey
|
360
|
+
}) => stateKey)}`);
|
361
|
+
return [];
|
362
|
+
}
|
363
|
+
return query.decodeResult(change);
|
364
|
+
});
|
365
|
+
}
|
366
|
+
}
|
367
|
+
|
368
|
+
const BalanceStatusLive = subscriptionId => `live-${subscriptionId}`;
|
246
369
|
function excludeFromTransferableAmount(locks) {
|
247
370
|
if (typeof locks === "string") return BigInt(locks);
|
248
371
|
if (!Array.isArray(locks)) locks = [locks];
|
@@ -492,13 +615,14 @@ class Balance {
|
|
492
615
|
get id() {
|
493
616
|
const {
|
494
617
|
source,
|
618
|
+
subSource,
|
495
619
|
address,
|
496
620
|
chainId,
|
497
621
|
evmNetworkId,
|
498
622
|
tokenId
|
499
623
|
} = this.#storage;
|
500
624
|
const locationId = chainId !== undefined ? chainId : evmNetworkId;
|
501
|
-
return
|
625
|
+
return [source, address, locationId, tokenId, subSource].filter(Boolean).join("-");
|
502
626
|
}
|
503
627
|
get source() {
|
504
628
|
return this.#storage.source;
|
@@ -553,10 +677,36 @@ class Balance {
|
|
553
677
|
get reserved() {
|
554
678
|
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, BigInt("0")) : BigInt(this.#storage.reserves?.amount || "0"));
|
555
679
|
}
|
680
|
+
get reserves() {
|
681
|
+
return (Array.isArray(this.#storage.reserves) ? this.#storage.reserves : [this.#storage.reserves]).flatMap(reserve => {
|
682
|
+
if (reserve === undefined) return [];
|
683
|
+
if (typeof reserve === "string") return {
|
684
|
+
label: "other",
|
685
|
+
amount: this.#format(reserve)
|
686
|
+
};
|
687
|
+
return {
|
688
|
+
...reserve,
|
689
|
+
amount: this.#format(reserve.amount)
|
690
|
+
};
|
691
|
+
});
|
692
|
+
}
|
556
693
|
/** The frozen balance of this token. Is included in the free amount. */
|
557
694
|
get locked() {
|
558
695
|
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), BigInt("0")) : BigInt(this.#storage.locks?.amount || "0"));
|
559
696
|
}
|
697
|
+
get locks() {
|
698
|
+
return (Array.isArray(this.#storage.locks) ? this.#storage.locks : [this.#storage.locks]).flatMap(lock => {
|
699
|
+
if (lock === undefined) return [];
|
700
|
+
if (typeof lock === "string") return {
|
701
|
+
label: "other",
|
702
|
+
amount: this.#format(lock)
|
703
|
+
};
|
704
|
+
return {
|
705
|
+
...lock,
|
706
|
+
amount: this.#format(lock.amount)
|
707
|
+
};
|
708
|
+
});
|
709
|
+
}
|
560
710
|
/** @depreacted - use balance.locked */
|
561
711
|
get frozen() {
|
562
712
|
return this.locked;
|
@@ -672,16 +822,22 @@ class SumBalancesFormatter {
|
|
672
822
|
|
673
823
|
exports.Balance = Balance;
|
674
824
|
exports.BalanceFormatter = BalanceFormatter;
|
825
|
+
exports.BalanceStatusLive = BalanceStatusLive;
|
675
826
|
exports.Balances = Balances;
|
676
827
|
exports.DefaultBalanceModule = DefaultBalanceModule;
|
677
828
|
exports.FiatSumBalancesFormatter = FiatSumBalancesFormatter;
|
829
|
+
exports.RpcStateQueryHelper = RpcStateQueryHelper;
|
678
830
|
exports.StorageHelper = StorageHelper;
|
679
831
|
exports.SumBalancesFormatter = SumBalancesFormatter;
|
680
832
|
exports.TalismanBalancesDatabase = TalismanBalancesDatabase;
|
681
833
|
exports.balances = balances;
|
834
|
+
exports.createSubscriptionId = createSubscriptionId;
|
682
835
|
exports.createTypeRegistryCache = createTypeRegistryCache;
|
683
836
|
exports.db = db;
|
837
|
+
exports.deleteSubscriptionId = deleteSubscriptionId;
|
838
|
+
exports.deriveStatuses = deriveStatuses;
|
684
839
|
exports.excludeFromFeePayableLocks = excludeFromFeePayableLocks;
|
685
840
|
exports.excludeFromTransferableAmount = excludeFromTransferableAmount;
|
686
841
|
exports.filterMirrorTokens = filterMirrorTokens;
|
842
|
+
exports.getValidSubscriptionIds = getValidSubscriptionIds;
|
687
843
|
exports.includeInTotalExtraAmount = includeInTotalExtraAmount;
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import { Dexie } from 'dexie';
|
2
2
|
import { decorateStorage, StorageKey, TypeRegistry, Metadata } from '@polkadot/types';
|
3
|
+
import { hasOwnProperty, BigMath, isArrayOf, planckToTokens } from '@talismn/util';
|
4
|
+
import groupBy from 'lodash/groupBy';
|
3
5
|
import anylogger from 'anylogger';
|
4
|
-
import { BigMath, isArrayOf, planckToTokens } from '@talismn/util';
|
5
6
|
|
6
7
|
// TODO: Document default balances module purpose/usage
|
7
8
|
const DefaultBalanceModule = type => ({
|
@@ -59,7 +60,7 @@ const db = new TalismanBalancesDatabase();
|
|
59
60
|
|
60
61
|
var packageJson = {
|
61
62
|
name: "@talismn/balances",
|
62
|
-
version: "0.0.0-
|
63
|
+
version: "0.0.0-pr677-20230413171850",
|
63
64
|
author: "Talisman",
|
64
65
|
homepage: "https://talisman.xyz",
|
65
66
|
license: "UNLICENSED",
|
@@ -92,20 +93,22 @@ var packageJson = {
|
|
92
93
|
"@talismn/token-rates": "workspace:^",
|
93
94
|
"@talismn/util": "workspace:^",
|
94
95
|
anylogger: "^1.0.11",
|
95
|
-
dexie: "^3.2.3"
|
96
|
+
dexie: "^3.2.3",
|
97
|
+
lodash: "4.17.21"
|
96
98
|
},
|
97
99
|
devDependencies: {
|
98
|
-
"@polkadot/types": "^
|
100
|
+
"@polkadot/types": "^10.1.4",
|
99
101
|
"@talismn/eslint-config": "workspace:^",
|
100
102
|
"@talismn/tsconfig": "workspace:^",
|
101
103
|
"@types/jest": "^27.5.1",
|
104
|
+
"@types/lodash": "^4.14.180",
|
102
105
|
eslint: "^8.4.0",
|
103
106
|
jest: "^28.1.0",
|
104
107
|
"ts-jest": "^28.0.2",
|
105
108
|
typescript: "^4.6.4"
|
106
109
|
},
|
107
110
|
peerDependencies: {
|
108
|
-
"@polkadot/types": "
|
111
|
+
"@polkadot/types": "10.x"
|
109
112
|
},
|
110
113
|
preconstruct: {
|
111
114
|
entrypoints: [
|
@@ -138,8 +141,14 @@ const createTypeRegistryCache = () => {
|
|
138
141
|
if (cached) return cached;
|
139
142
|
const typeRegistry = new TypeRegistry();
|
140
143
|
if (typeof metadataRpc === "string") {
|
141
|
-
|
142
|
-
|
144
|
+
try {
|
145
|
+
const metadata = new Metadata(typeRegistry, metadataRpc);
|
146
|
+
metadata.registry.setMetadata(metadata);
|
147
|
+
} catch (cause) {
|
148
|
+
log.warn(new Error(`Failed to set metadata for chain ${chainId}`, {
|
149
|
+
cause
|
150
|
+
}));
|
151
|
+
}
|
143
152
|
}
|
144
153
|
typeRegistryCache.set(chainId, typeRegistry);
|
145
154
|
return typeRegistry;
|
@@ -153,6 +162,49 @@ const filterMirrorTokens = (balance, i, balances) => {
|
|
153
162
|
const mirrorOf = balance.token?.mirrorOf;
|
154
163
|
return !mirrorOf || !balances.find(b => b.tokenId === mirrorOf);
|
155
164
|
};
|
165
|
+
const getValidSubscriptionIds = () => {
|
166
|
+
return new Set(localStorage.getItem("TalismanBalancesSubscriptionIds")?.split(",") ?? []);
|
167
|
+
};
|
168
|
+
const createSubscriptionId = () => {
|
169
|
+
// delete current id (if exists)
|
170
|
+
deleteSubscriptionId();
|
171
|
+
|
172
|
+
// create new id
|
173
|
+
const subscriptionId = Date.now().toString();
|
174
|
+
sessionStorage.setItem("TalismanBalancesSubscriptionId", subscriptionId);
|
175
|
+
|
176
|
+
// add to list of current ids
|
177
|
+
const subscriptionIds = getValidSubscriptionIds();
|
178
|
+
subscriptionIds.add(subscriptionId);
|
179
|
+
localStorage.setItem("TalismanBalancesSubscriptionIds", [...subscriptionIds].filter(Boolean).join(","));
|
180
|
+
return subscriptionId;
|
181
|
+
};
|
182
|
+
const deleteSubscriptionId = () => {
|
183
|
+
const subscriptionId = sessionStorage.getItem("TalismanBalancesSubscriptionId");
|
184
|
+
if (!subscriptionId) return;
|
185
|
+
const subscriptionIds = getValidSubscriptionIds();
|
186
|
+
subscriptionIds.delete(subscriptionId);
|
187
|
+
localStorage.setItem("TalismanBalancesSubscriptionIds", [...subscriptionIds].filter(Boolean).join(","));
|
188
|
+
};
|
189
|
+
|
190
|
+
/**
|
191
|
+
* Sets all balance statuses from `live-${string}` to either `live` or `cached`
|
192
|
+
*/
|
193
|
+
const deriveStatuses = (validSubscriptionIds, balances) => balances.map(balance => {
|
194
|
+
if (balance.status === "live" || balance.status === "cache" || balance.status === "stale") return balance;
|
195
|
+
if (validSubscriptionIds.length < 1) return {
|
196
|
+
...balance,
|
197
|
+
status: "cache"
|
198
|
+
};
|
199
|
+
if (!validSubscriptionIds.includes(balance.status.slice("live-".length))) return {
|
200
|
+
...balance,
|
201
|
+
status: "cache"
|
202
|
+
};
|
203
|
+
return {
|
204
|
+
...balance,
|
205
|
+
status: "live"
|
206
|
+
};
|
207
|
+
});
|
156
208
|
|
157
209
|
/**
|
158
210
|
* Used by a variety of balance modules to help encode and decode substrate state calls.
|
@@ -235,6 +287,76 @@ class StorageHelper {
|
|
235
287
|
}
|
236
288
|
}
|
237
289
|
|
290
|
+
/**
|
291
|
+
* Pass some these into an `RpcStateQueryHelper` in order to easily batch multiple state queries into the one rpc call.
|
292
|
+
*/
|
293
|
+
|
294
|
+
/**
|
295
|
+
* Used by a variety of balance modules to help batch multiple state queries into the one rpc call.
|
296
|
+
*/
|
297
|
+
class RpcStateQueryHelper {
|
298
|
+
#chainConnector;
|
299
|
+
#queries;
|
300
|
+
constructor(chainConnector, queries) {
|
301
|
+
this.#chainConnector = chainConnector;
|
302
|
+
this.#queries = queries;
|
303
|
+
}
|
304
|
+
async subscribe(callback, timeout = false, subscribeMethod = "state_subscribeStorage", responseMethod = "state_storage", unsubscribeMethod = "state_unsubscribeStorage") {
|
305
|
+
const queriesByChain = groupBy(this.#queries, "chainId");
|
306
|
+
const subscriptions = Object.entries(queriesByChain).map(([chainId, queries]) => {
|
307
|
+
const params = [queries.map(({
|
308
|
+
stateKey
|
309
|
+
}) => stateKey)];
|
310
|
+
const unsubscribe = this.#chainConnector.subscribe(chainId, subscribeMethod, responseMethod, params, (error, result) => {
|
311
|
+
error ? callback(error) : callback(null, this.#distributeChangesToQueryDecoders.call(this, chainId, result));
|
312
|
+
}, timeout);
|
313
|
+
return () => unsubscribe(unsubscribeMethod);
|
314
|
+
}).map(subscription => subscription.catch(error => {
|
315
|
+
log.warn(`Failed to create subscription: ${error.message}`);
|
316
|
+
return () => {};
|
317
|
+
}));
|
318
|
+
return () => subscriptions.forEach(subscription => subscription.then(unsubscribe => unsubscribe()));
|
319
|
+
}
|
320
|
+
async fetch(method = "state_queryStorageAt") {
|
321
|
+
const queriesByChain = groupBy(this.#queries, "chainId");
|
322
|
+
const resultsByChain = await Promise.all(Object.entries(queriesByChain).map(async ([chainId, queries]) => {
|
323
|
+
const params = [queries.map(({
|
324
|
+
stateKey
|
325
|
+
}) => stateKey)];
|
326
|
+
const result = (await this.#chainConnector.send(chainId, method, params))[0];
|
327
|
+
return this.#distributeChangesToQueryDecoders.call(this, chainId, result);
|
328
|
+
}));
|
329
|
+
return resultsByChain.flatMap(result => result);
|
330
|
+
}
|
331
|
+
#distributeChangesToQueryDecoders(chainId, result) {
|
332
|
+
if (typeof result !== "object" || result === null) return [];
|
333
|
+
if (!hasOwnProperty(result, "changes") || typeof result.changes !== "object") return [];
|
334
|
+
if (!Array.isArray(result.changes)) return [];
|
335
|
+
return result.changes.flatMap(([reference, change]) => {
|
336
|
+
if (typeof reference !== "string") {
|
337
|
+
log.warn(`Received non-string reference in RPC result: ${reference}`);
|
338
|
+
return [];
|
339
|
+
}
|
340
|
+
if (typeof change !== "string" && change !== null) {
|
341
|
+
log.warn(`Received non-string and non-null change in RPC result: ${reference} | ${change}`);
|
342
|
+
return [];
|
343
|
+
}
|
344
|
+
const query = this.#queries.find(({
|
345
|
+
chainId: cId,
|
346
|
+
stateKey
|
347
|
+
}) => cId === chainId && stateKey === reference);
|
348
|
+
if (!query) {
|
349
|
+
log.warn(`Failed to find query:\n${reference} in\n${this.#queries.map(({
|
350
|
+
stateKey
|
351
|
+
}) => stateKey)}`);
|
352
|
+
return [];
|
353
|
+
}
|
354
|
+
return query.decodeResult(change);
|
355
|
+
});
|
356
|
+
}
|
357
|
+
}
|
358
|
+
|
359
|
+
const BalanceStatusLive = subscriptionId => `live-${subscriptionId}`;
|
238
360
|
function excludeFromTransferableAmount(locks) {
|
239
361
|
if (typeof locks === "string") return BigInt(locks);
|
240
362
|
if (!Array.isArray(locks)) locks = [locks];
|
@@ -484,13 +606,14 @@ class Balance {
|
|
484
606
|
get id() {
|
485
607
|
const {
|
486
608
|
source,
|
609
|
+
subSource,
|
487
610
|
address,
|
488
611
|
chainId,
|
489
612
|
evmNetworkId,
|
490
613
|
tokenId
|
491
614
|
} = this.#storage;
|
492
615
|
const locationId = chainId !== undefined ? chainId : evmNetworkId;
|
493
|
-
return
|
616
|
+
return [source, address, locationId, tokenId, subSource].filter(Boolean).join("-");
|
494
617
|
}
|
495
618
|
get source() {
|
496
619
|
return this.#storage.source;
|
@@ -545,10 +668,36 @@ class Balance {
|
|
545
668
|
get reserved() {
|
546
669
|
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, BigInt("0")) : BigInt(this.#storage.reserves?.amount || "0"));
|
547
670
|
}
|
671
|
+
get reserves() {
|
672
|
+
return (Array.isArray(this.#storage.reserves) ? this.#storage.reserves : [this.#storage.reserves]).flatMap(reserve => {
|
673
|
+
if (reserve === undefined) return [];
|
674
|
+
if (typeof reserve === "string") return {
|
675
|
+
label: "other",
|
676
|
+
amount: this.#format(reserve)
|
677
|
+
};
|
678
|
+
return {
|
679
|
+
...reserve,
|
680
|
+
amount: this.#format(reserve.amount)
|
681
|
+
};
|
682
|
+
});
|
683
|
+
}
|
548
684
|
/** The frozen balance of this token. Is included in the free amount. */
|
549
685
|
get locked() {
|
550
686
|
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) => BigMath.max(a, b), BigInt("0")) : BigInt(this.#storage.locks?.amount || "0"));
|
551
687
|
}
|
688
|
+
get locks() {
|
689
|
+
return (Array.isArray(this.#storage.locks) ? this.#storage.locks : [this.#storage.locks]).flatMap(lock => {
|
690
|
+
if (lock === undefined) return [];
|
691
|
+
if (typeof lock === "string") return {
|
692
|
+
label: "other",
|
693
|
+
amount: this.#format(lock)
|
694
|
+
};
|
695
|
+
return {
|
696
|
+
...lock,
|
697
|
+
amount: this.#format(lock.amount)
|
698
|
+
};
|
699
|
+
});
|
700
|
+
}
|
552
701
|
/** @depreacted - use balance.locked */
|
553
702
|
get frozen() {
|
554
703
|
return this.locked;
|
@@ -662,4 +811,4 @@ class SumBalancesFormatter {
|
|
662
811
|
}
|
663
812
|
}
|
664
813
|
|
665
|
-
export { Balance, BalanceFormatter, Balances, DefaultBalanceModule, FiatSumBalancesFormatter, StorageHelper, SumBalancesFormatter, TalismanBalancesDatabase, balances, createTypeRegistryCache, db, excludeFromFeePayableLocks, excludeFromTransferableAmount, filterMirrorTokens, includeInTotalExtraAmount };
|
814
|
+
export { Balance, BalanceFormatter, BalanceStatusLive, Balances, DefaultBalanceModule, FiatSumBalancesFormatter, RpcStateQueryHelper, StorageHelper, SumBalancesFormatter, TalismanBalancesDatabase, balances, createSubscriptionId, createTypeRegistryCache, db, deleteSubscriptionId, deriveStatuses, excludeFromFeePayableLocks, excludeFromTransferableAmount, filterMirrorTokens, getValidSubscriptionIds, includeInTotalExtraAmount };
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@talismn/balances",
|
3
|
-
"version": "0.0.0-
|
3
|
+
"version": "0.0.0-pr677-20230413171850",
|
4
4
|
"author": "Talisman",
|
5
5
|
"homepage": "https://talisman.xyz",
|
6
6
|
"license": "UNLICENSED",
|
@@ -27,26 +27,28 @@
|
|
27
27
|
"clean": "rm -rf dist && rm -rf .turbo rm -rf node_modules"
|
28
28
|
},
|
29
29
|
"dependencies": {
|
30
|
-
"@talismn/chain-connector": "^0.0.0-
|
31
|
-
"@talismn/chain-connector-evm": "^0.0.0-
|
32
|
-
"@talismn/chaindata-provider": "^0.0.0-
|
33
|
-
"@talismn/token-rates": "^0.0.0-
|
34
|
-
"@talismn/util": "^0.0.0-
|
30
|
+
"@talismn/chain-connector": "^0.0.0-pr677-20230413171850",
|
31
|
+
"@talismn/chain-connector-evm": "^0.0.0-pr677-20230413171850",
|
32
|
+
"@talismn/chaindata-provider": "^0.0.0-pr677-20230413171850",
|
33
|
+
"@talismn/token-rates": "^0.0.0-pr677-20230413171850",
|
34
|
+
"@talismn/util": "^0.0.0-pr677-20230413171850",
|
35
35
|
"anylogger": "^1.0.11",
|
36
|
-
"dexie": "^3.2.3"
|
36
|
+
"dexie": "^3.2.3",
|
37
|
+
"lodash": "4.17.21"
|
37
38
|
},
|
38
39
|
"devDependencies": {
|
39
|
-
"@polkadot/types": "^
|
40
|
+
"@polkadot/types": "^10.1.4",
|
40
41
|
"@talismn/eslint-config": "^0.0.1",
|
41
42
|
"@talismn/tsconfig": "^0.0.2",
|
42
43
|
"@types/jest": "^27.5.1",
|
44
|
+
"@types/lodash": "^4.14.180",
|
43
45
|
"eslint": "^8.4.0",
|
44
46
|
"jest": "^28.1.0",
|
45
47
|
"ts-jest": "^28.0.2",
|
46
48
|
"typescript": "^4.6.4"
|
47
49
|
},
|
48
50
|
"peerDependencies": {
|
49
|
-
"@polkadot/types": "
|
51
|
+
"@polkadot/types": "10.x"
|
50
52
|
},
|
51
53
|
"preconstruct": {
|
52
54
|
"entrypoints": [
|