@subwallet/extension-base 1.1.51-2 → 1.1.53-0

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 (71) hide show
  1. package/cjs/koni/api/tokens/evm/balance.js +1 -2
  2. package/cjs/koni/api/tokens/evm/transfer.js +3 -5
  3. package/cjs/koni/api/tokens/evm/web3.js +3 -3
  4. package/cjs/koni/background/handlers/Extension.js +5 -4
  5. package/cjs/koni/background/handlers/State.js +8 -71
  6. package/cjs/koni/background/subscription.js +3 -63
  7. package/cjs/packageInfo.js +1 -1
  8. package/cjs/services/balance-service/BalanceMapImpl.js +2 -2
  9. package/cjs/services/balance-service/helpers/index.js +27 -0
  10. package/cjs/services/balance-service/helpers/subscribe/evm.js +33 -15
  11. package/cjs/services/balance-service/helpers/subscribe/{balance.js → index.js} +46 -29
  12. package/cjs/services/balance-service/helpers/subscribe/substrate/equilibrium.js +34 -15
  13. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +157 -72
  14. package/cjs/services/balance-service/index.js +277 -75
  15. package/cjs/services/chain-service/constants.js +2 -1
  16. package/cjs/services/chain-service/health-check/utils/asset-info.js +1 -3
  17. package/cjs/services/chain-service/index.js +1 -9
  18. package/cjs/services/chain-service/utils/patch.js +1 -1
  19. package/cjs/services/earning-service/handlers/liquid-staking/stella-swap.js +2 -2
  20. package/cjs/services/request-service/handler/ConnectWCRequestHandler.js +0 -1
  21. package/cjs/services/storage-service/DatabaseService.js +10 -1
  22. package/cjs/services/wallet-connect-service/helpers.js +1 -1
  23. package/cjs/services/wallet-connect-service/index.js +19 -0
  24. package/cjs/utils/asset.js +19 -0
  25. package/cjs/utils/eth/parseTransaction/index.js +1 -1
  26. package/cjs/utils/index.js +12 -0
  27. package/koni/api/tokens/evm/balance.d.ts +1 -1
  28. package/koni/api/tokens/evm/balance.js +1 -2
  29. package/koni/api/tokens/evm/transfer.d.ts +2 -2
  30. package/koni/api/tokens/evm/transfer.js +3 -5
  31. package/koni/api/tokens/evm/web3.d.ts +1 -1
  32. package/koni/api/tokens/evm/web3.js +2 -2
  33. package/koni/background/handlers/Extension.js +5 -4
  34. package/koni/background/handlers/State.d.ts +1 -12
  35. package/koni/background/handlers/State.js +9 -72
  36. package/koni/background/subscription.d.ts +1 -5
  37. package/koni/background/subscription.js +1 -60
  38. package/package.json +23 -13
  39. package/packageInfo.js +1 -1
  40. package/services/balance-service/BalanceMapImpl.js +1 -1
  41. package/services/balance-service/helpers/index.d.ts +2 -0
  42. package/services/balance-service/helpers/index.js +5 -0
  43. package/services/balance-service/helpers/subscribe/evm.d.ts +3 -5
  44. package/services/balance-service/helpers/subscribe/evm.js +31 -14
  45. package/services/balance-service/helpers/subscribe/{balance.d.ts → index.d.ts} +2 -2
  46. package/services/balance-service/helpers/subscribe/{balance.js → index.js} +41 -28
  47. package/services/balance-service/helpers/subscribe/substrate/equilibrium.d.ts +3 -4
  48. package/services/balance-service/helpers/subscribe/substrate/equilibrium.js +29 -13
  49. package/services/balance-service/helpers/subscribe/substrate/index.d.ts +2 -2
  50. package/services/balance-service/helpers/subscribe/substrate/index.js +144 -67
  51. package/services/balance-service/index.d.ts +64 -6
  52. package/services/balance-service/index.js +279 -77
  53. package/services/chain-service/constants.js +2 -1
  54. package/services/chain-service/health-check/utils/asset-info.js +1 -3
  55. package/services/chain-service/index.js +2 -10
  56. package/services/chain-service/utils/patch.js +1 -1
  57. package/services/earning-service/handlers/liquid-staking/stella-swap.js +2 -2
  58. package/services/request-service/handler/ConnectWCRequestHandler.js +0 -1
  59. package/services/storage-service/DatabaseService.js +7 -1
  60. package/services/wallet-connect-service/helpers.js +1 -1
  61. package/services/wallet-connect-service/index.d.ts +1 -0
  62. package/services/wallet-connect-service/index.js +19 -1
  63. package/types/{balance.d.ts → balance/index.d.ts} +16 -0
  64. package/types/index.js +1 -1
  65. package/utils/asset.d.ts +2 -0
  66. package/utils/asset.js +12 -0
  67. package/utils/eth/parseTransaction/index.js +1 -1
  68. package/utils/index.d.ts +1 -0
  69. package/utils/index.js +1 -0
  70. /package/cjs/types/{balance.js → balance/index.js} +0 -0
  71. /package/types/{balance.js → balance/index.js} +0 -0
