@subwallet/extension-base 1.1.23-0 → 1.1.24-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.
Files changed (82) hide show
  1. package/background/KoniTypes.d.ts +12 -26
  2. package/cjs/constants/index.js +9 -3
  3. package/cjs/koni/api/staking/bonding/index.js +1 -0
  4. package/cjs/koni/api/tokens/evm/balance.js +5 -1
  5. package/cjs/koni/api/tokens/evm/transfer.js +8 -4
  6. package/cjs/koni/background/cron.js +2 -2
  7. package/cjs/koni/background/handlers/Extension.js +14 -5
  8. package/cjs/koni/background/handlers/Mobile.js +32 -0
  9. package/cjs/koni/background/handlers/State.js +126 -45
  10. package/cjs/koni/background/subscription.js +2 -2
  11. package/cjs/packageInfo.js +1 -1
  12. package/cjs/services/balance-service/helpers/group.js +53 -0
  13. package/cjs/services/balance-service/helpers/subscribe/balance.js +111 -0
  14. package/cjs/services/balance-service/helpers/subscribe/evm.js +95 -0
  15. package/cjs/services/balance-service/helpers/subscribe/substrate/equilibrium.js +113 -0
  16. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +324 -0
  17. package/cjs/services/balance-service/index.js +41 -16
  18. package/cjs/services/history-service/helpers/subscan-extrinsic-parser-helper.js +7 -1
  19. package/cjs/services/history-service/index.js +12 -8
  20. package/cjs/services/migration-service/scripts/MigrateProvider.js +1 -1
  21. package/cjs/services/storage-service/DatabaseService.js +47 -2
  22. package/cjs/services/storage-service/db-stores/Balance.js +9 -9
  23. package/cjs/services/subscan-service/index.js +66 -22
  24. package/cjs/services/transaction-service/index.js +4 -3
  25. package/cjs/types/balance.js +1 -0
  26. package/cjs/types/index.js +11 -0
  27. package/cjs/utils/{address.js → account.js} +32 -2
  28. package/cjs/utils/eth.js +7 -2
  29. package/cjs/utils/index.js +12 -0
  30. package/constants/index.d.ts +2 -0
  31. package/constants/index.js +2 -0
  32. package/koni/api/staking/bonding/index.js +1 -0
  33. package/koni/api/tokens/evm/balance.js +5 -1
  34. package/koni/api/tokens/evm/transfer.d.ts +1 -1
  35. package/koni/api/tokens/evm/transfer.js +8 -4
  36. package/koni/background/cron.js +3 -3
  37. package/koni/background/handlers/Extension.js +14 -5
  38. package/koni/background/handlers/Mobile.d.ts +5 -1
  39. package/koni/background/handlers/Mobile.js +31 -0
  40. package/koni/background/handlers/State.d.ts +6 -4
  41. package/koni/background/handlers/State.js +114 -34
  42. package/koni/background/subscription.js +2 -2
  43. package/package.json +40 -14
  44. package/packageInfo.js +1 -1
  45. package/services/balance-service/helpers/group.d.ts +9 -0
  46. package/services/balance-service/helpers/group.js +46 -0
  47. package/services/balance-service/helpers/subscribe/balance.d.ts +4 -0
  48. package/services/balance-service/helpers/subscribe/balance.js +103 -0
  49. package/services/balance-service/helpers/subscribe/evm.d.ts +5 -0
  50. package/services/balance-service/helpers/subscribe/evm.js +87 -0
  51. package/services/balance-service/helpers/subscribe/substrate/equilibrium.d.ts +4 -0
  52. package/services/balance-service/helpers/subscribe/substrate/equilibrium.js +105 -0
  53. package/services/balance-service/helpers/subscribe/substrate/index.d.ts +4 -0
  54. package/services/balance-service/helpers/subscribe/substrate/index.js +316 -0
  55. package/services/balance-service/index.d.ts +24 -5
  56. package/services/balance-service/index.js +40 -14
  57. package/services/history-service/helpers/subscan-extrinsic-parser-helper.js +7 -1
  58. package/services/history-service/index.js +12 -8
  59. package/services/migration-service/scripts/MigrateProvider.js +1 -1
  60. package/services/storage-service/DatabaseService.d.ts +7 -2
  61. package/services/storage-service/DatabaseService.js +47 -2
  62. package/services/storage-service/databases/index.d.ts +2 -1
  63. package/services/storage-service/db-stores/Balance.d.ts +2 -2
  64. package/services/storage-service/db-stores/Balance.js +9 -9
  65. package/services/subscan-service/index.d.ts +11 -5
  66. package/services/subscan-service/index.js +66 -26
  67. package/services/subscan-service/types.d.ts +4 -0
  68. package/services/transaction-service/index.js +5 -4
  69. package/types/balance.d.ts +40 -0
  70. package/types/balance.js +1 -0
  71. package/types/index.d.ts +1 -0
  72. package/types/index.js +1 -0
  73. package/utils/account.d.ts +15 -0
  74. package/utils/{address.js → account.js} +28 -0
  75. package/utils/eth.d.ts +1 -0
  76. package/utils/eth.js +4 -0
  77. package/utils/index.d.ts +1 -0
  78. package/utils/index.js +1 -0
  79. package/cjs/koni/api/dotsama/balance.js +0 -464
  80. package/koni/api/dotsama/balance.d.ts +0 -6
  81. package/koni/api/dotsama/balance.js +0 -451
  82. package/utils/address.d.ts +0 -5
