@subwallet/extension-base 1.1.25-1 → 1.1.27-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 (76) hide show
  1. package/background/KoniTypes.d.ts +3 -3
  2. package/background/handlers/State.js +3 -2
  3. package/cjs/background/handlers/State.js +3 -2
  4. package/cjs/constants/staking.js +4 -2
  5. package/cjs/koni/api/dotsama/transfer.js +2 -2
  6. package/cjs/koni/api/nft/config.js +2 -1
  7. package/cjs/koni/api/staking/bonding/astar.js +15 -24
  8. package/cjs/koni/api/staking/bonding/relayChain.js +48 -25
  9. package/cjs/koni/api/xcm/xTokens.js +1 -1
  10. package/cjs/koni/background/handlers/Extension.js +15 -8
  11. package/cjs/koni/background/handlers/Mobile.js +81 -5
  12. package/cjs/koni/background/handlers/State.js +54 -118
  13. package/cjs/koni/background/handlers/index.js +1 -1
  14. package/cjs/koni/background/subscription.js +34 -11
  15. package/cjs/packageInfo.js +1 -1
  16. package/cjs/services/balance-service/BalanceMapImpl.js +111 -0
  17. package/cjs/services/campaign-service/index.js +2 -0
  18. package/cjs/services/chain-service/constants.js +20 -3
  19. package/cjs/services/event-service/index.js +7 -7
  20. package/cjs/services/event-service/types.js +1 -1
  21. package/cjs/services/history-service/index.js +1 -0
  22. package/cjs/services/keyring-service/index.js +10 -6
  23. package/cjs/services/migration-service/scripts/index.js +3 -1
  24. package/cjs/services/migration-service/scripts/tokens/MigratePolygonUSDCProvider.js +16 -0
  25. package/cjs/services/migration-service/scripts/tokens/MigrateToken.js +33 -0
  26. package/cjs/services/setting-service/SettingService.js +2 -1
  27. package/cjs/services/setting-service/i18n/i18n.js +2 -1
  28. package/cjs/services/storage-service/DatabaseService.js +8 -19
  29. package/cjs/services/storage-service/db-stores/Balance.js +4 -13
  30. package/cjs/services/wallet-connect-service/index.js +6 -3
  31. package/cjs/storage/index.js +59 -0
  32. package/cjs/utils/array.js +27 -1
  33. package/constants/staking.d.ts +1 -0
  34. package/constants/staking.js +2 -1
  35. package/koni/api/dotsama/transfer.js +2 -2
  36. package/koni/api/nft/config.js +2 -1
  37. package/koni/api/staking/bonding/astar.js +15 -24
  38. package/koni/api/staking/bonding/relayChain.js +40 -17
  39. package/koni/api/xcm/xTokens.js +1 -1
  40. package/koni/background/handlers/Extension.js +15 -8
  41. package/koni/background/handlers/Mobile.d.ts +6 -0
  42. package/koni/background/handlers/Mobile.js +75 -3
  43. package/koni/background/handlers/State.d.ts +10 -9
  44. package/koni/background/handlers/State.js +43 -105
  45. package/koni/background/handlers/index.js +1 -1
  46. package/koni/background/subscription.d.ts +4 -1
  47. package/koni/background/subscription.js +34 -11
  48. package/package.json +40 -20
  49. package/packageInfo.js +1 -1
  50. package/services/balance-service/BalanceMapImpl.d.ts +17 -0
  51. package/services/balance-service/BalanceMapImpl.js +101 -0
  52. package/services/campaign-service/index.d.ts +1 -0
  53. package/services/campaign-service/index.js +2 -0
  54. package/services/chain-service/constants.d.ts +1 -0
  55. package/services/chain-service/constants.js +18 -2
  56. package/services/event-service/index.d.ts +1 -4
  57. package/services/event-service/index.js +8 -7
  58. package/services/event-service/types.js +1 -1
  59. package/services/history-service/index.js +1 -0
  60. package/services/keyring-service/index.js +10 -6
  61. package/services/migration-service/scripts/index.js +3 -1
  62. package/services/migration-service/scripts/tokens/MigratePolygonUSDCProvider.d.ts +5 -0
  63. package/services/migration-service/scripts/tokens/MigratePolygonUSDCProvider.js +8 -0
  64. package/services/migration-service/scripts/tokens/MigrateToken.d.ts +9 -0
  65. package/services/migration-service/scripts/tokens/MigrateToken.js +26 -0
  66. package/services/setting-service/SettingService.js +2 -1
  67. package/services/setting-service/i18n/i18n.js +2 -1
  68. package/services/storage-service/DatabaseService.d.ts +3 -1
  69. package/services/storage-service/DatabaseService.js +7 -19
  70. package/services/storage-service/db-stores/Balance.d.ts +3 -2
  71. package/services/storage-service/db-stores/Balance.js +4 -13
  72. package/services/wallet-connect-service/index.js +5 -3
  73. package/storage/index.d.ts +14 -0
  74. package/storage/index.js +52 -0
  75. package/utils/array.d.ts +1 -0
  76. package/utils/array.js +26 -1