@@ -1,25 +1,50 @@
1
1
  import { AmountData, DetectBalanceCache } from '@subwallet/extension-base/background/KoniTypes';
2
2
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
3
- import { BalanceItem } from '@subwallet/extension-base/types';
3
+ import { ServiceStatus, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
4
+ import { EventItem, EventType } from '@subwallet/extension-base/services/event-service/types';
5
+ import { BalanceItem, BalanceJson } from '@subwallet/extension-base/types';
6
+ import { PromiseHandler } from '@subwallet/extension-base/utils';
7
+ import { BehaviorSubject } from 'rxjs';
4
8
  /**
5
9
  * Balance service
6
10
  * @class
7
11
  */
8
- export declare class BalanceService {
9
- private readonly state;
12
+ export declare class BalanceService implements StoppableServiceInterface {
13
+ private state;
14
+ private balanceMap;
15
+ private balanceUpdateCache;
16
+ startPromiseHandler: PromiseHandler<void>;
17
+ stopPromiseHandler: PromiseHandler<void>;
18
+ status: ServiceStatus;
19
+ private isReload;
10
20
  private readonly detectAccountBalanceStore;
11
21
  private readonly balanceDetectSubject;
12
22
  private readonly intervalTime;
13
23
  private readonly cacheTime;
14
- private readonly startHandler;
15
24
  /**
16
25
  * @constructor
17
26
  * @param {KoniState} state - The state of extension.
18
27
  */
19
28
  constructor(state: KoniState);
20
- startDetectBalance(): Promise<void>;
29
+ /** Init service */
30
+ init(): Promise<void>;
31
+ /** Restore balance map */
32
+ loadData(): Promise<void>;
33
+ /** Start service */
34
+ start(): Promise<void>;
35
+ /** Stop service */
36
+ stop(): Promise<void>;
37
+ /** Wait service start */
38
+ waitForStarted(): Promise<void>;
39
+ /** Wait service stop */
40
+ waitForStopped(): Promise<void>;
41
+ /**
42
+ * Handle when data change
43
+ * */
44
+ handleEvents(events: EventItem<EventType>[], eventTypes: EventType[]): void;
21
45
  getBalanceDetectCache(update: (value: DetectBalanceCache) => void): void;
22
46
  setBalanceDetectCache(addresses: string[]): void;
47
+ /** Subscribe token free balance of a address on chain */
23
48
  subscribeTokenFreeBalance(address: string, chain: string, tokenSlug: string | undefined, callback?: (rs: AmountData) => void): Promise<[() => void, AmountData]>;
24
49
  /**
25
50
  * @public
@@ -32,6 +57,39 @@ export declare class BalanceService {
32
57
  * @return {Promise<AmountData>} - Free token balance of address on chain
33
58
  */
34
59
  getTokenFreeBalance(address: string, chain: string, tokenSlug?: string): Promise<AmountData>;
35
- subscribeBalance(addresses: string[], chains: string[] | null, _callback: (rs: BalanceItem) => void): () => void;
60
+ /** Remove balance from the subject object by addresses */
61
+ removeBalanceByAddresses(addresses: string[]): void;
62
+ /** Remove inactive asset from the balance map */
63
+ removeInactiveChainBalances(): Promise<void>;
64
+ getBalance(reset?: boolean): Promise<BalanceJson>;
65
+ /** Get stored balance from db */
66
+ getStoredBalance(address: string): Promise<BalanceItem[]>;
67
+ handleResetBalance(forceRefresh?: boolean): Promise<void>;
68
+ /**
69
+ * Update value for balance map
70
+ * Note: items must be same tokenSlug */
71
+ setBalanceItem(items: BalanceItem[]): void;
72
+ /**
73
+ * Store balance map to db
74
+ * */
75
+ private updateBalanceStore;
76
+ /**
77
+ * Subscribe balance map with subject object
78
+ * */
79
+ subscribeBalanceMap(): BehaviorSubject<import("@subwallet/extension-base/types").BalanceMap>;
80
+ /** Subscribe area */
81
+ private _unsubscribeBalance;
82
+ /** Subscribe balance subscription */
83
+ runSubscribeBalances(): Promise<void>;
84
+ /** Unsubscribe balance subscription */
85
+ runUnsubscribeBalances(): void;
86
+ /** Reload balance subscription */
87
+ reloadBalance(): Promise<void>;
88
+ /** Subscribe area */
36
89
  autoEnableChains(addresses: string[]): Promise<void>;
90
+ private _intervalScan;
91
+ private _unsubscribeBalanceDetectCache;
92
+ private startBalanceDetectCache;
93
+ private startScanBalance;
94
+ private stopScanBalance;
37
95
  }
@@ -3,73 +3,144 @@
3
3
 
4
4
  import { BalanceError } from '@subwallet/extension-base/background/errors/BalanceError';
5
5
  import { BalanceErrorType } from '@subwallet/extension-base/background/KoniTypes';
6
- import { groupBalance } from '@subwallet/extension-base/services/balance-service/helpers/group';
7
- import { subscribeEVMBalance } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/evm';
8
- import { subscribeSubstrateBalance } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/substrate';
9
- import { _PURE_EVM_CHAINS } from '@subwallet/extension-base/services/chain-service/constants';
10
- import { _getChainNativeTokenSlug, _isChainEvmCompatible, _isPureEvmChain } from '@subwallet/extension-base/services/chain-service/utils';
6
+ import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants';
7
+ import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
8
+ import { _getChainNativeTokenSlug } from '@subwallet/extension-base/services/chain-service/utils';
11
9
  import DetectAccountBalanceStore from '@subwallet/extension-base/stores/DetectAccountBalance';
12
- import { categoryAddresses, createPromiseHandler } from '@subwallet/extension-base/utils';
10
+ import { addLazy, createPromiseHandler, isAccountAll, waitTimeout } from '@subwallet/extension-base/utils';
13
11
  import keyring from '@subwallet/ui-keyring';
14
12
  import { t } from 'i18next';
15
13
  import { BehaviorSubject } from 'rxjs';
16
14
  import { noop } from '@polkadot/util';
15
+ import { BalanceMapImpl } from "./BalanceMapImpl.js";
16
+ import { subscribeBalance } from "./helpers/index.js";
17
17
 
18
18
  /**
19
19
  * Balance service
20
20
  * @class
21
21
  */
22
22
  export class BalanceService {
23
+ balanceUpdateCache = [];
24
+ startPromiseHandler = createPromiseHandler();
25
+ stopPromiseHandler = createPromiseHandler();
26
+ status = ServiceStatus.NOT_INITIALIZED;
27
+ isReload = false;
23
28
  detectAccountBalanceStore = new DetectAccountBalanceStore();
24
29
  balanceDetectSubject = new BehaviorSubject({});
25
30
  intervalTime = 3 * 60 * 1000;
26
31
  cacheTime = 15 * 60 * 1000;
32
+
27
33
  /**
28
34
  * @constructor
29
35
  * @param {KoniState} state - The state of extension.
30
36
  */
31
37
  constructor(state) {
32
38
  this.state = state;
33
- // Todo: Load data from db to balanceSubject
34
- // Todo: Start subscribe balance and data
35
- // Todo: Listen change and apply to balanceSubject
36
- // Todo: Active/Chain
37
- // Todo: Add/remove account
38
- // Todo: Add new account
39
- // Todo: Optimize get balance for single account and chain with cache
40
- // Todo: Move everything of fetching balance to this service
41
-
42
- this.startHandler = createPromiseHandler();
43
- const updateBalanceDetectCache = value => {
44
- this.startHandler.resolve();
45
- this.balanceDetectSubject.next(value || {});
46
- };
47
- this.getBalanceDetectCache(updateBalanceDetectCache);
48
- this.detectAccountBalanceStore.getSubject().subscribe({
49
- next: updateBalanceDetectCache
50
- });
51
- this.startDetectBalance().catch(console.error);
39
+ this.balanceMap = new BalanceMapImpl();
52
40
  }
53
- async startDetectBalance() {
54
- const scanBalance = () => {
55
- const addresses = keyring.getPairs().map(account => account.address);
56
- const cache = this.balanceDetectSubject.value;
57
- const now = Date.now();
58
- const needDetectAddresses = [];
59
- for (const address of addresses) {
60
- if (!cache[address] || now - cache[address] > this.cacheTime) {
61
- needDetectAddresses.push(address);
62
- }
41
+
42
+ /** Init service */
43
+ async init() {
44
+ this.status = ServiceStatus.INITIALIZING;
45
+ await this.state.eventService.waitChainReady;
46
+ await this.state.eventService.waitAccountReady;
47
+
48
+ // Load data from db to balanceSubject
49
+ await this.loadData();
50
+ this.status = ServiceStatus.INITIALIZED;
51
+
52
+ // Start service
53
+ await this.start();
54
+
55
+ // Handle events
56
+ this.state.eventService.onLazy(this.handleEvents.bind(this));
57
+ }
58
+
59
+ /** Restore balance map */
60
+ async loadData() {
61
+ const backupBalanceData = await this.state.dbService.getStoredBalance();
62
+ this.balanceMap.updateBalanceItems(backupBalanceData, true);
63
+ }
64
+
65
+ /** Start service */
66
+ async start() {
67
+ if (this.status === ServiceStatus.STOPPING) {
68
+ await this.waitForStopped();
69
+ }
70
+ if (this.status === ServiceStatus.STARTED || this.status === ServiceStatus.STARTING) {
71
+ return await this.waitForStarted();
72
+ }
73
+ this.status = ServiceStatus.STARTING;
74
+ await this.startScanBalance();
75
+
76
+ // Run subscribe balance
77
+ await this.runSubscribeBalances();
78
+
79
+ // Update status
80
+ this.stopPromiseHandler = createPromiseHandler();
81
+ this.status = ServiceStatus.STARTED;
82
+ this.startPromiseHandler.resolve();
83
+ }
84
+
85
+ /** Stop service */
86
+ async stop() {
87
+ if (this.status === ServiceStatus.STARTING) {
88
+ await this.waitForStarted();
89
+ }
90
+ if (this.status === ServiceStatus.STOPPED || this.status === ServiceStatus.STOPPING) {
91
+ return await this.waitForStopped();
92
+ }
93
+ this.runUnsubscribeBalances();
94
+ this.stopScanBalance();
95
+
96
+ // Update status
97
+ this.startPromiseHandler = createPromiseHandler();
98
+ this.status = ServiceStatus.STOPPING;
99
+ this.stopPromiseHandler.resolve();
100
+ }
101
+
102
+ /** Wait service start */
103
+ waitForStarted() {
104
+ return this.startPromiseHandler.promise;
105
+ }
106
+
107
+ /** Wait service stop */
108
+ waitForStopped() {
109
+ return this.stopPromiseHandler.promise;
110
+ }
111
+
112
+ /**
113
+ * Handle when data change
114
+ * */
115
+ handleEvents(events, eventTypes) {
116
+ const removedAddresses = [];
117
+ let needReload = false;
118
+ let lazyTime = 2000;
119
+
120
+ // Account changed or chain changed (active or inactive)
121
+ if (eventTypes.includes('account.updateCurrent') || eventTypes.includes('account.add') || eventTypes.includes('chain.updateState') || eventTypes.includes('asset.updateState')) {
122
+ needReload = true;
123
+ if (eventTypes.includes('account.updateCurrent')) {
124
+ lazyTime = 1000;
63
125
  }
64
- if (needDetectAddresses.length) {
65
- this.autoEnableChains(needDetectAddresses).finally(noop);
126
+ }
127
+ events.forEach(event => {
128
+ if (event.type === 'account.remove') {
129
+ removedAddresses.push(event.data[0]);
130
+ lazyTime = 1000;
66
131
  }
67
- };
68
- await this.state.eventService.waitAccountReady;
69
- await this.state.eventService.waitChainReady;
70
- await this.startHandler.promise;
71
- scanBalance();
72
- setInterval(scanBalance, this.intervalTime);
132
+ });
133
+ if (removedAddresses.length > 0) {
134
+ this.balanceMap.removeBalanceItems([...removedAddresses, ALL_ACCOUNT_KEY]); // Add all account key to recalculate all account balances
135
+ needReload = true;
136
+ }
137
+ if (needReload) {
138
+ addLazy('reloadBalanceByEvents', () => {
139
+ if (!this.isReload) {
140
+ this.runSubscribeBalances().catch(console.error);
141
+ }
142
+ }, lazyTime, undefined, true);
143
+ }
73
144
  }
74
145
  getBalanceDetectCache(update) {
75
146
  this.detectAccountBalanceStore.get('DetectBalanceCache', value => {
@@ -88,7 +159,7 @@ export class BalanceService {
88
159
  });
89
160
  }
90
161
 
91
- /* Subscribe token free balance on chain */
162
+ /** Subscribe token free balance of a address on chain */
92
163
  async subscribeTokenFreeBalance(address, chain, tokenSlug, callback) {
93
164
  const chainInfo = this.state.chainService.getChainInfoByKey(chain);
94
165
  const chainState = this.state.chainService.getChainStateByKey(chain);
@@ -110,7 +181,12 @@ export class BalanceService {
110
181
  }
111
182
  return new Promise((resolve, reject) => {
112
183
  let hasError = true;
113
- const unsub = this.subscribeBalance([address], [chain], rs => {
184
+ const assetMap = this.state.chainService.getAssetRegistry();
185
+ const chainInfoMap = this.state.chainService.getChainInfoMap();
186
+ const evmApiMap = this.state.chainService.getEvmApiMap();
187
+ const substrateApiMap = this.state.chainService.getSubstrateApiMap();
188
+ const unsub = subscribeBalance([address], [chain], [tSlug], assetMap, chainInfoMap, substrateApiMap, evmApiMap, result => {
189
+ const rs = result[0];
114
190
  if (rs.tokenSlug === tSlug) {
115
191
  hasError = false;
116
192
  const balance = {
@@ -150,45 +226,131 @@ export class BalanceService {
150
226
  const [, balance] = await this.subscribeTokenFreeBalance(address, chain, tokenSlug);
151
227
  return balance;
152
228
  }
153
- subscribeBalance(addresses, chains, _callback) {
154
- const [substrateAddresses, evmAddresses] = categoryAddresses(addresses);
155
- const chainInfoMap = this.state.chainService.getChainInfoMap();
156
- const chainStateMap = this.state.chainService.getChainStateMap();
157
- const substrateApiMap = this.state.chainService.getSubstrateApiMap();
158
- const evmApiMap = this.state.chainService.getEvmApiMap();
159
229
 
160
- // Get data from chain or all chains
161
- const chainList = chains || Object.keys(chainInfoMap);
162
- // Filter active chain only
163
- const useChainInfos = chainList.filter(c => chainStateMap[c] && chainStateMap[c].active).map(c => chainInfoMap[c]);
164
- const callback = items => {
165
- if (items.length) {
166
- _callback(groupBalance(items, 'GROUPED', items[0].tokenSlug));
167
- }
230
+ /** Remove balance from the subject object by addresses */
231
+ removeBalanceByAddresses(addresses) {
232
+ this.balanceMap.removeBalanceItems([...addresses, ALL_ACCOUNT_KEY]);
233
+ }
234
+
235
+ /** Remove inactive asset from the balance map */
236
+ async removeInactiveChainBalances() {
237
+ const assetSettings = await this.state.chainService.getAssetSettings();
238
+ this.balanceMap.removeBalanceItemByFilter(item => {
239
+ return !assetSettings[item.tokenSlug];
240
+ });
241
+ }
242
+ async getBalance(reset) {
243
+ await this.removeInactiveChainBalances();
244
+ return {
245
+ details: this.balanceMap.map,
246
+ reset
168
247
  };
248
+ }
169
249
 
170
- // Looping over each chain
171
- const unsubList = useChainInfos.map(async chainInfo => {
172
- const chainSlug = chainInfo.slug;
173
- const useAddresses = _isChainEvmCompatible(chainInfo) ? evmAddresses : substrateAddresses;
174
- if (_isPureEvmChain(chainInfo)) {
175
- const nativeTokenInfo = this.state.getNativeTokenInfo(chainSlug);
176
- return subscribeEVMBalance(chainSlug, useAddresses, evmApiMap, callback, nativeTokenInfo);
177
- }
178
- if (!useAddresses || useAddresses.length === 0 || _PURE_EVM_CHAINS.indexOf(chainSlug) > -1) {
179
- return undefined;
250
+ /** Get stored balance from db */
251
+ async getStoredBalance(address) {
252
+ return await this.state.dbService.stores.balance.getBalanceMapByAddresses(address);
253
+ }
254
+ async handleResetBalance(forceRefresh) {
255
+ if (forceRefresh) {
256
+ this.balanceMap.setData({});
257
+ await this.state.dbService.stores.balance.clear();
258
+ } else {
259
+ await Promise.all([this.removeInactiveChainBalances()]);
260
+ }
261
+ }
262
+
263
+ /**
264
+ * Update value for balance map
265
+ * Note: items must be same tokenSlug */
266
+ setBalanceItem(items) {
267
+ if (items.length) {
268
+ const nowTime = new Date().getTime();
269
+ for (const item of items) {
270
+ const balance = {
271
+ timestamp: nowTime,
272
+ ...item
273
+ };
274
+ this.balanceUpdateCache.push(balance);
180
275
  }
181
- const networkAPI = await substrateApiMap[chainSlug].isReady;
182
- return subscribeSubstrateBalance(useAddresses, chainInfo, chainSlug, networkAPI, evmApiMap, callback);
276
+ addLazy('updateBalanceStore', () => {
277
+ const isAllAccount = isAccountAll(this.state.keyringService.currentAccount.address);
278
+ this.balanceMap.updateBalanceItems(this.balanceUpdateCache, isAllAccount);
279
+ if (isAllAccount) {
280
+ this.balanceUpdateCache = [...this.balanceUpdateCache, ...Object.values(this.balanceMap.map[ALL_ACCOUNT_KEY])];
281
+ }
282
+ this.updateBalanceStore(this.balanceUpdateCache);
283
+ this.balanceUpdateCache = [];
284
+ }, 300, 1800);
285
+ }
286
+ }
287
+
288
+ /**
289
+ * Store balance map to db
290
+ * */
291
+ updateBalanceStore(items) {
292
+ this.state.dbService.updateBulkBalanceStore(items).catch(console.warn);
293
+ }
294
+
295
+ /**
296
+ * Subscribe balance map with subject object
297
+ * */
298
+ subscribeBalanceMap() {
299
+ return this.balanceMap.mapSubject;
300
+ }
301
+
302
+ /** Subscribe area */
303
+
304
+ /** Subscribe balance subscription */
305
+ async runSubscribeBalances() {
306
+ await Promise.all([this.state.eventService.waitKeyringReady, this.state.eventService.waitChainReady]);
307
+ this.runUnsubscribeBalances();
308
+ const addresses = this.state.getDecodedAddresses();
309
+ if (!addresses.length) {
310
+ return;
311
+ }
312
+
313
+ // Reset balance before subscribe
314
+ await this.handleResetBalance();
315
+ let cancel = false;
316
+ const assetMap = this.state.chainService.getAssetRegistry();
317
+ const chainInfoMap = this.state.chainService.getChainInfoMap();
318
+ const evmApiMap = this.state.chainService.getEvmApiMap();
319
+ const substrateApiMap = this.state.chainService.getSubstrateApiMap();
320
+ const activeChainSlugs = Object.keys(this.state.getActiveChainInfoMap());
321
+ const assetState = this.state.chainService.subscribeAssetSettings().value;
322
+ const assets = Object.values(assetMap).filter(asset => {
323
+ var _assetState$asset$slu;
324
+ return activeChainSlugs.includes(asset.originChain) && ((_assetState$asset$slu = assetState[asset.slug]) === null || _assetState$asset$slu === void 0 ? void 0 : _assetState$asset$slu.visible);
325
+ }).map(asset => asset.slug);
326
+ const unsub = subscribeBalance(addresses, activeChainSlugs, assets, assetMap, chainInfoMap, substrateApiMap, evmApiMap, result => {
327
+ !cancel && this.setBalanceItem(result);
183
328
  });
184
- return () => {
185
- unsubList.forEach(subProm => {
186
- subProm.then(unsub => {
187
- unsub && unsub();
188
- }).catch(console.error);
189
- });
329
+ const unsub2 = this.state.subscribeMantaPayBalance();
330
+ this._unsubscribeBalance = () => {
331
+ cancel = true;
332
+ unsub && unsub();
333
+ unsub2 && unsub2();
190
334
  };
191
335
  }
336
+
337
+ /** Unsubscribe balance subscription */
338
+ runUnsubscribeBalances() {
339
+ this._unsubscribeBalance && this._unsubscribeBalance();
340
+ this._unsubscribeBalance = undefined;
341
+ }
342
+
343
+ /** Reload balance subscription */
344
+ async reloadBalance() {
345
+ this.isReload = true;
346
+ await this.handleResetBalance(true);
347
+ await this.runSubscribeBalances();
348
+ await waitTimeout(1800);
349
+ this.isReload = false;
350
+ }
351
+
352
+ /** Subscribe area */
353
+
192
354
  async autoEnableChains(addresses) {
193
355
  this.setBalanceDetectCache(addresses);
194
356
  const assetMap = this.state.chainService.getAssetRegistry();
@@ -257,4 +419,44 @@ export class BalanceService {
257
419
  });
258
420
  }
259
421
  }
422
+ async startScanBalance() {
423
+ var _this$startBalanceDet2;
424
+ await Promise.all([this.state.eventService.waitAccountReady, this.state.eventService.waitChainReady]);
425
+ this.stopScanBalance();
426
+ this.startBalanceDetectCache = createPromiseHandler();
427
+ const updateBalanceDetectCache = value => {
428
+ var _this$startBalanceDet;
429
+ (_this$startBalanceDet = this.startBalanceDetectCache) === null || _this$startBalanceDet === void 0 ? void 0 : _this$startBalanceDet.resolve();
430
+ this.balanceDetectSubject.next(value || {});
431
+ };
432
+ this.getBalanceDetectCache(updateBalanceDetectCache);
433
+ const subscription = this.detectAccountBalanceStore.getSubject().subscribe({
434
+ next: updateBalanceDetectCache
435
+ });
436
+ this._unsubscribeBalanceDetectCache = subscription.unsubscribe;
437
+ const scanBalance = () => {
438
+ const addresses = keyring.getPairs().map(account => account.address);
439
+ const cache = this.balanceDetectSubject.value;
440
+ const now = Date.now();
441
+ const needDetectAddresses = [];
442
+ for (const address of addresses) {
443
+ if (!cache[address] || now - cache[address] > this.cacheTime) {
444
+ needDetectAddresses.push(address);
445
+ }
446
+ }
447
+ if (needDetectAddresses.length) {
448
+ this.autoEnableChains(needDetectAddresses).finally(noop);
449
+ }
450
+ };
451
+ await ((_this$startBalanceDet2 = this.startBalanceDetectCache) === null || _this$startBalanceDet2 === void 0 ? void 0 : _this$startBalanceDet2.promise);
452
+ scanBalance();
453
+ this._intervalScan = setInterval(scanBalance, this.intervalTime);
454
+ }
455
+ stopScanBalance() {
456
+ this._intervalScan && clearInterval(this._intervalScan);
457
+ this._unsubscribeBalanceDetectCache && this._unsubscribeBalanceDetectCache();
458
+ this._intervalScan = undefined;
459
+ this._unsubscribeBalanceDetectCache = undefined;
460
+ this.startBalanceDetectCache = undefined;
461
+ }
260
462
  }
@@ -240,7 +240,8 @@ export const _DEFAULT_ACTIVE_CHAINS = [..._DEFAULT_CHAINS, 'vara_network'];
240
240
  export const EVM_PASS_CONNECT_STATUS = {
241
241
  arbitrum_one: ['*'],
242
242
  okxTest: ['*'],
243
- astarZkEvm: ['*']
243
+ astarZkEvm: ['*'],
244
+ xlayer: ['*']
244
245
  };
245
246
  export const EVM_REFORMAT_DECIMALS = {
246
247
  acala: ['acala_evm', 'karura_evm']
@@ -216,9 +216,7 @@ export const getEvmNativeInfo = async api => {
216
216
  };
217
217
  export const getErc20AssetInfo = async (asset, api) => {
218
218
  const contractAddress = _getContractAddressOfToken(asset);
219
- const tokenContract = getERC20Contract('chain', contractAddress, {
220
- chain: api
221
- });
219
+ const tokenContract = getERC20Contract(contractAddress, api);
222
220
  const [_decimals, _symbol, _name] = await Promise.all([
223
221
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
224
222
  tokenContract.methods.decimals().call(),
@@ -11,7 +11,7 @@ import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chai
11
11
  import { _ChainConnectionStatus, _CUSTOM_PREFIX, _NFT_CONTRACT_STANDARDS, _SMART_CONTRACT_STANDARDS } from '@subwallet/extension-base/services/chain-service/types';
12
12
  import { _isAssetAutoEnable, _isAssetFungibleToken, _isChainEnabled, _isCustomAsset, _isCustomChain, _isCustomProvider, _isEqualContractAddress, _isEqualSmartContractAsset, _isMantaZkAsset, _isPureEvmChain, _isPureSubstrateChain, _parseAssetRefKey, fetchPatchData, randomizeProvider, updateLatestChainInfo } from '@subwallet/extension-base/services/chain-service/utils';
13
13
  import AssetSettingStore from '@subwallet/extension-base/stores/AssetSetting';
14
- import { addLazy, fetchStaticData, MODULE_SUPPORT } from '@subwallet/extension-base/utils';
14
+ import { addLazy, fetchStaticData, filterAssetsByChainAndType, MODULE_SUPPORT } from '@subwallet/extension-base/utils';
15
15
  import { BehaviorSubject, Subject } from 'rxjs';
16
16
  import Web3 from 'web3';
17
17
  import { logger as createLogger } from '@polkadot/util/logger';
@@ -271,13 +271,7 @@ export class ChainService {
271
271
  return destinationTokenInfo;
272
272
  }
273
273
  getAssetByChainAndType(chainSlug, assetTypes) {
274
- const result = {};
275
- Object.values(this.getAssetRegistry()).forEach(assetInfo => {
276
- if (assetTypes.includes(assetInfo.assetType) && assetInfo.originChain === chainSlug) {
277
- result[assetInfo.slug] = assetInfo;
278
- }
279
- });
280
- return result;
274
+ return filterAssetsByChainAndType(this.getAssetRegistry(), chainSlug, assetTypes);
281
275
  }
282
276
  getSmartContractNfts() {
283
277
  const result = [];
@@ -561,8 +555,6 @@ export class ChainService {
561
555
  const chainState = chainStateMap[originChain];
562
556
  if (!assetState) {
563
557
  // If this asset not has asset setting, this token is not enabled before (not turned off before)
564
- // @ts-ignore
565
- // TODO: Merge issue detect balance to define manualTurnOff props
566
558
  if (!chainState || !chainState.manualTurnOff) {
567
559
  await this.updateAssetSetting(assetSlug, {
568
560
  visible: true
@@ -5,7 +5,7 @@ import fetch from 'cross-fetch';
5
5
  const PRODUCTION_BRANCHES = ['master', 'webapp', 'webapp-dev'];
6
6
  const branchName = process.env.BRANCH_NAME || 'subwallet-dev';
7
7
  const fetchDomain = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'https://chain-list-assets.subwallet.app' : 'https://dev.sw-chain-list-assets.pages.dev';
8
- const ChainListVersion = '0.2.53';
8
+ const ChainListVersion = '0.2.54';
9
9
  export async function fetchPatchData(slug) {
10
10
  try {
11
11
  const fetchPromise = fetch(`${fetchDomain}/patch/${ChainListVersion}/${slug}`);
@@ -192,7 +192,7 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
192
192
  const derivativeTokenInfo = this.state.getAssetBySlug(derivativeTokenSlug);
193
193
  const inputTokenSlug = this.inputAsset;
194
194
  const inputTokenInfo = this.state.getAssetBySlug(inputTokenSlug);
195
- const inputTokenContract = getERC20Contract(this.chain, _getContractAddressOfToken(inputTokenInfo), this.state.getEvmApiMap());
195
+ const inputTokenContract = getERC20Contract(_getContractAddressOfToken(inputTokenInfo), evmApi);
196
196
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
197
197
  const allowanceCall = inputTokenContract.methods.allowance(params.address, _getContractAddressOfToken(derivativeTokenInfo));
198
198
  const [allowance, gasPrice] = await Promise.all([
@@ -257,7 +257,7 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
257
257
  const derivativeTokenInfo = this.state.getAssetBySlug(this.derivativeAssets[0]);
258
258
  const derivativeTokenContractAddress = _getContractAddressOfToken(derivativeTokenInfo);
259
259
  const evmApi = this.evmApi;
260
- const inputTokenContract = getERC20Contract(this.chain, _getContractAddressOfToken(inputTokenInfo), this.state.getEvmApiMap());
260
+ const inputTokenContract = getERC20Contract(_getContractAddressOfToken(inputTokenInfo), evmApi);
261
261
 
262
262
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
263
263
  const approveCall = inputTokenContract.methods.approve(derivativeTokenContractAddress, MAX_INT); // TODO: need test
@@ -51,7 +51,6 @@ export default class ConnectWCRequestHandler {
51
51
  ...request
52
52
  };
53
53
  this.updateIconConnectWC();
54
- this.#requestService.popupOpen();
55
54
  }
56
55
  resetWallet() {
57
56
  for (const request of Object.values(this.#connectWCRequests)) {
@@ -11,6 +11,7 @@ import NominatorMetadataStore from '@subwallet/extension-base/services/storage-s
11
11
  import YieldPoolStore from '@subwallet/extension-base/services/storage-service/db-stores/YieldPoolStore';
12
12
  import YieldPositionStore from '@subwallet/extension-base/services/storage-service/db-stores/YieldPositionStore';
13
13
  import { reformatAddress } from '@subwallet/extension-base/utils';
14
+ import keyring from '@subwallet/ui-keyring';
14
15
  import { exportDB } from 'dexie-export-import';
15
16
  import { logger as createLogger } from '@polkadot/util';
16
17
  export const DEXIE_BACKUP_TABLES = ['chain', 'asset', 'migrations', 'transactions', 'campaign'];
@@ -63,7 +64,12 @@ export default class DatabaseService {
63
64
 
64
65
  // Balance
65
66
  async getStoredBalance() {
66
- return this.stores.balance.table.toArray();
67
+ const addresses = keyring.getPairs().map(({
68
+ address
69
+ }) => address);
70
+
71
+ // Filter not exist address
72
+ return this.stores.balance.table.filter(obj => addresses.includes(obj.address)).toArray();
67
73
  }
68
74
  async updateBalanceStore(item) {
69
75
  if (item.state === APIItemState.READY) {
@@ -11,7 +11,7 @@ export const getWCId = id => {
11
11
  export const convertConnectRequest = request => {
12
12
  return {
13
13
  id: getWCId(request.id),
14
- isInternal: false,
14
+ isInternal: true,
15
15
  request: request,
16
16
  url: request.params.proposer.metadata.url
17
17
  };
@@ -16,4 +16,5 @@ export default class WalletConnectService {
16
16
  responseRequest(response: EngineTypes.RespondParams): Promise<void>;
17
17
  resetWallet(resetAll: boolean): Promise<void>;
18
18
  disconnect(topic: string): Promise<void>;
19
+ private findMethodsMissing;
19
20
  }