@@ -0,0 +1,324 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.subscribeSubstrateBalance = subscribeSubstrateBalance;
7
+ var _types = require("@subwallet/chain-list/types");
8
+ var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
9
+ var _constants = require("@subwallet/extension-base/constants");
10
+ var _wasm = require("@subwallet/extension-base/koni/api/tokens/wasm");
11
+ var _utils = require("@subwallet/extension-base/koni/api/tokens/wasm/utils");
12
+ var _handlers = require("@subwallet/extension-base/koni/background/handlers");
13
+ var _evm = require("@subwallet/extension-base/services/balance-service/helpers/subscribe/evm");
14
+ var _constants2 = require("@subwallet/extension-base/services/chain-service/constants");
15
+ var _utils2 = require("@subwallet/extension-base/services/chain-service/utils");
16
+ var _util = require("@polkadot/util");
17
+ var _equilibrium = require("./equilibrium");
18
+ // Copyright 2019-2022 @subwallet/extension-base
19
+ // SPDX-License-Identifier: Apache-2.0
20
+
21
+ async function subscribeSubstrateBalance(addresses, chainInfo, chain, networkAPI, evmApiMap, callBack) {
22
+ let unsubNativeToken;
23
+ if (!_constants2._BALANCE_CHAIN_GROUP.kintsugi.includes(chain) && !_constants2._BALANCE_CHAIN_GROUP.genshiro.includes(chain) && !_constants2._BALANCE_CHAIN_GROUP.equilibrium_parachain.includes(chain)) {
24
+ unsubNativeToken = await subscribeWithSystemAccountPallet(addresses, chainInfo, networkAPI.api, callBack);
25
+ }
26
+ let unsubLocalToken;
27
+ let unsubEvmContractToken;
28
+ let unsubWasmContractToken;
29
+ try {
30
+ if (_constants2._BALANCE_CHAIN_GROUP.bifrost.includes(chain)) {
31
+ unsubLocalToken = await subscribeTokensAccountsPallet(addresses, chain, networkAPI.api, callBack);
32
+ } else if (_constants2._BALANCE_CHAIN_GROUP.kintsugi.includes(chain)) {
33
+ unsubLocalToken = await subscribeTokensAccountsPallet(addresses, chain, networkAPI.api, callBack, true);
34
+ } else if (_constants2._BALANCE_CHAIN_GROUP.statemine.includes(chain)) {
35
+ unsubLocalToken = await subscribeAssetsAccountPallet(addresses, chain, networkAPI.api, callBack);
36
+ } else if (_constants2._BALANCE_CHAIN_GROUP.genshiro.includes(chain)) {
37
+ unsubLocalToken = await (0, _equilibrium.subscribeEqBalanceAccountPallet)(addresses, chain, networkAPI.api, callBack, true);
38
+ } else if (_constants2._BALANCE_CHAIN_GROUP.equilibrium_parachain.includes(chain)) {
39
+ unsubLocalToken = await (0, _equilibrium.subscribeEquilibriumTokenBalance)(addresses, chain, networkAPI.api, callBack, true);
40
+ } else if (_constants2._BALANCE_CHAIN_GROUP.centrifuge.includes(chain)) {
41
+ unsubLocalToken = await subscribeOrmlTokensPallet(addresses, chain, networkAPI.api, callBack);
42
+ }
43
+ if ((0, _utils2._isChainEvmCompatible)(chainInfo)) {
44
+ unsubEvmContractToken = (0, _evm.subscribeERC20Interval)(addresses, chain, evmApiMap, callBack);
45
+ }
46
+ if ((0, _utils2._checkSmartContractSupportByChain)(chainInfo, _types._AssetType.PSP22)) {
47
+ // Get sub-token for substrate-based chains
48
+ unsubWasmContractToken = subscribePSP22Balance(addresses, chain, networkAPI.api, callBack);
49
+ }
50
+ } catch (err) {
51
+ console.warn(err);
52
+ }
53
+ return () => {
54
+ unsubNativeToken && unsubNativeToken();
55
+ unsubLocalToken && unsubLocalToken();
56
+ unsubEvmContractToken && unsubEvmContractToken();
57
+ unsubWasmContractToken && unsubWasmContractToken();
58
+ };
59
+ }
60
+
61
+ // handler according to different logic
62
+ async function subscribeWithSystemAccountPallet(addresses, chainInfo, networkAPI, callBack) {
63
+ const chainNativeTokenSlug = (0, _utils2._getChainNativeTokenSlug)(chainInfo);
64
+
65
+ // TODO: Need handle case error
66
+ const unsub = await networkAPI.query.system.account.multi(addresses, async balances => {
67
+ const pooledStakingBalances = [];
68
+ if ((0, _utils2._isSubstrateRelayChain)(chainInfo) && networkAPI.query.nominationPools) {
69
+ var _networkAPI$query$nom;
70
+ const poolMemberDatas = await ((_networkAPI$query$nom = networkAPI.query.nominationPools.poolMembers) === null || _networkAPI$query$nom === void 0 ? void 0 : _networkAPI$query$nom.multi(addresses));
71
+ if (poolMemberDatas) {
72
+ for (const _poolMemberData of poolMemberDatas) {
73
+ const poolMemberData = _poolMemberData.toPrimitive();
74
+ if (poolMemberData) {
75
+ let pooled = new _util.BN(poolMemberData.points.toString());
76
+ Object.entries(poolMemberData.unbondingEras).forEach(_ref => {
77
+ let [, amount] = _ref;
78
+ pooled = pooled.add(new _util.BN(amount));
79
+ });
80
+ pooledStakingBalances.push(pooled);
81
+ } else {
82
+ pooledStakingBalances.push(_util.BN_ZERO);
83
+ }
84
+ }
85
+ }
86
+ }
87
+ const items = balances.map((balance, index) => {
88
+ var _balance$data, _balance$data$free, _balance$data2, _balance$data2$reserv, _balance$data3, _balance$data3$miscFr, _balance$data4, _balance$data4$frozen, _balance$data5, _balance$data5$feeFro;
89
+ let total = ((_balance$data = balance.data) === null || _balance$data === void 0 ? void 0 : (_balance$data$free = _balance$data.free) === null || _balance$data$free === void 0 ? void 0 : _balance$data$free.toBn()) || new _util.BN(0);
90
+ const reserved = ((_balance$data2 = balance.data) === null || _balance$data2 === void 0 ? void 0 : (_balance$data2$reserv = _balance$data2.reserved) === null || _balance$data2$reserv === void 0 ? void 0 : _balance$data2$reserv.toBn()) || new _util.BN(0);
91
+ // @ts-ignore
92
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
93
+ const miscFrozen = ((_balance$data3 = balance.data) === null || _balance$data3 === void 0 ? void 0 : (_balance$data3$miscFr = _balance$data3.miscFrozen) === null || _balance$data3$miscFr === void 0 ? void 0 : _balance$data3$miscFr.toBn()) || (balance === null || balance === void 0 ? void 0 : (_balance$data4 = balance.data) === null || _balance$data4 === void 0 ? void 0 : (_balance$data4$frozen = _balance$data4.frozen) === null || _balance$data4$frozen === void 0 ? void 0 : _balance$data4$frozen.toBn()) || new _util.BN(0);
94
+ const feeFrozen = ((_balance$data5 = balance.data) === null || _balance$data5 === void 0 ? void 0 : (_balance$data5$feeFro = _balance$data5.feeFrozen) === null || _balance$data5$feeFro === void 0 ? void 0 : _balance$data5$feeFro.toBn()) || new _util.BN(0);
95
+ let locked = reserved.add(miscFrozen);
96
+ total = total.add(reserved);
97
+ const pooledStakingBalance = pooledStakingBalances[index] || _util.BN_ZERO;
98
+ if (pooledStakingBalance.gt(_util.BN_ZERO)) {
99
+ total = total.add(pooledStakingBalance);
100
+ locked = locked.add(pooledStakingBalance);
101
+ }
102
+ const free = total.sub(locked);
103
+ return {
104
+ address: addresses[index],
105
+ tokenSlug: chainNativeTokenSlug,
106
+ free: free.gte(_util.BN_ZERO) ? free.toString() : '0',
107
+ locked: locked.toString(),
108
+ state: _KoniTypes.APIItemState.READY,
109
+ substrateInfo: {
110
+ miscFrozen: miscFrozen.toString(),
111
+ reserved: reserved.toString(),
112
+ feeFrozen: feeFrozen.toString()
113
+ }
114
+ };
115
+ });
116
+ callBack(items);
117
+ });
118
+ return () => {
119
+ unsub();
120
+ };
121
+ }
122
+ function subscribePSP22Balance(addresses, chain, api, callBack) {
123
+ let tokenList = {};
124
+ const psp22ContractMap = {};
125
+ const getTokenBalances = () => {
126
+ Object.values(tokenList).map(async tokenInfo => {
127
+ try {
128
+ const contract = psp22ContractMap[tokenInfo.slug];
129
+ const balances = await Promise.all(addresses.map(async address => {
130
+ try {
131
+ var _balanceOf$output, _ref2;
132
+ const _balanceOf = await contract.query['psp22::balanceOf'](address, {
133
+ gasLimit: (0, _utils.getDefaultWeightV2)(api)
134
+ }, address);
135
+ const balanceObj = _balanceOf === null || _balanceOf === void 0 ? void 0 : (_balanceOf$output = _balanceOf.output) === null || _balanceOf$output === void 0 ? void 0 : _balanceOf$output.toPrimitive();
136
+ return {
137
+ address: address,
138
+ tokenSlug: tokenInfo.slug,
139
+ free: _balanceOf.output ? (_ref2 = balanceObj.ok) !== null && _ref2 !== void 0 ? _ref2 : balanceObj.Ok : '0',
140
+ locked: '0',
141
+ state: _KoniTypes.APIItemState.READY
142
+ };
143
+ } catch (err) {
144
+ console.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, err);
145
+ return {
146
+ address: address,
147
+ tokenSlug: tokenInfo.slug,
148
+ free: '0',
149
+ locked: '0',
150
+ state: _KoniTypes.APIItemState.READY
151
+ };
152
+ }
153
+ }));
154
+ callBack(balances);
155
+ } catch (err) {
156
+ console.warn(tokenInfo.slug, err); // TODO: error createType
157
+ }
158
+ });
159
+ };
160
+
161
+ tokenList = _handlers.state.getAssetByChainAndAsset(chain, [_types._AssetType.PSP22]);
162
+ Object.entries(tokenList).forEach(_ref3 => {
163
+ let [slug, tokenInfo] = _ref3;
164
+ psp22ContractMap[slug] = (0, _wasm.getPSP22ContractPromise)(api, (0, _utils2._getContractAddressOfToken)(tokenInfo));
165
+ });
166
+ getTokenBalances();
167
+ const interval = setInterval(getTokenBalances, _constants.SUB_TOKEN_REFRESH_BALANCE_INTERVAL);
168
+ return () => {
169
+ clearInterval(interval);
170
+ };
171
+ }
172
+ async function subscribeTokensAccountsPallet(addresses, chain, api, callBack, includeNativeToken) {
173
+ const tokenTypes = includeNativeToken ? [_types._AssetType.NATIVE, _types._AssetType.LOCAL] : [_types._AssetType.LOCAL];
174
+ const tokenMap = _handlers.state.getAssetByChainAndAsset(chain, tokenTypes);
175
+ const unsubList = await Promise.all(Object.values(tokenMap).map(async tokenInfo => {
176
+ try {
177
+ const onChainInfo = (0, _utils2._getTokenOnChainInfo)(tokenInfo);
178
+ const assetId = (0, _utils2._getTokenOnChainAssetId)(tokenInfo);
179
+
180
+ // Get Token Balance
181
+ // @ts-ignore
182
+ return await api.query.tokens.accounts.multi(addresses.map(address => [address, onChainInfo || assetId]), balances => {
183
+ const items = balances.map((balance, index) => {
184
+ const tokenBalance = {
185
+ reserved: balance.reserved || new _util.BN(0),
186
+ frozen: balance.frozen || new _util.BN(0),
187
+ free: balance.free || new _util.BN(0) // free is actually total balance
188
+ };
189
+
190
+ const freeBalance = tokenBalance.free.sub(tokenBalance.frozen);
191
+ const lockedBalance = tokenBalance.frozen.add(tokenBalance.reserved);
192
+ return {
193
+ address: addresses[index],
194
+ tokenSlug: tokenInfo.slug,
195
+ state: _KoniTypes.APIItemState.READY,
196
+ free: freeBalance.toString(),
197
+ locked: lockedBalance.toString(),
198
+ substrateInfo: {
199
+ reserved: tokenBalance.reserved.toString(),
200
+ miscFrozen: tokenBalance.frozen.toString()
201
+ }
202
+ };
203
+ });
204
+ callBack(items);
205
+ });
206
+ } catch (err) {
207
+ console.warn(err);
208
+ }
209
+ return undefined;
210
+ }));
211
+ return () => {
212
+ unsubList.forEach(unsub => {
213
+ unsub && unsub();
214
+ });
215
+ };
216
+ }
217
+ async function subscribeAssetsAccountPallet(addresses, chain, api, callBack) {
218
+ const tokenMap = _handlers.state.getAssetByChainAndAsset(chain, [_types._AssetType.LOCAL]);
219
+ Object.values(tokenMap).forEach(token => {
220
+ if (_constants2._MANTA_ZK_CHAIN_GROUP.includes(token.originChain) && token.symbol.startsWith(_constants2._ZK_ASSET_PREFIX)) {
221
+ delete tokenMap[token.slug];
222
+ }
223
+ });
224
+ const unsubList = await Promise.all(Object.values(tokenMap).map(async tokenInfo => {
225
+ try {
226
+ const assetIndex = (0, _utils2._getTokenOnChainAssetId)(tokenInfo);
227
+
228
+ // Get Token Balance
229
+ return await api.query.assets.account.multi(addresses.map(address => [assetIndex, address]), balances => {
230
+ const items = balances.map((balance, index) => {
231
+ // @ts-ignore
232
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-assignment
233
+ const bdata = balance === null || balance === void 0 ? void 0 : balance.toHuman();
234
+ let frozen = _util.BN_ZERO;
235
+ let total = _util.BN_ZERO;
236
+ if (bdata) {
237
+ // @ts-ignore
238
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument
239
+ const addressBalance = new _util.BN(String(bdata === null || bdata === void 0 ? void 0 : bdata.balance).replaceAll(',', '') || '0');
240
+
241
+ // @ts-ignore
242
+ if (bdata !== null && bdata !== void 0 && bdata.isFrozen) {
243
+ frozen = addressBalance;
244
+ } else {
245
+ total = addressBalance;
246
+ }
247
+ }
248
+ const free = total.sub(frozen);
249
+ return {
250
+ address: addresses[index],
251
+ tokenSlug: tokenInfo.slug,
252
+ free: free.toString(),
253
+ locked: frozen.toString(),
254
+ state: _KoniTypes.APIItemState.READY,
255
+ substrateInfo: {
256
+ miscFrozen: frozen.toString(),
257
+ reserved: '0'
258
+ }
259
+ };
260
+ });
261
+ callBack(items);
262
+ });
263
+ } catch (err) {
264
+ console.warn(err);
265
+ }
266
+ return undefined;
267
+ }));
268
+ return () => {
269
+ unsubList.forEach(unsub => {
270
+ unsub && unsub();
271
+ });
272
+ };
273
+ }
274
+
275
+ // eslint-disable-next-line @typescript-eslint/require-await
276
+ async function subscribeOrmlTokensPallet(addresses, chain, api, callBack) {
277
+ const tokenTypes = [_types._AssetType.LOCAL];
278
+ const tokenMap = _handlers.state.getAssetByChainAndAsset(chain, tokenTypes);
279
+ const unsubList = Object.values(tokenMap).map(async tokenInfo => {
280
+ try {
281
+ const onChainInfo = (0, _utils2._getTokenOnChainInfo)(tokenInfo);
282
+
283
+ // Get Token Balance
284
+ // @ts-ignore
285
+ const unsub = await api.query.ormlTokens.accounts.multi(addresses.map(address => [address, onChainInfo]), balances => {
286
+ const items = balances.map((balance, index) => {
287
+ const tokenBalance = {
288
+ reserved: balance.reserved || new _util.BN(0),
289
+ frozen: balance.frozen || new _util.BN(0),
290
+ free: balance.free || new _util.BN(0) // free is actually total balance
291
+ };
292
+
293
+ // free balance = total balance - frozen misc
294
+ // locked balance = reserved + frozen misc
295
+ const freeBalance = tokenBalance.free.sub(tokenBalance.frozen);
296
+ const lockedBalance = tokenBalance.frozen.add(tokenBalance.reserved);
297
+ return {
298
+ address: addresses[index],
299
+ tokenSlug: tokenInfo.slug,
300
+ state: _KoniTypes.APIItemState.READY,
301
+ free: freeBalance.toString(),
302
+ locked: lockedBalance.toString(),
303
+ substrateInfo: {
304
+ reserved: tokenBalance.reserved.toString(),
305
+ miscFrozen: tokenBalance.frozen.toString()
306
+ }
307
+ };
308
+ });
309
+ callBack(items);
310
+ });
311
+ return unsub;
312
+ } catch (err) {
313
+ console.warn(err);
314
+ return undefined;
315
+ }
316
+ });
317
+ return () => {
318
+ unsubList.forEach(subProm => {
319
+ subProm.then(unsub => {
320
+ unsub && unsub();
321
+ }).catch(console.error);
322
+ });
323
+ };
324
+ }
@@ -6,8 +6,9 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.BalanceService = void 0;
7
7
  var _BalanceError = require("@subwallet/extension-base/background/errors/BalanceError");