@@ -19,6 +19,6 @@ function getCurrencyId(tokenInfo) {
19
19
  }
20
20
  export function getExtrinsicByXtokensPallet(tokenInfo, originChainInfo, destinationChainInfo, recipientAddress, value, api) {
21
21
  const weightParam = ['pioneer'].includes(originChainInfo.slug) ? FOUR_INSTRUCTIONS_WEIGHT : getDestWeight();
22
- const destVersion = ['moonbeam', 'moonriver', 'bifrost_dot', 'interlay', 'hydradx_main', 'acala', 'parallel', 'astar', 'shiden'].includes(originChainInfo.slug) ? 'V3' : undefined;
22
+ const destVersion = ['moonbeam', 'moonriver', 'bifrost_dot', 'interlay', 'hydradx_main', 'acala', 'parallel', 'astar', 'shiden', 'centrifuge'].includes(originChainInfo.slug) ? 'V3' : undefined;
23
23
  return api.tx.xTokens.transfer(getCurrencyId(tokenInfo), value, getDestMultilocation(destinationChainInfo, recipientAddress, destVersion), weightParam);
24
24
  }
@@ -1000,21 +1000,24 @@ export default class KoniExtension {
1000
1000
  });
1001
1001
  return this.getPrice();
1002
1002
  }
1003
- getBalance(reset) {
1003
+ async getBalance(reset) {
1004
1004
  return this.#koniState.getBalance(reset);
1005
1005
  }
1006
- subscribeBalance(id, port) {
1006
+ async subscribeBalance(id, port) {
1007
1007
  const cb = createSubscription(id, port);
1008
1008
  const balanceSubscription = this.#koniState.subscribeBalance().subscribe({
1009
1009
  next: rs => {
1010
- cb(rs);
1010
+ const data = {
1011
+ details: rs
1012
+ };
1013
+ cb(data);
1011
1014
  }
1012
1015
  });
1013
1016
  this.createUnsubscriptionHandle(id, balanceSubscription.unsubscribe);
1014
1017
  port.onDisconnect.addListener(() => {
1015
1018
  this.cancelSubscription(id);
1016
1019
  });
1017
- return this.getBalance(true);
1020
+ return await this.getBalance(true);
1018
1021
  }
1019
1022
  getCrowdloan(reset) {
1020
1023
  return this.#koniState.getCrowdloan(reset);
@@ -3204,6 +3207,10 @@ export default class KoniExtension {
3204
3207
  return await this.#koniState.reloadNft();
3205
3208
  } else if (data === 'staking') {
3206
3209
  return await this.#koniState.reloadStaking();
3210
+ } else if (data === 'balance') {
3211
+ return await this.#koniState.reloadBalance();
3212
+ } else if (data === 'crowdloan') {
3213
+ return await this.#koniState.reloadCrowdloan();
3207
3214
  }
3208
3215
  return Promise.resolve(false);
3209
3216
  }
@@ -3730,9 +3737,9 @@ export default class KoniExtension {
3730
3737
  case 'pri(price.getSubscription)':
3731
3738
  return await this.subscribePrice(id, port);
3732
3739
  case 'pri(balance.getBalance)':
3733
- return this.getBalance();
3740
+ return await this.getBalance();
3734
3741
  case 'pri(balance.getSubscription)':
3735
- return this.subscribeBalance(id, port);
3742
+ return await this.subscribeBalance(id, port);
3736
3743
  case 'pri(crowdloan.getCrowdloan)':
3737
3744
  return this.getCrowdloan();
3738
3745
  case 'pri(crowdloan.getSubscription)':
@@ -4068,8 +4075,8 @@ export default class KoniExtension {
4068
4075
  return this.#koniState.dbService.exportDB();
4069
4076
  case 'pri(database.import)':
4070
4077
  return this.#koniState.dbService.importDB(request);
4071
- case 'pri(database.checkMetadata)':
4072
- return this.#koniState.dbService.checkImportMetadata(request);
4078
+ case 'pri(database.exportJson)':
4079
+ return this.#koniState.dbService.getExportJson();
4073
4080
  /* Database */
4074
4081
  // Default
4075
4082
  default:
@@ -2,9 +2,13 @@
2
2
  import { ActiveCronAndSubscriptionMap, CronServiceType, MobileData, RequestCronAndSubscriptionAction, RequestInitCronAndSubscription, SubscriptionServiceType } from '@subwallet/extension-base/background/KoniTypes';
3
3
  import { MessageTypes, RequestTypes, ResponseType } from '@subwallet/extension-base/background/types';
4
4
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
5
+ export declare function isLocalStorageReset(): boolean;
6
+ export declare function isIndexedDBReset(): Promise<boolean>;
7
+ export declare function isWebRunnerDataReset(): Promise<boolean>;
5
8
  export default class Mobile {
6
9
  private state;
7
10
  private restoreHandler;
11
+ private lastRestoreData;
8
12
  constructor(state: KoniState);
9
13
  ping(): string;
10
14
  initCronAndSubscription({ cron: { activeServices, intervalMap }, subscription: { activeServices } }: RequestInitCronAndSubscription): ActiveCronAndSubscriptionMap;
@@ -18,6 +22,8 @@ export default class Mobile {
18
22
  startSubscriptionServices(services: SubscriptionServiceType[]): void;
19
23
  stopSubscriptionServices(services: SubscriptionServiceType[]): void;
20
24
  restartSubscriptionServices(services: SubscriptionServiceType[]): void;
25
+ private _getLocalStorageExportData;
26
+ private _getDexieExportData;
21
27
  mobileBackup(): Promise<MobileData>;
22
28
  mobileRestore({ indexedDB, storage }: Partial<MobileData>): Promise<void>;
23
29
  waitRestore(): Promise<void>;
@@ -1,7 +1,31 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ import { state } from '@subwallet/extension-base/koni/background/handlers/index';
5
+ import { SWStorage } from '@subwallet/extension-base/storage';
6
+ import { listMerge } from '@subwallet/extension-base/utils';
4
7
  import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
8
+ export function isLocalStorageReset() {
9
+ var _window;
10
+ if ((_window = window) !== null && _window !== void 0 && _window.localStorage) {
11
+ return !window.localStorage.getItem('keyring:subwallet');
12
+ } else {
13
+ return false;
14
+ }
15
+ }
16
+ export async function isIndexedDBReset() {
17
+ try {
18
+ return (await state.dbService.stores.migration.table.count()) < 1;
19
+ } catch (e) {
20
+ return true;
21
+ }
22
+ }
23
+
24
+ // Detect problems on the web-runner
25
+ export async function isWebRunnerDataReset() {
26
+ return isLocalStorageReset() || (await isIndexedDBReset());
27
+ }
28
+ const swStorage = SWStorage.instance;
5
29
  const DEFAULT_SERVICE_MAP = {
6
30
  subscription: {
7
31
  chainRegistry: true,
@@ -22,8 +46,17 @@ export default class Mobile {
22
46
  // @ts-ignore
23
47
 
24
48
  restoreHandler = createPromiseHandler();
49
+ lastRestoreData = {};
25
50
  constructor(state) {
26
51
  this.state = state;
52
+ if (!isLocalStorageReset()) {
53
+ this.lastRestoreData.storage = swStorage.copy();
54
+ }
55
+ (async () => {
56
+ if (!(await isIndexedDBReset())) {
57
+ this.lastRestoreData.indexedDB = await state.dbService.getExportJson();
58
+ }
59
+ })().catch(console.error);
27
60
  }
28
61
  ping() {
29
62
  return 'mobile:ping';
@@ -94,10 +127,46 @@ export default class Mobile {
94
127
  restartSubscriptionServices(services) {
95
128
  console.log('restartSubscriptionServices');
96
129
  }
97
- async mobileBackup() {
130
+ async _getLocalStorageExportData() {
131
+ return Promise.resolve(JSON.stringify(swStorage.copy()));
132
+ }
133
+ async _getDexieExportData() {
98
134
  const indexedDB = await this.state.dbService.exportDB();
135
+ if ((await isIndexedDBReset()) && this.lastRestoreData.indexedDB) {
136
+ // Merge with latest restore DexieData
137
+ const exportData = await this.state.dbService.getExportJson();
138
+ const exportTables = exportData === null || exportData === void 0 ? void 0 : exportData.data.data;
139
+ const existedData = this.lastRestoreData.indexedDB;
140
+ const existedTableMap = Object.fromEntries(existedData.data.data.map(table => [table.tableName, table]));
141
+ if ((exportTables === null || exportTables === void 0 ? void 0 : exportTables.length) > 0) {
142
+ exportTables.forEach(({
143
+ inbound,
144
+ rows,
145
+ tableName
146
+ }) => {
147
+ const latestTable = existedTableMap[tableName];
148
+
149
+ // chain & asset & campaign
150
+ if (tableName === 'chain' || tableName === 'asset' || tableName === 'campaign') {
151
+ latestTable.rows = listMerge('slug', latestTable.rows, rows);
152
+
153
+ // Todo: Campaign still doesn't work
154
+ } else if (tableName === 'migrations') {
155
+ latestTable.rows = listMerge('key', latestTable.rows, rows);
156
+ } else if (tableName === 'transactions') {
157
+ latestTable.rows = listMerge(['chain', 'address', 'extrinsicHash'], latestTable.rows, rows);
158
+ }
159
+ });
160
+ }
161
+ return JSON.stringify(existedData);
162
+ }
163
+ return indexedDB;
164
+ }
165
+ async mobileBackup() {
166
+ const storage = await this._getLocalStorageExportData();
167
+ const indexedDB = await this._getDexieExportData();
99
168
  return {
100
- storage: JSON.stringify(localStorage),
169
+ storage,
101
170
  indexedDB
102
171
  };
103
172
  }
@@ -108,10 +177,13 @@ export default class Mobile {
108
177
  if (storage) {
109
178
  const storageData = JSON.parse(storage);
110
179
  for (const key in storageData) {
111
- localStorage.setItem(key, storageData[key]);
180
+ swStorage.setItem(key, storageData[key]);
112
181
  }
113
182
  }
114
183
  if (indexedDB) {
184
+ // Backup the last restore data to memory
185
+ this.lastRestoreData.indexedDB = JSON.parse(indexedDB);
186
+ // Backup the last restore data to memory
115
187
  await this.state.dbService.importDB(indexedDB);
116
188
  }
117
189
  this.restoreHandler.resolve();
@@ -36,7 +36,6 @@ export default class KoniState {
36
36
  private readonly accountRefStore;
37
37
  private externalRequest;
38
38
  private balanceMap;
39
- private balanceSubject;
40
39
  private crowdloanMap;
41
40
  private crowdloanSubject;
42
41
  private nftSubject;
@@ -84,7 +83,7 @@ export default class KoniState {
84
83
  saveMetadata(meta: MetadataDef): void;
85
84
  sign(url: string, request: RequestSign, account: AccountJson): Promise<ResponseSigning>;
86
85
  get authSubjectV2(): BehaviorSubject<import("@subwallet/extension-base/background/types").AuthorizeRequest[]>;
87
- generateDefaultBalanceMap(): BalanceMap;
86
+ generateDefaultBalanceMap(_addresses?: string[]): BalanceMap;
88
87
  private afterChainServiceInit;
89
88
  init(): Promise<void>;
90
89
  initMantaPay(password: string): Promise<void>;
@@ -150,17 +149,18 @@ export default class KoniState {
150
149
  getAccountAddress(): string | null;
151
150
  getDecodedAddresses(address?: string): string[];
152
151
  getAllAddresses(): string[];
153
- private removeInactiveChainBalances;
154
- getBalance(reset?: boolean): BalanceJson;
155
- getStoredBalance(address: string): Promise<BalanceMap>;
156
- handleSwitchAccount(newAddress: string): Promise<void>;
157
- resetBalanceMap(newAddress: string): Promise<void>;
152
+ removeInactiveChainBalances(): Promise<void>;
153
+ getBalance(reset?: boolean): Promise<BalanceJson>;
154
+ getStoredBalance(address: string): Promise<BalanceItem[]>;
155
+ private isFirstLoad;
156
+ handleResetBalance(newAddress: string, forceRefresh?: boolean): Promise<void>;
158
157
  resetCrowdloanMap(newAddress: string): Promise<void>;
159
158
  resetStaking(newAddress: string): void;
159
+ private balanceUpdateCache;
160
160
  /** Note: items must be same tokenSlug */
161
161
  setBalanceItem(items: BalanceItem[]): void;
162
162
  private updateBalanceStore;
163
- subscribeBalance(): Subject<BalanceJson>;
163
+ subscribeBalance(): BehaviorSubject<BalanceMap>;
164
164
  getCrowdloan(reset?: boolean): CrowdloanJson;
165
165
  getStoredCrowdloan(address: string): Promise<Record<string, import("../../../services/storage-service/databases").ICrowdloanItem>>;
166
166
  setCrowdloanItem(networkKey: string, item: CrowdloanItem): void;
@@ -210,7 +210,6 @@ export default class KoniState {
210
210
  cleanExternalRequest(): void;
211
211
  pauseAllNetworks(code?: number, reason?: string): Promise<void>;
212
212
  resumeAllNetworks(): Promise<void>;
213
- private publishBalance;
214
213
  private publishCrowdloan;
215
214
  findNetworkKeyByGenesisHash(genesisHash?: string | null): [string | undefined, _ChainInfo | undefined];
216
215
  findChainIdGenesisHash(genesisHash?: string | null): number | undefined;
@@ -236,6 +235,8 @@ export default class KoniState {
236
235
  onAccountRemove(): void;
237
236
  reloadNft(): Promise<boolean>;
238
237
  reloadStaking(): Promise<boolean>;
238
+ reloadBalance(): Promise<boolean>;
239
+ reloadCrowdloan(): Promise<boolean>;
239
240
  approvePassPhishingPage(_url: string): Promise<boolean>;
240
241
  resetWallet(resetAll: boolean): Promise<void>;
241
242
  enableMantaPay(updateStore: boolean, address: string, password: string, seedPhrase?: string): Promise<string | undefined>;
@@ -7,7 +7,7 @@ import { isSubscriptionRunning, unsubscribe } from '@subwallet/extension-base/ba
7
7
  import { APIItemState, BasicTxErrorType, ChainType, EvmProviderErrorType, ExternalRequestPromiseStatus, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
8
8
  import { ALL_ACCOUNT_KEY, ALL_GENESIS_HASH, MANTA_PAY_BALANCE_INTERVAL } from '@subwallet/extension-base/constants';
9
9
  import { BalanceService } from '@subwallet/extension-base/services/balance-service';
10
- import { groupBalance } from '@subwallet/extension-base/services/balance-service/helpers/group';
10
+ import { BalanceMapImpl } from '@subwallet/extension-base/services/balance-service/BalanceMapImpl';
11
11
  import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
12
12
  import BuyService from '@subwallet/extension-base/services/buy-service';
13
13
  import CampaignService from '@subwallet/extension-base/services/campaign-service';
@@ -28,7 +28,7 @@ import { SUBSCAN_API_CHAIN_MAP, SUBSCAN_BALANCE_CHAIN_MAP_REVERSE } from '@subwa
28
28
  import TransactionService from '@subwallet/extension-base/services/transaction-service';
29
29
  import WalletConnectService from '@subwallet/extension-base/services/wallet-connect-service';
30
30
  import AccountRefStore from '@subwallet/extension-base/stores/AccountRef';
31
- import { isAccountAll, isSameAddress, stripUrl, TARGET_ENV } from '@subwallet/extension-base/utils';
31
+ import { addLazy, isAccountAll, stripUrl, TARGET_ENV } from '@subwallet/extension-base/utils';
32
32
  import { recalculateGasPrice } from '@subwallet/extension-base/utils/eth';
33
33
  import { isContractAddress, parseContractInput } from '@subwallet/extension-base/utils/eth/parseTransaction';
34
34
  import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
@@ -61,8 +61,7 @@ export default class KoniState {
61
61
  unsubscriptionMap = {};
62
62
  accountRefStore = new AccountRefStore();
63
63
  externalRequest = {};
64
- balanceMap = {};
65
- balanceSubject = new Subject();
64
+ balanceMap = new BalanceMapImpl();
66
65
  crowdloanMap = generateDefaultCrowdloanMap();
67
66
  crowdloanSubject = new Subject();
68
67
  nftSubject = new Subject();
@@ -186,11 +185,11 @@ export default class KoniState {
186
185
  get authSubjectV2() {
187
186
  return this.requestService.authSubjectV2;
188
187
  }
189
- generateDefaultBalanceMap() {
188
+ generateDefaultBalanceMap(_addresses) {
190
189
  const balanceMap = {};
191
190
  const activeChains = this.chainService.getActiveChainInfoMap();
192
191
  const isAllAccount = isAccountAll(this.keyringService.currentAccount.address);
193
- const addresses = isAllAccount ? Object.keys(this.keyringService.accounts) : [this.keyringService.currentAccount.address];
192
+ const addresses = _addresses || (isAllAccount ? Object.keys(this.keyringService.accounts) : [this.keyringService.currentAccount.address]);
194
193
  addresses.forEach(address => {
195
194
  const temp = {};
196
195
  Object.values(activeChains).forEach(chainInfo => {
@@ -217,6 +216,7 @@ export default class KoniState {
217
216
  await this.chainService.init();
218
217
  this.afterChainServiceInit();
219
218
  await this.migrationService.run();
219
+ this.campaignService.init();
220
220
  this.eventService.emit('chain.ready', true);
221
221
  this.onReady();
222
222
  this.onAccountAdd();
@@ -673,70 +673,29 @@ export default class KoniState {
673
673
  getAllAddresses() {
674
674
  return keyring.getAccounts().map(account => account.address);
675
675
  }
676
- removeInactiveChainBalances(balanceMap) {
677
- const activeBalanceMap = {};
678
- Object.entries(balanceMap).forEach(([address, balances]) => {
679
- activeBalanceMap[address] = {};
680
- Object.entries(balances).forEach(([tokenSlug, item]) => {
681
- const tokenInfo = this.chainService.getAssetBySlug(tokenSlug);
682
- if (tokenInfo) {
683
- const chainInfo = this.chainService.getChainInfoByKey(tokenInfo.originChain);
684
- if (chainInfo && this.getChainStateByKey(chainInfo.slug).active) {
685
- activeBalanceMap[address][tokenSlug] = item;
686
- }
687
- }
688
- });
676
+ async removeInactiveChainBalances() {
677
+ const assetSettings = await this.chainService.getAssetSettings();
678
+ this.balanceMap.removeBalanceItemByFilter(item => {
679
+ return !assetSettings[item.tokenSlug];
689
680
  });
690
- return activeBalanceMap;
691
681
  }
692
- getBalance(reset) {
693
- const activeData = this.removeInactiveChainBalances(this.balanceMap);
682
+ async getBalance(reset) {
683
+ await this.removeInactiveChainBalances();
694
684
  return {
695
- details: activeData,
685
+ details: this.balanceMap.map,
696
686
  reset
697
687
  };
698
688
  }
699
689
  async getStoredBalance(address) {
700
- const items = await this.dbService.stores.balance.getBalanceMapByAddresses(address);
701
- return items || {};
690
+ return await this.dbService.stores.balance.getBalanceMapByAddresses(address);
702
691
  }
703
- async handleSwitchAccount(newAddress) {
704
- await Promise.all([this.resetBalanceMap(newAddress), this.resetCrowdloanMap(newAddress)]);
705
- }
706
- async resetBalanceMap(newAddress) {
707
- const defaultData = this.generateDefaultBalanceMap();
708
- let storedData = await this.getStoredBalance(newAddress);
709
- storedData = this.removeInactiveChainBalances(storedData);
710
- const result = {};
711
- for (const [address, balanceInfo] of Object.entries(defaultData)) {
712
- result[address] = {
713
- ...balanceInfo
714
- };
715
- }
716
- for (const [address, balanceInfo] of Object.entries(storedData)) {
717
- if (!result[address]) {
718
- result[address] = {
719
- ...balanceInfo
720
- };
721
- } else {
722
- const temp = {
723
- ...result[address]
724
- };
725
- for (const [slug, item] of Object.entries(balanceInfo)) {
726
- temp[slug] = {
727
- ...item
728
- };
729
- }
730
- result[address] = {
731
- ...temp
732
- };
733
- }
692
+ isFirstLoad = true;
693
+ async handleResetBalance(newAddress, forceRefresh) {
694
+ if (this.isFirstLoad || forceRefresh) {
695
+ const backupBalanceData = await this.dbService.getStoredBalance();
696
+ this.balanceMap.updateBalanceItems(backupBalanceData, isAccountAll(newAddress));
734
697
  }
735
- this.balanceMap = {
736
- ...defaultData,
737
- ...storedData
738
- };
739
- this.publishBalance(true);
698
+ await Promise.all([this.removeInactiveChainBalances()]);
740
699
  }
741
700
  async resetCrowdloanMap(newAddress) {
742
701
  const defaultData = generateDefaultCrowdloanMap();
@@ -759,62 +718,35 @@ export default class KoniState {
759
718
  });
760
719
  });
761
720
  }
721
+ balanceUpdateCache = [];
762
722
 
763
723
  /** Note: items must be same tokenSlug */
764
724
  setBalanceItem(items) {
765
725
  if (items.length) {
766
- const tokens = [];
767
- const updates = [];
726
+ const nowTime = new Date().getTime();
768
727
  for (const item of items) {
769
- const address = item.address;
770
- const tokenSlug = item.tokenSlug;
771
- if (!tokens.includes(tokenSlug)) {
772
- tokens.push(tokenSlug);
773
- }
774
- if (!this.balanceMap[address]) {
775
- this.balanceMap[address] = {};
776
- }
777
- const data = {
778
- timestamp: +new Date(),
728
+ const balance = {
729
+ timestamp: nowTime,
779
730
  ...item
780
731
  };
781
- this.balanceMap[address][tokenSlug] = data;
782
- updates.push(data);
732
+ this.balanceUpdateCache.push(balance);
783
733
  }
784
- const isAllAccount = isAccountAll(this.keyringService.currentAccount.address);
785
- if (isAllAccount) {
786
- const address = ALL_ACCOUNT_KEY;
787
- for (const token of tokens) {
788
- const items = [];
789
- for (const [_adr, balanceInfo] of Object.entries(this.balanceMap)) {
790
- if (!isSameAddress(_adr, address)) {
791
- const item = balanceInfo[token];
792
- item && items.push(item);
793
- }
794
- }
795
- const _balance = groupBalance(items, address, token);
796
- const balance = {
797
- timestamp: +new Date(),
798
- ..._balance
799
- };
800
- if (!this.balanceMap[address]) {
801
- this.balanceMap[address] = {};
802
- }
803
- this.balanceMap[address][token] = balance;
804
- updates.push(balance);
734
+ addLazy('updateBalanceStore', () => {
735
+ const isAllAccount = isAccountAll(this.keyringService.currentAccount.address);
736
+ this.balanceMap.updateBalanceItems(this.balanceUpdateCache, isAllAccount);
737
+ if (isAllAccount) {
738
+ this.balanceUpdateCache = [...this.balanceUpdateCache, ...Object.values(this.balanceMap.map[ALL_ACCOUNT_KEY])];
805
739
  }
806
- }
807
- this.updateBalanceStore(updates);
808
- this.lazyNext('setBalanceItem', () => {
809
- this.publishBalance();
810
- });
740
+ this.updateBalanceStore(this.balanceUpdateCache);
741
+ this.balanceUpdateCache = [];
742
+ }, 300, 1800);
811
743
  }
812
744
  }
813
745
  updateBalanceStore(items) {
814
746
  this.dbService.updateBulkBalanceStore(items).catch(e => this.logger.warn(e));
815
747
  }
816
748
  subscribeBalance() {
817
- return this.balanceSubject;
749
+ return this.balanceMap.mapSubject;
818
750
  }
819
751
  getCrowdloan(reset) {
820
752
  return {
@@ -1064,9 +996,6 @@ export default class KoniState {
1064
996
  async resumeAllNetworks() {
1065
997
  return this.chainService.resumeAllChainApis();
1066
998
  }
1067
- publishBalance(reset) {
1068
- this.balanceSubject.next(this.getBalance(reset));
1069
- }
1070
999
  publishCrowdloan(reset) {
1071
1000
  this.crowdloanSubject.next(this.getCrowdloan(reset));
1072
1001
  }
@@ -1593,6 +1522,7 @@ export default class KoniState {
1593
1522
  // Remove Balance
1594
1523
  stores.balance.removeAllByAddress(address).catch(console.error);
1595
1524
  stores.balance.removeAllByAddress(ALL_ACCOUNT_KEY).catch(console.error);
1525
+ this.balanceMap.removeBalanceItems([address, ALL_ACCOUNT_KEY]);
1596
1526
 
1597
1527
  // Remove NFT
1598
1528
  stores.nft.deleteNftByAddress([address]).catch(console.error);
@@ -1610,6 +1540,14 @@ export default class KoniState {
1610
1540
  await this.subscription.reloadStaking();
1611
1541
  return true;
1612
1542
  }
1543
+ async reloadBalance() {
1544
+ await this.subscription.reloadBalance();
1545
+ return true;
1546
+ }
1547
+ async reloadCrowdloan() {
1548
+ await this.subscription.reloadCrowdloan();
1549
+ return true;
1550
+ }
1613
1551
  async approvePassPhishingPage(_url) {
1614
1552
  return new Promise(resolve => {
1615
1553
  this.settingService.getPassPhishingList(value => {
@@ -44,7 +44,7 @@ export default function handlers({
44
44
  const isMobile = port.name === PORT_MOBILE;
45
45
  const isExtension = port.name === extensionPortName;
46
46
  const sender = port.sender;
47
- const from = isExtension ? 'extension' : sender.tab && sender.tab.url || sender.url || '<unknown>';
47
+ const from = isExtension ? 'extension' : sender.url || sender.tab && sender.tab.url || '<unknown>';
48
48
  const source = `${from}: ${id}: ${message}`;
49
49
 
50
50
  // console.log(` [in] ${source}`); // :: ${JSON.stringify(request)}`);
@@ -16,7 +16,8 @@ export declare class KoniSubscription {
16
16
  stopAllSubscription(): void;
17
17
  start(): Promise<void>;
18
18
  stop(): Promise<void>;
19
- subscribeBalancesAndCrowdloans(address: string, chainInfoMap: Record<string, _ChainInfo>, chainStateMap: Record<string, _ChainState>, substrateApiMap: Record<string, _SubstrateApi>, web3ApiMap: Record<string, _EvmApi>, onlyRunOnFirstTime?: boolean): void;
19
+ subscribeBalances(address: string, chainInfoMap: Record<string, _ChainInfo>, chainStateMap: Record<string, _ChainState>, substrateApiMap: Record<string, _SubstrateApi>, web3ApiMap: Record<string, _EvmApi>, onlyRunOnFirstTime?: boolean): void;
20
+ subscribeCrowdloans(address: string, substrateApiMap: Record<string, _SubstrateApi>, onlyRunOnFirstTime?: boolean): void;
20
21
  subscribeStakingOnChain(address: string, substrateApiMap: Record<string, _SubstrateApi>, onlyRunOnFirstTime?: boolean): void;
21
22
  initStakingOnChainSubscription(addresses: string[], substrateApiMap: Record<string, _SubstrateApi>, onlyRunOnFirstTime?: boolean): (() => void) | undefined;
22
23
  initEssentialChainStakingMetadataSubscription(substrateApiMap: Record<string, _SubstrateApi>, onlyRunOnFirstTime?: boolean): (() => void) | undefined;
@@ -27,5 +28,7 @@ export declare class KoniSubscription {
27
28
  subscribeStakingReward(address: string): Promise<void>;
28
29
  subscribeStakingRewardFastInterval(address: string): Promise<void>;
29
30
  reloadStaking(): Promise<void>;
31
+ reloadBalance(): Promise<void>;
32
+ reloadCrowdloan(): Promise<void>;
30
33
  }
31
34
  export {};
@@ -50,10 +50,11 @@ export class KoniSubscription {
50
50
  }
51
51
  async start() {
52
52
  var _this$state$keyringSe;
53
- await Promise.all([this.state.eventService.waitKeyringReady, this.state.eventService.waitAssetReady]);
53
+ await Promise.all([this.state.eventService.waitCryptoReady, this.state.eventService.waitKeyringReady, this.state.eventService.waitAssetReady]);
54
54
  const currentAddress = (_this$state$keyringSe = this.state.keyringService.currentAccount) === null || _this$state$keyringSe === void 0 ? void 0 : _this$state$keyringSe.address;
55
55
  if (currentAddress) {
56
- this.subscribeBalancesAndCrowdloans(currentAddress, this.state.getChainInfoMap(), this.state.getChainStateMap(), this.state.getSubstrateApiMap(), this.state.getEvmApiMap());
56
+ this.subscribeBalances(currentAddress, this.state.getChainInfoMap(), this.state.getChainStateMap(), this.state.getSubstrateApiMap(), this.state.getEvmApiMap());
57
+ this.subscribeCrowdloans(currentAddress, this.state.getSubstrateApiMap());
57
58
  this.subscribeStakingOnChain(currentAddress, this.state.getSubstrateApiMap());
58
59
  }
59
60
  this.eventHandler = (events, eventTypes) => {
@@ -67,10 +68,11 @@ export class KoniSubscription {
67
68
  if (!address) {
68
69
  return;
69
70
  }
70
- this.subscribeBalancesAndCrowdloans(address, serviceInfo.chainInfoMap, serviceInfo.chainStateMap, serviceInfo.chainApiMap.substrate, serviceInfo.chainApiMap.evm);
71
+ this.subscribeBalances(address, serviceInfo.chainInfoMap, serviceInfo.chainStateMap, serviceInfo.chainApiMap.substrate, serviceInfo.chainApiMap.evm);
72
+ this.subscribeCrowdloans(address, serviceInfo.chainApiMap.substrate);
71
73
  this.subscribeStakingOnChain(address, serviceInfo.chainApiMap.substrate);
72
74
  };
73
- this.state.eventService.onLazy(this.eventHandler);
75
+ this.state.eventService.onLazy(this.eventHandler.bind(this));
74
76
  }
75
77
  async stop() {
76
78
  if (this.eventHandler) {
@@ -80,16 +82,24 @@ export class KoniSubscription {
80
82
  this.stopAllSubscription();
81
83
  return Promise.resolve();
82
84
  }
83
- subscribeBalancesAndCrowdloans(address, chainInfoMap, chainStateMap, substrateApiMap, web3ApiMap, onlyRunOnFirstTime) {
84
- this.state.handleSwitchAccount(address).then(() => {
85
- const addresses = this.state.getDecodedAddresses(address);
86
- if (!addresses.length) {
87
- return;
88
- }
85
+ subscribeBalances(address, chainInfoMap, chainStateMap, substrateApiMap, web3ApiMap, onlyRunOnFirstTime) {
86
+ const addresses = this.state.getDecodedAddresses(address);
87
+ if (!addresses.length) {
88
+ return;
89
+ }
90
+ this.state.handleResetBalance(address).then(() => {
89
91
  this.updateSubscription('balance', this.initBalanceSubscription(addresses, chainInfoMap, chainStateMap, substrateApiMap, web3ApiMap, onlyRunOnFirstTime));
90
- this.updateSubscription('crowdloan', this.initCrowdloanSubscription(addresses, substrateApiMap, onlyRunOnFirstTime));
91
92
  }).catch(err => this.logger.warn(err));
92
93
  }
94
+ subscribeCrowdloans(address, substrateApiMap, onlyRunOnFirstTime) {
95
+ const addresses = this.state.getDecodedAddresses(address);
96
+ if (!addresses.length) {
97
+ return;
98
+ }
99
+ this.state.resetCrowdloanMap(address).then(() => {
100
+ this.updateSubscription('crowdloan', this.initCrowdloanSubscription(addresses, substrateApiMap, onlyRunOnFirstTime));
101
+ }).catch(console.error);
102
+ }
93
103
  subscribeStakingOnChain(address, substrateApiMap, onlyRunOnFirstTime) {
94
104
  this.state.resetStaking(address);
95
105
  const addresses = this.state.getDecodedAddresses(address);
@@ -242,4 +252,17 @@ export class KoniSubscription {
242
252
  this.subscribeStakingOnChain(currentAddress, this.state.getSubstrateApiMap());
243
253
  await waitTimeout(1800);
244
254
  }
255
+ async reloadBalance() {
256
+ var _this$state$keyringSe3;
257
+ const currentAddress = (_this$state$keyringSe3 = this.state.keyringService.currentAccount) === null || _this$state$keyringSe3 === void 0 ? void 0 : _this$state$keyringSe3.address;
258
+ this.subscribeBalances(currentAddress, this.state.getChainInfoMap(), this.state.getChainStateMap(), this.state.getSubstrateApiMap(), this.state.getEvmApiMap());
259
+ await waitTimeout(1800);
260
+ }
261
+ async reloadCrowdloan() {
262
+ var _this$state$keyringSe4;
263
+ const currentAddress = (_this$state$keyringSe4 = this.state.keyringService.currentAccount) === null || _this$state$keyringSe4 === void 0 ? void 0 : _this$state$keyringSe4.address;
264
+ await this.state.handleResetBalance(currentAddress, true);
265
+ this.subscribeCrowdloans(currentAddress, this.state.getSubstrateApiMap());
266
+ await waitTimeout(1800);
267
+ }
245
268
  }