8
8
  var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
9
- var _balance = require("@subwallet/extension-base/koni/api/dotsama/balance");
10
- var _handlers = require("@subwallet/extension-base/koni/background/handlers");
9
+ var _group = require("@subwallet/extension-base/services/balance-service/helpers/group");
10
+ var _evm = require("@subwallet/extension-base/services/balance-service/helpers/subscribe/evm");
11
+ var _substrate = require("@subwallet/extension-base/services/balance-service/helpers/subscribe/substrate");
11
12
  var _constants = require("@subwallet/extension-base/services/chain-service/constants");
12
13
  var _utils = require("@subwallet/extension-base/services/chain-service/utils");
13
14
  var _utils2 = require("@subwallet/extension-base/utils");
@@ -15,10 +16,17 @@ var _i18next = require("i18next");
15
16
  // Copyright 2019-2022 @subwallet/extension-base authors & contributors
16
17
  // SPDX-License-Identifier: Apache-2.0
17
18
 
19
+ /**
20
+ * Balance service
21
+ * @class
22
+ */
18
23
  class BalanceService {
19
- constructor(chainService) {
20
- this.chainService = chainService;
21
-
24
+ /**
25
+ * @constructor
26
+ * @param {KoniState} state - The state of extension.
27
+ */
28
+ constructor(state) {
29
+ this.state = state;
22
30
  // Todo: Load data from db to balanceSubject
23
31
  // Todo: Start subscribe balance and data
24
32
  // Todo: Listen change and apply to balanceSubject
@@ -29,9 +37,10 @@ class BalanceService {
29
37
  // Todo: Move everything of fetching balance to this service
30
38
  }
31
39
 
40
+ /* Subscribe token free balance on chain */
32
41
  async subscribeTokenFreeBalance(address, chain, tokenSlug, callback) {
33
- const chainInfo = this.chainService.getChainInfoByKey(chain);
34
- const chainState = this.chainService.getChainStateByKey(chain);
42
+ const chainInfo = this.state.chainService.getChainInfoByKey(chain);
43
+ const chainState = this.state.chainService.getChainStateByKey(chain);
35
44
  if (!chainInfo || !chainState || !chainState.active) {
36
45
  return Promise.reject(new _BalanceError.BalanceError(_KoniTypes.BalanceErrorType.NETWORK_ERROR, (0, _i18next.t)('{{chain}} is inactive. Please enable network', {
37
46
  replace: {
@@ -40,7 +49,7 @@ class BalanceService {
40
49
  })));
41
50
  }
42
51
  const tSlug = tokenSlug || (0, _utils._getChainNativeTokenSlug)(chainInfo);
43
- const tokenInfo = this.chainService.getAssetBySlug(tSlug);
52
+ const tokenInfo = this.state.chainService.getAssetBySlug(tSlug);
44
53
  if (!tokenInfo) {
45
54
  return Promise.reject(new _BalanceError.BalanceError(_KoniTypes.BalanceErrorType.TOKEN_ERROR, (0, _i18next.t)('Transfer is currently not available for this token: {{tSlug}}', {
46
55
  replace: {
@@ -75,35 +84,51 @@ class BalanceService {
75
84
  }, 9999);
76
85
  });
77
86
  }
87
+
88
+ /**
89
+ * @public
90
+ * @async
91
+ * @function getTokenFreeBalance
92
+ * @desc Fetch free balance on chain
93
+ * @param {string} address - Address
94
+ * @param {string} chain - Slug of chain
95
+ * @param {string} [tokenSlug] - Slug of token
96
+ * @return {Promise<AmountData>} - Free token balance of address on chain
97
+ */
78
98
  async getTokenFreeBalance(address, chain, tokenSlug) {
79
99
  const [, balance] = await this.subscribeTokenFreeBalance(address, chain, tokenSlug);
80
100
  return balance;
81
101
  }
82
- subscribeBalance(addresses, chains, callback) {
102
+ subscribeBalance(addresses, chains, _callback) {
83
103
  const [substrateAddresses, evmAddresses] = (0, _utils2.categoryAddresses)(addresses);
84
- const chainInfoMap = this.chainService.getChainInfoMap();
85
- const chainStateMap = this.chainService.getChainStateMap();
86
- const substrateApiMap = this.chainService.getSubstrateApiMap();
87
- const evmApiMap = this.chainService.getEvmApiMap();
104
+ const chainInfoMap = this.state.chainService.getChainInfoMap();
105
+ const chainStateMap = this.state.chainService.getChainStateMap();
106
+ const substrateApiMap = this.state.chainService.getSubstrateApiMap();
107
+ const evmApiMap = this.state.chainService.getEvmApiMap();
88
108
 
89
109
  // Get data from chain or all chains
90
110
  const chainList = chains || Object.keys(chainInfoMap);
91
111
  // Filter active chain only
92
112
  const useChainInfos = chainList.filter(c => chainStateMap[c] && chainStateMap[c].active).map(c => chainInfoMap[c]);
113
+ const callback = items => {
114
+ if (items.length) {
115
+ _callback((0, _group.groupBalance)(items, 'GROUPED', items[0].tokenSlug));
116
+ }
117
+ };
93
118
 
94
119
  // Looping over each chain
95
120
  const unsubList = useChainInfos.map(async chainInfo => {
96
121
  const chainSlug = chainInfo.slug;
97
122
  const useAddresses = (0, _utils._isChainEvmCompatible)(chainInfo) ? evmAddresses : substrateAddresses;
98
123
  if ((0, _utils._isPureEvmChain)(chainInfo)) {
99
- const nativeTokenInfo = _handlers.state.getNativeTokenInfo(chainSlug);
100
- return (0, _balance.subscribeEVMBalance)(chainSlug, useAddresses, evmApiMap, callback, nativeTokenInfo);
124
+ const nativeTokenInfo = this.state.getNativeTokenInfo(chainSlug);
125
+ return (0, _evm.subscribeEVMBalance)(chainSlug, useAddresses, evmApiMap, callback, nativeTokenInfo);
101
126
  }
102
127
  if (!useAddresses || useAddresses.length === 0 || _constants._PURE_EVM_CHAINS.indexOf(chainSlug) > -1) {
103
128
  return undefined;
104
129
  }
105
130
  const networkAPI = await substrateApiMap[chainSlug].isReady;
106
- return (0, _balance.subscribeSubstrateBalance)(useAddresses, chainInfo, chainSlug, networkAPI, evmApiMap, callback);
131
+ return (0, _substrate.subscribeSubstrateBalance)(useAddresses, chainInfo, chainSlug, networkAPI, evmApiMap, callback);
107
132
  });
108
133
  return () => {
109
134
  unsubList.forEach(subProm => {
@@ -20,6 +20,12 @@ function paramJsonParse(item) {
20
20
  return [];
21
21
  }
22
22
  }
23
+ function autoAddPublicKeyPrefix(publicKey) {
24
+ if (!publicKey.startsWith('0x')) {
25
+ return `0x${publicKey}`;
26
+ }
27
+ return publicKey;
28
+ }
23
29
  function balanceTransferParserFunction(item) {
24
30
  const params = paramJsonParse(item);
25
31
  params.forEach(p => {
@@ -27,7 +33,7 @@ function balanceTransferParserFunction(item) {
27
33
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
28
34
  const toPublicKey = p.value.id || p.value.Id;
29
35
  if (toPublicKey) {
30
- item.to = (0, _utilCrypto.encodeAddress)(toPublicKey, 42);
36
+ item.to = (0, _utilCrypto.encodeAddress)(autoAddPublicKeyPrefix(toPublicKey), 42);
31
37
  }
32
38
  } else if (p.name === 'value') {
33
39
  if (item.amount) {
@@ -83,7 +83,7 @@ class HistoryService {
83
83
  const excludeExtrinsicParserKeys = ['balances.transfer_all'];
84
84
 
85
85
  // Note: fetchAllPossibleExtrinsicItems and fetchAllPossibleTransferItems-receive can run parallelly
86
- // Hover, fetchAllPossibleTransferItems-sent must run after fetchAllPossibleExtrinsicItems,
86
+ // However, fetchAllPossibleTransferItems-sent must run after fetchAllPossibleExtrinsicItems,
87
87
  // to avoid "duplicate Extrinsic Hash between items" problem
88
88
 
89
89
  this.subscanService.fetchAllPossibleExtrinsicItems(chain, address, extrinsicItems => {
@@ -104,11 +104,12 @@ class HistoryService {
104
104
  excludeTransferExtrinsicHash.push(x.extrinsic_hash);
105
105
  }
106
106
  });
107
- this.subscanService.fetchAllPossibleTransferItems(chain, address, 'sent', transferItems => {
107
+ this.subscanService.fetchAllPossibleTransferItems(chain, address, 'sent').then(rsMap => {
108
108
  const result = [];
109
- transferItems.forEach(t => {
110
- if (!excludeTransferExtrinsicHash.includes(t.hash)) {
111
- result.push((0, _subscanHistory.parseSubscanTransferData)(address, t, chainInfo));
109
+ Object.keys(rsMap).forEach(hash => {
110
+ // only push item that does not have same hash with another item
111
+ if (!excludeTransferExtrinsicHash.includes(hash) && rsMap[hash].length === 1) {
112
+ result.push((0, _subscanHistory.parseSubscanTransferData)(address, rsMap[hash][0], chainInfo));
112
113
  }
113
114
  });
114
115
  this.addHistoryItems(result).catch(e => {
@@ -120,10 +121,13 @@ class HistoryService {
120
121
  }).catch(e => {
121
122
  console.log('fetchAllPossibleExtrinsicItems error', e);
122
123
  });
123
- this.subscanService.fetchAllPossibleTransferItems(chain, address, 'received', transferItems => {
124
+ this.subscanService.fetchAllPossibleTransferItems(chain, address, 'received').then(rsMap => {
124
125
  const result = [];
125
- transferItems.forEach(t => {
126
- result.push((0, _subscanHistory.parseSubscanTransferData)(address, t, chainInfo));
126
+ Object.keys(rsMap).forEach(hash => {
127
+ // only push item that does not have same hash with another item
128
+ if (rsMap[hash].length === 1) {
129
+ result.push((0, _subscanHistory.parseSubscanTransferData)(address, rsMap[hash][0], chainInfo));
130
+ }
127
131
  });
128
132
  this.addHistoryItems(result).catch(e => {
129
133
  console.log('addHistoryItems in fetchAllPossibleTransferItems-receive error', e);
@@ -14,7 +14,7 @@ class MigrateProvider extends _Base.default {
14
14
  const state = this.state;
15
15
  const chainState = state.getChainStateByKey(this.slug);
16
16
  const chainInfo = state.getChainInfo(this.slug);
17
- if (chainState.active && chainState.currentProvider === this.oldProvider) {
17
+ if (chainState && chainState.active && chainState.currentProvider === this.oldProvider) {
18
18
  await state.upsertChainInfo({
19
19
  mode: 'update',
20
20
  chainEditInfo: {
@@ -13,10 +13,12 @@ var _ChainStakingMetadata = _interopRequireDefault(require("@subwallet/extension
13
13
  var _MantaPay = _interopRequireDefault(require("@subwallet/extension-base/services/storage-service/db-stores/MantaPay"));
14
14
  var _NominatorMetadata = _interopRequireDefault(require("@subwallet/extension-base/services/storage-service/db-stores/NominatorMetadata"));
15
15
  var _utils = require("@subwallet/extension-base/utils");
16
+ var _dexieExportImport = require("dexie-export-import");
16
17
  var _util = require("@polkadot/util");
17
18
  // Copyright 2019-2022 @subwallet/extension-base authors & contributors
18
19
  // SPDX-License-Identifier: Apache-2.0
19
20
 
21
+ const EXPORT_EXCLUDE_TABLES = ['metadata'];
20
22
  class DatabaseService {
21
23
  // TODO: might remove this
22
24
 
@@ -63,14 +65,19 @@ class DatabaseService {
63
65
  async getStoredBalance() {
64
66
  return this.stores.balance.table.toArray();
65
67
  }
66
- async updateBalanceStore(address, item) {
68
+ async updateBalanceStore(item) {
67
69
  if (item.state === _KoniTypes.APIItemState.READY) {
68
70
  return this.stores.balance.upsert({
69
- address,
70
71
  ...item
71
72
  });
72
73
  }
73
74
  }
75
+ async updateBulkBalanceStore(items) {
76
+ const filtered = items.filter(item => item.state !== _KoniTypes.APIItemState.PENDING);
77
+ if (filtered.length) {
78
+ return this.stores.balance.bulkUpsert(filtered);
79
+ }
80
+ }
74
81
  async removeFromBalanceStore(assets) {
75
82
  return this.stores.balance.removeBySlugs(assets);
76
83
  }
@@ -287,5 +294,43 @@ class DatabaseService {
287
294
  upsertCampaign(campaign) {
288
295
  return this.stores.campaign.upsertCampaign(campaign);
289
296
  }
297
+ async exportDB() {
298
+ const blob = await (0, _dexieExportImport.exportDB)(this._db, {
299
+ filter: (table, value, key) => {
300
+ if (EXPORT_EXCLUDE_TABLES.indexOf(table) >= 0) {
301
+ return false;
302
+ }
303
+ return true;
304
+ }
305
+ });
306
+ return await blob.text();
307
+ }
308
+ async importDB(data) {
309
+ try {
310
+ const blob = new Blob([data], {
311
+ type: 'application/json'
312
+ });
313
+ await this._db.import(blob, {
314
+ overwriteValues: true,
315
+ acceptMissingTables: true,
316
+ acceptVersionDiff: true
317
+ });
318
+ return true;
319
+ } catch (e) {
320
+ this.logger.error(e);
321
+ return false;
322
+ }
323
+ }
324
+ async checkImportMetadata(data) {
325
+ try {
326
+ const blob = new Blob([data], {
327
+ type: 'application/json'
328
+ });
329
+ return await (0, _dexieExportImport.peakImportFile)(blob);
330
+ } catch (e) {
331
+ this.logger.error(e);
332
+ return null;
333
+ }
334
+ }
290
335
  }
291
336
  exports.default = DatabaseService;
@@ -10,17 +10,17 @@ var _BaseStoreWithAddress = _interopRequireDefault(require("../db-stores/BaseSto
10
10
  // SPDX-License-Identifier: Apache-2.0
11
11
 
12
12
  class BalanceStore extends _BaseStoreWithAddress.default {
13
- async getBalanceMapByAddress(address) {
14
- const data = await this.table.where('address').equals(address).toArray();
13
+ async getBalanceMapByAddresses(addresses) {
14
+ const data = await this.table.where('address').anyOf(addresses).toArray();
15
15
  const balanceMap = {};
16
16
  data.forEach(storedBalance => {
17
- balanceMap[storedBalance.tokenSlug] = {
18
- tokenSlug: storedBalance.tokenSlug,
19
- state: storedBalance.state,
20
- free: storedBalance.free,
21
- locked: storedBalance.locked,
22
- substrateInfo: storedBalance.substrateInfo,
23
- timestamp: storedBalance.timestamp
17
+ const address = storedBalance.address;
18
+ const slug = storedBalance.tokenSlug;
19
+ if (!balanceMap[address]) {
20
+ balanceMap[address] = {};
21
+ }
22
+ balanceMap[address][slug] = {
23
+ ...storedBalance
24
24
  };
25
25
  });
26
26
  return balanceMap;