@subwallet/extension-base 1.0.2-2 → 1.0.3-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 (151) hide show
  1. package/background/KoniTypes.d.ts +56 -40
  2. package/background/KoniTypes.js +11 -9
  3. package/background/errors/TransactionError.js +25 -1
  4. package/background/types.d.ts +10 -5
  5. package/cjs/background/KoniTypes.js +11 -9
  6. package/cjs/background/errors/TransactionError.js +24 -0
  7. package/cjs/constants/index.js +8 -26
  8. package/cjs/koni/api/dotsama/balance.js +49 -224
  9. package/cjs/koni/api/dotsama/transfer.js +34 -39
  10. package/cjs/koni/api/nft/acala_nft/index.js +7 -7
  11. package/cjs/koni/api/nft/bit.country/index.js +7 -6
  12. package/cjs/koni/api/nft/evm_nft/index.js +8 -3
  13. package/cjs/koni/api/nft/index.js +3 -6
  14. package/cjs/koni/api/nft/karura_nft/index.js +7 -6
  15. package/cjs/koni/api/nft/rmrk_nft/index.js +11 -1
  16. package/cjs/koni/api/nft/statemine_nft/index.js +7 -6
  17. package/cjs/koni/api/nft/unique_nft/index.js +5 -1
  18. package/cjs/koni/api/nft/wasm_nft/index.js +170 -111
  19. package/cjs/koni/api/nft/wasm_nft/utils.js +11 -7
  20. package/cjs/koni/api/staking/bonding/amplitude.js +13 -9
  21. package/cjs/koni/api/staking/bonding/astar.js +15 -13
  22. package/cjs/koni/api/staking/bonding/index.js +22 -10
  23. package/cjs/koni/api/staking/bonding/paraChain.js +85 -2
  24. package/cjs/koni/api/staking/bonding/relayChain.js +122 -16
  25. package/cjs/koni/api/staking/bonding/utils.js +27 -8
  26. package/cjs/koni/api/tokens/wasm/index.js +5 -4
  27. package/cjs/koni/api/tokens/wasm/utils.js +63 -0
  28. package/cjs/koni/api/xcm/polkadotXcm.js +1 -1
  29. package/cjs/koni/api/xcm/utils.js +18 -13
  30. package/cjs/koni/api/xcm/xTokens.js +1 -1
  31. package/cjs/koni/api/xcm/xcmPallet.js +9 -6
  32. package/cjs/koni/background/cron.js +171 -61
  33. package/cjs/koni/background/handlers/Extension.js +391 -207
  34. package/cjs/koni/background/handlers/State.js +49 -34
  35. package/cjs/koni/background/handlers/Tabs.js +50 -17
  36. package/cjs/koni/background/subscription.js +53 -28
  37. package/cjs/packageInfo.js +1 -1
  38. package/cjs/services/base/types.js +20 -0
  39. package/cjs/services/chain-service/handler/SubstrateChainHandler.js +13 -8
  40. package/cjs/services/chain-service/index.js +73 -49
  41. package/cjs/services/event-service/index.js +5 -1
  42. package/cjs/services/event-service/types.js +11 -1
  43. package/cjs/services/history-service/index.js +101 -50
  44. package/cjs/services/history-service/subsquid-multi-chain-history.js +13 -10
  45. package/cjs/services/keyring-service/index.js +11 -13
  46. package/cjs/services/migration-service/scripts/MigrateImportedToken.js +2 -1
  47. package/cjs/services/price-service/coingecko.js +0 -1
  48. package/cjs/services/price-service/index.js +71 -24
  49. package/cjs/services/request-service/handler/AuthRequestHandler.js +13 -7
  50. package/cjs/services/request-service/handler/EvmRequestHandler.js +8 -12
  51. package/cjs/services/request-service/index.js +14 -5
  52. package/cjs/services/storage-service/DatabaseService.js +66 -34
  53. package/cjs/services/storage-service/db-stores/Nft.js +7 -15
  54. package/cjs/services/storage-service/db-stores/Transaction.js +6 -10
  55. package/cjs/services/transaction-service/event-parser/index.js +20 -48
  56. package/cjs/services/transaction-service/index.js +104 -48
  57. package/cjs/services/transaction-service/utils.js +10 -8
  58. package/cjs/utils/address.js +10 -1
  59. package/cjs/utils/index.js +9 -15
  60. package/cjs/utils/promise.js +26 -0
  61. package/constants/index.d.ts +7 -13
  62. package/constants/index.js +7 -13
  63. package/koni/api/dotsama/balance.d.ts +0 -1
  64. package/koni/api/dotsama/balance.js +22 -197
  65. package/koni/api/dotsama/transfer.js +11 -16
  66. package/koni/api/nft/acala_nft/index.js +7 -7
  67. package/koni/api/nft/bit.country/index.js +7 -6
  68. package/koni/api/nft/evm_nft/index.js +7 -3
  69. package/koni/api/nft/index.d.ts +1 -2
  70. package/koni/api/nft/index.js +3 -6
  71. package/koni/api/nft/karura_nft/index.js +7 -6
  72. package/koni/api/nft/nft.d.ts +1 -0
  73. package/koni/api/nft/rmrk_nft/index.js +11 -1
  74. package/koni/api/nft/statemine_nft/index.js +7 -6
  75. package/koni/api/nft/unique_nft/index.js +5 -1
  76. package/koni/api/nft/wasm_nft/index.d.ts +0 -2
  77. package/koni/api/nft/wasm_nft/index.js +168 -109
  78. package/koni/api/nft/wasm_nft/utils.d.ts +7 -5
  79. package/koni/api/nft/wasm_nft/utils.js +7 -5
  80. package/koni/api/staking/bonding/amplitude.d.ts +0 -1
  81. package/koni/api/staking/bonding/amplitude.js +15 -10
  82. package/koni/api/staking/bonding/astar.js +8 -6
  83. package/koni/api/staking/bonding/index.d.ts +4 -1
  84. package/koni/api/staking/bonding/index.js +23 -13
  85. package/koni/api/staking/bonding/paraChain.d.ts +3 -0
  86. package/koni/api/staking/bonding/paraChain.js +86 -5
  87. package/koni/api/staking/bonding/relayChain.d.ts +5 -1
  88. package/koni/api/staking/bonding/relayChain.js +121 -18
  89. package/koni/api/staking/bonding/utils.d.ts +3 -2
  90. package/koni/api/staking/bonding/utils.js +27 -9
  91. package/koni/api/tokens/wasm/index.js +5 -4
  92. package/koni/api/tokens/wasm/utils.d.ts +6 -0
  93. package/koni/api/tokens/wasm/utils.js +54 -0
  94. package/koni/api/xcm/polkadotXcm.js +2 -2
  95. package/koni/api/xcm/utils.d.ts +5 -6
  96. package/koni/api/xcm/utils.js +15 -10
  97. package/koni/api/xcm/xTokens.js +2 -2
  98. package/koni/api/xcm/xcmPallet.js +10 -9
  99. package/koni/background/cron.d.ts +6 -1
  100. package/koni/background/cron.js +172 -62
  101. package/koni/background/handlers/Extension.d.ts +9 -3
  102. package/koni/background/handlers/Extension.js +306 -126
  103. package/koni/background/handlers/State.d.ts +5 -6
  104. package/koni/background/handlers/State.js +51 -34
  105. package/koni/background/handlers/Tabs.js +50 -17
  106. package/koni/background/subscription.d.ts +2 -0
  107. package/koni/background/subscription.js +51 -29
  108. package/package.json +29 -14
  109. package/packageInfo.js +1 -1
  110. package/services/base/types.d.ts +34 -0
  111. package/services/base/types.js +15 -0
  112. package/services/chain-service/handler/SubstrateChainHandler.js +14 -9
  113. package/services/chain-service/helper/psp22_abi.json +1041 -881
  114. package/services/chain-service/helper/psp34_abi.json +2963 -1807
  115. package/services/chain-service/index.d.ts +5 -2
  116. package/services/chain-service/index.js +68 -45
  117. package/services/chain-service/types.d.ts +1 -0
  118. package/services/event-service/index.js +5 -1
  119. package/services/event-service/types.d.ts +5 -9
  120. package/services/event-service/types.js +4 -1
  121. package/services/history-service/index.d.ts +28 -7
  122. package/services/history-service/index.js +101 -50
  123. package/services/history-service/subsquid-multi-chain-history.js +16 -12
  124. package/services/keyring-service/index.d.ts +4 -2
  125. package/services/keyring-service/index.js +11 -13
  126. package/services/migration-service/scripts/MigrateImportedToken.js +2 -1
  127. package/services/price-service/coingecko.js +0 -1
  128. package/services/price-service/index.d.ts +22 -1
  129. package/services/price-service/index.js +71 -24
  130. package/services/request-service/handler/AuthRequestHandler.d.ts +3 -1
  131. package/services/request-service/handler/AuthRequestHandler.js +13 -7
  132. package/services/request-service/handler/EvmRequestHandler.js +8 -12
  133. package/services/request-service/index.d.ts +3 -1
  134. package/services/request-service/index.js +14 -5
  135. package/services/storage-service/DatabaseService.d.ts +2 -0
  136. package/services/storage-service/DatabaseService.js +66 -34
  137. package/services/storage-service/db-stores/Nft.d.ts +2 -2
  138. package/services/storage-service/db-stores/Nft.js +7 -14
  139. package/services/storage-service/db-stores/Transaction.d.ts +2 -0
  140. package/services/storage-service/db-stores/Transaction.js +6 -10
  141. package/services/transaction-service/event-parser/index.js +21 -49
  142. package/services/transaction-service/index.d.ts +2 -0
  143. package/services/transaction-service/index.js +86 -32
  144. package/services/transaction-service/types.d.ts +2 -0
  145. package/services/transaction-service/utils.js +10 -8
  146. package/utils/address.d.ts +3 -0
  147. package/utils/address.js +8 -1
  148. package/utils/index.d.ts +2 -2
  149. package/utils/index.js +7 -13
  150. package/utils/promise.d.ts +6 -0
  151. package/utils/promise.js +20 -0
@@ -31,7 +31,6 @@ export default class KoniState {
31
31
  private readonly unsubscriptionMap;
32
32
  private readonly accountRefStore;
33
33
  private externalRequest;
34
- private serviceInfoSubject;
35
34
  private balanceMap;
36
35
  private balanceSubject;
37
36
  private crowdloanMap;
@@ -109,8 +108,8 @@ export default class KoniState {
109
108
  subscribeNftCollection(): import("dexie").Observable<NftCollection[]>;
110
109
  resetNft(newAddress: string): void;
111
110
  updateNftData(network: string, nftData: NftItem, address: string, callback?: (nftData: NftItem) => void): void;
112
- removeNfts(chain: string, address: string, collectionId: string, nftIds: string[]): import("dexie").PromiseExtended<number>;
113
111
  deleteNftCollection(chain: string, collectionId: string): Promise<void>;
112
+ cleanUpNfts(chain: string, owner: string, collectionId: string[], nftIds: string[], ownNothing?: boolean): void;
114
113
  getNft(): Promise<NftJson | undefined>;
115
114
  subscribeNft(): Subject<NftJson>;
116
115
  resetStakingReward(): void;
@@ -141,7 +140,7 @@ export default class KoniState {
141
140
  private removeInactiveChainBalances;
142
141
  getBalance(reset?: boolean): BalanceJson;
143
142
  getStoredBalance(address: string): Promise<Record<string, BalanceItem>>;
144
- switchAccount(newAddress: string): Promise<void>;
143
+ handleSwitchAccount(newAddress: string): Promise<void>;
145
144
  resetBalanceMap(newAddress: string): Promise<void>;
146
145
  resetCrowdloanMap(newAddress: string): Promise<void>;
147
146
  resetStaking(newAddress: string): void;
@@ -153,7 +152,6 @@ export default class KoniState {
153
152
  setCrowdloanItem(networkKey: string, item: CrowdloanItem): void;
154
153
  private updateCrowdloanStore;
155
154
  subscribeCrowdloan(): Subject<CrowdloanJson>;
156
- getAllPriceIds(): string[];
157
155
  getSmartContractNfts(): _ChainAsset[];
158
156
  getChainInfoMap(): Record<string, _ChainInfo>;
159
157
  getChainStateMap(): Record<string, _ChainState>;
@@ -182,7 +180,6 @@ export default class KoniState {
182
180
  disableChain(chainSlug: string): Promise<boolean>;
183
181
  enableChain(chainSlug: string, enableTokens?: boolean): Promise<boolean>;
184
182
  resetDefaultChains(): boolean;
185
- updateNetworkStatus(networkKey: string, status: _ChainConnectionStatus): void;
186
183
  getSubstrateApiMap(): Record<string, import("@subwallet/extension-base/services/chain-service/types")._SubstrateApi>;
187
184
  getSubstrateApi(networkKey: string): import("@subwallet/extension-base/services/chain-service/types")._SubstrateApi;
188
185
  getEvmApiMap(): Record<string, import("@subwallet/extension-base/services/chain-service/types")._EvmApi>;
@@ -190,7 +187,6 @@ export default class KoniState {
190
187
  getApiMap(): ApiMap;
191
188
  refreshSubstrateApi(key: string): boolean;
192
189
  refreshWeb3Api(key: string): void;
193
- subscribeServiceInfo(): Subject<ServiceInfo>;
194
190
  getServiceInfo(): ServiceInfo;
195
191
  getExternalRequestMap(): Record<string, ExternalRequestPromise>;
196
192
  setExternalRequestMap(id: string, value: ExternalRequestPromise): void;
@@ -219,8 +215,11 @@ export default class KoniState {
219
215
  wakeup(): Promise<void>;
220
216
  cancelSubscription(id: string): boolean;
221
217
  createUnsubscriptionHandle(id: string, unsubscribe: () => void): void;
218
+ updateChainConnectionStatus(chain: string, status: _ChainConnectionStatus): void;
222
219
  autoEnableChains(addresses: string[]): Promise<void>;
223
220
  onAccountAdd(): void;
224
221
  onAccountRemove(): void;
222
+ reloadNft(): Promise<boolean>;
223
+ reloadStaking(): Promise<boolean>;
225
224
  }
226
225
  export {};
@@ -27,7 +27,6 @@ import AccountRefStore from '@subwallet/extension-base/stores/AccountRef';
27
27
  import { isContractAddress, parseContractInput } from '@subwallet/extension-base/utils/eth/parseTransaction';
28
28
  import { decodePair } from '@subwallet/keyring/pair/decode';
29
29
  import { keyring } from '@subwallet/ui-keyring';
30
- import { accounts } from '@subwallet/ui-keyring/observable/accounts';
31
30
  import SimpleKeyring from 'eth-simple-keyring';
32
31
  import { Subject } from 'rxjs';
33
32
  import { assert, BN, hexStripPrefix, hexToU8a, isHex, logger as createLogger, u8aToHex } from '@polkadot/util';
@@ -59,7 +58,6 @@ export default class KoniState {
59
58
  unsubscriptionMap = {};
60
59
  accountRefStore = new AccountRefStore();
61
60
  externalRequest = {};
62
- serviceInfoSubject = new Subject();
63
61
  balanceMap = {};
64
62
  balanceSubject = new Subject();
65
63
  crowdloanMap = generateDefaultCrowdloanMap();
@@ -85,10 +83,10 @@ export default class KoniState {
85
83
  this.notificationService = new NotificationService();
86
84
  this.chainService = new ChainService(this.dbService, this.eventService);
87
85
  this.settingService = new SettingService();
88
- this.requestService = new RequestService(this.chainService, this.settingService);
86
+ this.requestService = new RequestService(this.chainService, this.settingService, this.keyringService);
89
87
  this.priceService = new PriceService(this.dbService, this.eventService, this.chainService);
90
88
  this.balanceService = new BalanceService(this.chainService);
91
- this.historyService = new HistoryService(this.dbService, this.chainService, this.eventService);
89
+ this.historyService = new HistoryService(this.dbService, this.chainService, this.eventService, this.keyringService);
92
90
  this.transactionService = new TransactionService(this.chainService, this.eventService, this.requestService, this.balanceService, this.historyService, this.notificationService, this.dbService);
93
91
  this.migrationService = new MigrationService(this);
94
92
  this.subscription = new KoniSubscription(this, this.dbService);
@@ -213,6 +211,8 @@ export default class KoniState {
213
211
  onReady() {
214
212
  this.subscription.start();
215
213
  this.cron.start();
214
+ this.historyService.start().catch(console.error);
215
+ this.priceService.start().catch(console.error);
216
216
  this.ready = true;
217
217
  this.logger.log('State is ready');
218
218
  }
@@ -253,7 +253,7 @@ export default class KoniState {
253
253
  return this.requestService.getAuthList();
254
254
  }
255
255
  getAddressList(value = false) {
256
- const addressList = Object.keys(accounts.subject.value);
256
+ const addressList = Object.keys(this.keyringService.accounts);
257
257
  return addressList.reduce((addressList, v) => ({
258
258
  ...addressList,
259
259
  [v]: value
@@ -296,7 +296,7 @@ export default class KoniState {
296
296
  return addresses;
297
297
  }
298
298
  async getPooledStakingRecordsByAddress(addresses) {
299
- return await this.dbService.getPooledStakings(addresses, this.activeChainSlugs);
299
+ return this.dbService.getPooledStakings(addresses, this.activeChainSlugs);
300
300
  }
301
301
 
302
302
  // TODO: delete later
@@ -354,12 +354,12 @@ export default class KoniState {
354
354
  this.dbService.addNft(address, nftData).catch(e => this.logger.warn(e));
355
355
  callback && callback(nftData);
356
356
  }
357
- removeNfts(chain, address, collectionId, nftIds) {
358
- return this.dbService.removeNfts(chain, address, collectionId, nftIds);
359
- }
360
357
  deleteNftCollection(chain, collectionId) {
361
358
  return this.dbService.deleteNftCollection(chain, collectionId);
362
359
  }
360
+ cleanUpNfts(chain, owner, collectionId, nftIds, ownNothing) {
361
+ this.dbService.cleanUpNft(chain, owner, collectionId, nftIds, ownNothing).catch(e => this.logger.warn(e));
362
+ }
363
363
  async getNft() {
364
364
  const addresses = this.getDecodedAddresses();
365
365
  if (!addresses.length) {
@@ -446,7 +446,7 @@ export default class KoniState {
446
446
  if (address === ALL_ACCOUNT_KEY) {
447
447
  const pairs = keyring.getAccounts();
448
448
  const pair = pairs[0];
449
- const pairGenesisHash = pair.meta.genesisHash;
449
+ const pairGenesisHash = (pair === null || pair === void 0 ? void 0 : pair.meta.genesisHash) || '';
450
450
  if (pairs.length > 1 || !pair) {
451
451
  result.allGenesisHash = currentGenesisHash || undefined;
452
452
  } else {
@@ -531,7 +531,11 @@ export default class KoniState {
531
531
  isApproved
532
532
  }) => {
533
533
  if (isApproved) {
534
- await this.upsertChainInfo(networkData);
534
+ if (networkData.mode === 'insert') {
535
+ await this.upsertChainInfo(networkData);
536
+ } else {
537
+ // TODO: update existed network (need more discussion)
538
+ }
535
539
  return null;
536
540
  } else {
537
541
  throw new EvmProviderError(EvmProviderErrorType.USER_REJECTED_REQUEST);
@@ -554,7 +558,8 @@ export default class KoniState {
554
558
  assetType: tokenInfo.type,
555
559
  metadata: _parseMetadataForSmartContractAsset(tokenInfo.contractAddress),
556
560
  multiChainAsset: null,
557
- hasValue: _isChainTestNet(this.chainService.getChainInfoByKey(tokenInfo.originChain))
561
+ hasValue: _isChainTestNet(this.chainService.getChainInfoByKey(tokenInfo.originChain)),
562
+ icon: ''
558
563
  });
559
564
  return isApproved;
560
565
  } else {
@@ -656,7 +661,7 @@ export default class KoniState {
656
661
  const items = await this.dbService.stores.balance.getBalanceMapByAddress(address);
657
662
  return items || {};
658
663
  }
659
- async switchAccount(newAddress) {
664
+ async handleSwitchAccount(newAddress) {
660
665
  await Promise.all([this.resetBalanceMap(newAddress), this.resetCrowdloanMap(newAddress)]);
661
666
  }
662
667
  async resetBalanceMap(newAddress) {
@@ -737,9 +742,6 @@ export default class KoniState {
737
742
  subscribeCrowdloan() {
738
743
  return this.crowdloanSubject;
739
744
  }
740
- getAllPriceIds() {
741
- return this.chainService.getAllPriceIds();
742
- }
743
745
  getSmartContractNfts() {
744
746
  return this.chainService.getSmartContractNfts();
745
747
  }
@@ -797,7 +799,9 @@ export default class KoniState {
797
799
  await this.chainService.updateAssetSetting(tokenSlug, {
798
800
  visible: true
799
801
  });
800
- this.eventService.emit('asset.update', tokenSlug);
802
+ this.eventService.emit('asset.updateState', tokenSlug);
803
+ } else {
804
+ this.eventService.emit('asset.updateState', tokenSlug);
801
805
  }
802
806
  }
803
807
  deleteCustomAssets(targetTokens) {
@@ -824,6 +828,7 @@ export default class KoniState {
824
828
  await this.chainService.updateAssetSetting(newNativeTokenSlug, {
825
829
  visible: true
826
830
  });
831
+ this.eventService.emit('asset.updateState', newNativeTokenSlug);
827
832
  }
828
833
  return true;
829
834
  }
@@ -866,13 +871,6 @@ export default class KoniState {
866
871
  const defaultChains = this.getDefaultNetworkKeys();
867
872
  return this.chainService.resetChainInfoMap(defaultChains);
868
873
  }
869
- updateNetworkStatus(networkKey, status) {
870
- const chainState = this.chainService.getChainStateByKey(networkKey);
871
- if (chainState.connectionStatus === status) {
872
- return;
873
- }
874
- this.chainService.setChainConnectionStatus(networkKey, status);
875
- }
876
874
  getSubstrateApiMap() {
877
875
  return this.chainService.getSubstrateApiMap();
878
876
  }
@@ -898,9 +896,6 @@ export default class KoniState {
898
896
  refreshWeb3Api(key) {
899
897
  this.chainService.refreshEvmApi(key);
900
898
  }
901
- subscribeServiceInfo() {
902
- return this.serviceInfoSubject;
903
- }
904
899
  getServiceInfo() {
905
900
  return {
906
901
  chainInfoMap: this.chainService.getChainInfoMap(),
@@ -998,7 +993,10 @@ export default class KoniState {
998
993
  if (!chainId) {
999
994
  return [undefined, undefined];
1000
995
  }
1001
- const rs = Object.entries(this.chainService.getChainInfoMap()).find(([networkKey, chainInfo]) => _getEvmChainId(chainInfo) === chainId);
996
+ const rs = Object.entries(this.chainService.getChainInfoMap()).find(([networkKey, chainInfo]) => {
997
+ var _chainInfo$evmInfo;
998
+ return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$evmInfo = chainInfo.evmInfo) === null || _chainInfo$evmInfo === void 0 ? void 0 : _chainInfo$evmInfo.evmChainId) === chainId;
999
+ });
1002
1000
  if (rs) {
1003
1001
  return rs;
1004
1002
  } else {
@@ -1232,17 +1230,23 @@ export default class KoniState {
1232
1230
  account: account,
1233
1231
  canSign: true
1234
1232
  };
1233
+ const eType = transaction.value ? ExtrinsicType.TRANSFER_BALANCE : ExtrinsicType.EVM_EXECUTE;
1234
+ const transactionData = {
1235
+ ...transaction
1236
+ };
1237
+ if (eType === ExtrinsicType.TRANSFER_BALANCE) {
1238
+ // @ts-ignore
1239
+ transactionData.tokenSlug = this.chainService.getNativeTokenInfo(networkKey).slug;
1240
+ }
1235
1241
 
1236
- // Todo: Convert this to handle transaction
1242
+ // Custom handle this instead of general handler transaction
1237
1243
  const transactionEmitter = await this.transactionService.addTransaction({
1238
1244
  transaction: requestPayload,
1239
1245
  address: requestPayload.from,
1240
1246
  chain: networkKey,
1241
1247
  url,
1242
- data: {
1243
- ...transaction
1244
- },
1245
- extrinsicType: transaction.value ? ExtrinsicType.TRANSFER_BALANCE : ExtrinsicType.EVM_EXECUTE,
1248
+ data: transactionData,
1249
+ extrinsicType: eType,
1246
1250
  chainType: ChainType.EVM
1247
1251
  });
1248
1252
 
@@ -1320,11 +1324,15 @@ export default class KoniState {
1320
1324
  this.cron.stop();
1321
1325
  this.subscription.stop();
1322
1326
  await this.pauseAllNetworks(undefined, 'IDLE mode');
1327
+ await this.historyService.stop();
1328
+ await this.priceService.stop();
1323
1329
  }
1324
1330
  async wakeup() {
1325
1331
  await this.resumeAllNetworks();
1326
1332
  this.cron.start();
1327
1333
  this.subscription.start();
1334
+ await this.historyService.start();
1335
+ await this.priceService.start();
1328
1336
  }
1329
1337
  cancelSubscription(id) {
1330
1338
  if (isSubscriptionRunning(id)) {
@@ -1339,6 +1347,9 @@ export default class KoniState {
1339
1347
  createUnsubscriptionHandle(id, unsubscribe) {
1340
1348
  this.unsubscriptionMap[id] = unsubscribe;
1341
1349
  }
1350
+ updateChainConnectionStatus(chain, status) {
1351
+ this.chainService.setChainConnectionStatus(chain, status);
1352
+ }
1342
1353
  async autoEnableChains(addresses) {
1343
1354
  const assetMap = this.chainService.getAssetRegistry();
1344
1355
  const promiseList = addresses.map(address => {
@@ -1364,7 +1375,7 @@ export default class KoniState {
1364
1375
  var _currentAssetSettings;
1365
1376
  const chain = SUBSCAN_CHAIN_MAP_REVERSE[network];
1366
1377
  const chainInfo = chain ? chainMap[chain] : null;
1367
- const balanceIsEmpty = (!balance || balance === '0') && !locked && locked === '0' && (!bonded || bonded === '0');
1378
+ const balanceIsEmpty = (!balance || balance === '0') && (!locked || locked === '0') && (!bonded || bonded === '0');
1368
1379
 
1369
1380
  // Cancel if chain is not supported or is testnet or balance is 0
1370
1381
  if (!chainInfo || chainInfo.isTestnet || balanceIsEmpty) {
@@ -1409,4 +1420,10 @@ export default class KoniState {
1409
1420
  stores.staking.removeAllByAddress(address).catch(console.error);
1410
1421
  });
1411
1422
  }
1423
+ async reloadNft() {
1424
+ return await this.cron.reloadNft();
1425
+ }
1426
+ async reloadStaking() {
1427
+ return await this.cron.reloadStaking();
1428
+ }
1412
1429
  }
@@ -13,7 +13,6 @@ import { PHISHING_PAGE_REDIRECT } from '@subwallet/extension-base/defaults';
13
13
  import { _generateCustomProviderKey } from '@subwallet/extension-base/services/chain-service/utils';
14
14
  import { canDerive } from '@subwallet/extension-base/utils';
15
15
  import keyring from '@subwallet/ui-keyring';
16
- import { accounts as accountsObservable } from '@subwallet/ui-keyring/observable/accounts';
17
16
  import Web3 from 'web3';
18
17
  import { checkIfDenied } from '@polkadot/phishing';
19
18
  import { assert, isNumber } from '@polkadot/util';
@@ -182,13 +181,13 @@ export default class KoniTabs {
182
181
  anyType
183
182
  }) {
184
183
  const authInfo = await this.getAuthInfo(url);
185
- return transformAccountsV2(accountsObservable.subject.getValue(), anyType, authInfo, accountAuthType);
184
+ return transformAccountsV2(this.#koniState.keyringService.accounts, anyType, authInfo, accountAuthType);
186
185
  }
187
186
  accountsSubscribeV2(url, {
188
187
  accountAuthType
189
188
  }, id, port) {
190
189
  const cb = createSubscription(id, port);
191
- const subscription = accountsObservable.subject.subscribe(accounts => {
190
+ const subscription = this.#koniState.keyringService.accountSubject.subscribe(accounts => {
192
191
  this.getAuthInfo(url).then(authInfo => {
193
192
  cb(transformAccountsV2(accounts, false, authInfo, accountAuthType));
194
193
  }).catch(console.error);
@@ -213,7 +212,7 @@ export default class KoniTabs {
213
212
  async getEvmCurrentAccount(url, getAll = false) {
214
213
  return await new Promise(resolve => {
215
214
  this.getAuthInfo(url).then(authInfo => {
216
- const allAccounts = accountsObservable.subject.getValue();
215
+ const allAccounts = this.#koniState.keyringService.accounts;
217
216
  const accountList = transformAccountsV2(allAccounts, false, authInfo, 'evm').map(a => a.address);
218
217
  let accounts = [];
219
218
  const address = this.#koniState.keyringService.currentAccount.address;
@@ -250,18 +249,25 @@ export default class KoniTabs {
250
249
  slug
251
250
  } = currentEvmNetwork;
252
251
  const evmApi = this.#koniState.getEvmApi(slug);
253
- const web3 = evmApi.api;
254
- if (web3.currentProvider instanceof Web3.providers.WebsocketProvider) {
252
+ const web3 = evmApi === null || evmApi === void 0 ? void 0 : evmApi.api;
253
+ if ((web3 === null || web3 === void 0 ? void 0 : web3.currentProvider) instanceof Web3.providers.WebsocketProvider) {
255
254
  if (!web3.currentProvider.connected) {
256
255
  console.log(`[Web3] ${slug} is disconnected, trying to connect...`);
257
256
  this.#koniState.refreshWeb3Api(slug);
257
+ let checkingNum = 0;
258
258
  const poll = resolve => {
259
+ checkingNum += 1;
259
260
  if (web3.currentProvider.connected) {
260
261
  console.log(`Network [${slug}] is connected.`);
261
262
  resolve(true);
262
263
  } else {
263
264
  console.log(`Connecting to network [${slug}]`);
264
- setTimeout(() => poll(resolve), 400);
265
+ if (checkingNum < 10) {
266
+ setTimeout(() => poll(resolve), 900);
267
+ } else {
268
+ console.log(`Max retry, stop checking [${slug}]`);
269
+ resolve(false);
270
+ }
265
271
  }
266
272
  };
267
273
  await new Promise(poll);
@@ -329,12 +335,16 @@ export default class KoniTabs {
329
335
  contractAddress: input.options.address,
330
336
  originChain: chain
331
337
  });
332
- if (validate.isExist) {
333
- throw new EvmProviderError(EvmProviderErrorType.INTERNAL_ERROR, 'Current token is existed');
334
- } else if (validate.contractError) {
338
+
339
+ // Below code is comment because we will handle exited token in the ui-view
340
+ // if (validate.isExist) {
341
+ // throw new EvmProviderError(EvmProviderErrorType.INTERNAL_ERROR, 'Current token is existed');
342
+ // } else
343
+ if (validate.contractError) {
335
344
  throw new EvmProviderError(EvmProviderErrorType.INVALID_PARAMS, 'Contract address is invalid');
336
345
  }
337
346
  const tokenInfo = {
347
+ slug: validate === null || validate === void 0 ? void 0 : validate.existedSlug,
338
348
  type: tokenType,
339
349
  name: validate.name,
340
350
  contractAddress: input.options.address,
@@ -357,16 +367,38 @@ export default class KoniTabs {
357
367
  } = input[0];
358
368
  if (chainId) {
359
369
  const chainIdNum = parseInt(chainId, 16);
360
- const [networkKey] = this.#koniState.findNetworkKeyByChainId(chainIdNum);
361
- if (networkKey) {
370
+ const [existedNetworkSlug, existedChainInfo] = this.#koniState.findNetworkKeyByChainId(chainIdNum);
371
+ if (existedNetworkSlug && existedChainInfo && existedChainInfo !== null && existedChainInfo !== void 0 && existedChainInfo.evmInfo) {
372
+ const evmInfo = existedChainInfo.evmInfo;
373
+ const substrateInfo = existedChainInfo.substrateInfo;
374
+ const chainState = this.#koniState.getChainStateByKey(existedNetworkSlug);
375
+ await this.#koniState.addNetworkConfirm(id, url, {
376
+ mode: 'update',
377
+ chainSpec: {
378
+ evmChainId: evmInfo.evmChainId,
379
+ decimals: evmInfo.decimals,
380
+ existentialDeposit: evmInfo.existentialDeposit,
381
+ genesisHash: (substrateInfo === null || substrateInfo === void 0 ? void 0 : substrateInfo.genesisHash) || '',
382
+ paraId: (substrateInfo === null || substrateInfo === void 0 ? void 0 : substrateInfo.paraId) || null,
383
+ addressPrefix: (substrateInfo === null || substrateInfo === void 0 ? void 0 : substrateInfo.addressPrefix) || 0
384
+ },
385
+ chainEditInfo: {
386
+ blockExplorer: blockExplorerUrls === null || blockExplorerUrls === void 0 ? void 0 : blockExplorerUrls[0],
387
+ slug: existedNetworkSlug,
388
+ currentProvider: chainState.currentProvider,
389
+ providers: existedChainInfo.providers,
390
+ symbol: evmInfo.symbol,
391
+ chainType: 'EVM',
392
+ name: existedChainInfo.name
393
+ }
394
+ });
362
395
  return await this.switchEvmChain(id, url, {
363
396
  method: 'wallet_switchEthereumChain',
364
397
  params: [{
365
398
  chainId
366
399
  }]
367
400
  });
368
- }
369
- if (rpcUrls && chainName) {
401
+ } else if (rpcUrls && chainName) {
370
402
  const filteredUrls = rpcUrls.filter(targetString => {
371
403
  let url;
372
404
  try {
@@ -407,6 +439,8 @@ export default class KoniTabs {
407
439
  name: chainInfo.name
408
440
  }
409
441
  });
442
+ } else {
443
+ throw new EvmProviderError(EvmProviderErrorType.INVALID_PARAMS, 'Invalid provider');
410
444
  }
411
445
  }
412
446
  }
@@ -661,9 +695,8 @@ export default class KoniTabs {
661
695
  if (e.code) {
662
696
  throw e;
663
697
  } else {
664
- // @ts-ignore
665
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
666
- throw new EvmProviderError(EvmProviderErrorType.INTERNAL_ERROR, e.message);
698
+ console.error(e);
699
+ throw new EvmProviderError(EvmProviderErrorType.INTERNAL_ERROR, e === null || e === void 0 ? void 0 : e.toString());
667
700
  }
668
701
  }
669
702
  }
@@ -1,4 +1,5 @@
1
1
  import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
2
+ import { ChainStakingMetadata } from '@subwallet/extension-base/background/KoniTypes';
2
3
  import { _ChainState, _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
3
4
  import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
4
5
  import KoniState from './handlers/State';
@@ -26,6 +27,7 @@ export declare class KoniSubscription {
26
27
  initNftSubscription(addresses: string[], substrateApiMap: Record<string, _SubstrateApi>, evmApiMap: Record<string, _EvmApi>, smartContractNfts: _ChainAsset[], chainInfoMap: Record<string, _ChainInfo>): void;
27
28
  subscribeStakingReward(address: string): Promise<void>;
28
29
  subscribeStakingRewardFastInterval(address: string): Promise<void>;
30
+ fetchingStakingFromApi(): Promise<Record<string, ChainStakingMetadata>>;
29
31
  fetchChainStakingMetadata(chainInfoMap: Record<string, _ChainInfo>, chainStateMap: Record<string, _ChainState>, substrateApiMap: Record<string, _SubstrateApi>): Promise<void>;
30
32
  fetchNominatorMetadata(currentAddress: string, chainInfoMap: Record<string, _ChainInfo>, chainStateMap: Record<string, _ChainState>, substrateApiMap: Record<string, _SubstrateApi>): Promise<void>;
31
33
  }
@@ -11,6 +11,8 @@ import { getAmplitudeUnclaimedStakingReward } from '@subwallet/extension-base/ko
11
11
  import { nftHandler } from '@subwallet/extension-base/koni/background/handlers';
12
12
  import { _STAKING_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-service/constants';
13
13
  import { _isChainEnabled, _isChainEvmCompatible, _isChainSupportSubstrateStaking, _isSubstrateRelayChain } from '@subwallet/extension-base/services/chain-service/utils';
14
+ import { COMMON_RELOAD_EVENTS } from '@subwallet/extension-base/services/event-service/types';
15
+ import axios from 'axios';
14
16
  import { logger as createLogger } from '@polkadot/util';
15
17
  import { isEthereumAddress } from '@polkadot/util-crypto';
16
18
  export class KoniSubscription {
@@ -58,30 +60,28 @@ export class KoniSubscription {
58
60
  this.subscribeBalancesAndCrowdloans(currentAddress, this.state.getChainInfoMap(), this.state.getChainStateMap(), this.state.getSubstrateApiMap(), this.state.getEvmApiMap());
59
61
  this.subscribeStakingOnChain(currentAddress, this.state.getSubstrateApiMap());
60
62
  }
61
- if (!this.eventHandler) {
62
- const reloadEvents = ['account.add', 'account.remove', 'account.updateCurrent', 'chain.add', 'chain.update', 'chain.enable', 'asset.update', 'asset.enable', 'transaction.done', 'transaction.failed'];
63
- this.eventHandler = (events, eventTypes) => {
64
- var _serviceInfo$currentA;
65
- const serviceInfo = this.state.getServiceInfo();
66
- const needReload = eventTypes.some(eT => reloadEvents.includes(eT));
67
- if (!needReload) {
68
- return;
69
- }
70
- this.logger.log('ServiceInfo updated, restarting...');
71
- const address = (_serviceInfo$currentA = serviceInfo.currentAccountInfo) === null || _serviceInfo$currentA === void 0 ? void 0 : _serviceInfo$currentA.address;
72
- if (!address) {
73
- return;
74
- }
75
- this.subscribeBalancesAndCrowdloans(address, serviceInfo.chainInfoMap, serviceInfo.chainStateMap, serviceInfo.chainApiMap.substrate, serviceInfo.chainApiMap.evm);
76
- this.subscribeStakingOnChain(address, serviceInfo.chainApiMap.substrate);
77
- };
78
- this.state.eventService.onLazy(this.eventHandler);
79
- }
63
+ this.eventHandler = (events, eventTypes) => {
64
+ var _serviceInfo$currentA;
65
+ const serviceInfo = this.state.getServiceInfo();
66
+ const needReload = eventTypes.some(eventType => COMMON_RELOAD_EVENTS.includes(eventType));
67
+ if (!needReload) {
68
+ return;
69
+ }
70
+ this.logger.log('ServiceInfo updated, restarting...');
71
+ const address = (_serviceInfo$currentA = serviceInfo.currentAccountInfo) === null || _serviceInfo$currentA === void 0 ? void 0 : _serviceInfo$currentA.address;
72
+ if (!address) {
73
+ return;
74
+ }
75
+ this.subscribeBalancesAndCrowdloans(address, serviceInfo.chainInfoMap, serviceInfo.chainStateMap, serviceInfo.chainApiMap.substrate, serviceInfo.chainApiMap.evm);
76
+ this.subscribeStakingOnChain(address, serviceInfo.chainApiMap.substrate);
77
+ };
78
+ this.state.eventService.onLazy(this.eventHandler);
80
79
  }
81
80
  stop() {
82
81
  this.logger.log('Stopping subscription');
83
82
  if (this.eventHandler) {
84
83
  this.state.eventService.offLazy(this.eventHandler);
84
+ this.eventHandler = undefined;
85
85
  }
86
86
  this.stopAllSubscription();
87
87
  }
@@ -107,7 +107,7 @@ export class KoniSubscription {
107
107
  });
108
108
  }
109
109
  subscribeBalancesAndCrowdloans(address, chainInfoMap, chainStateMap, substrateApiMap, web3ApiMap, onlyRunOnFirstTime) {
110
- this.state.switchAccount(address).then(() => {
110
+ this.state.handleSwitchAccount(address).then(() => {
111
111
  const addresses = this.state.getDecodedAddresses(address);
112
112
  if (!addresses.length) {
113
113
  return;
@@ -178,9 +178,7 @@ export class KoniSubscription {
178
178
  nftHandler.setDotSamaApiMap(substrateApiMap);
179
179
  nftHandler.setWeb3ApiMap(evmApiMap);
180
180
  nftHandler.setAddresses(addresses);
181
- nftHandler.handleNfts(smartContractNfts, (...args) => this.state.updateNftData(...args), (...args) => this.state.setNftCollection(...args)).then(() => {
182
- this.logger.log('nft state updated');
183
- }).catch(this.logger.log);
181
+ nftHandler.handleNfts(smartContractNfts, (...args) => this.state.updateNftData(...args), (...args) => this.state.setNftCollection(...args), (...args) => this.state.cleanUpNfts(...args)).catch(this.logger.log);
184
182
  }
185
183
  async subscribeStakingReward(address) {
186
184
  const addresses = this.state.getDecodedAddresses(address);
@@ -197,7 +195,6 @@ export class KoniSubscription {
197
195
  });
198
196
  const result = await getNominationStakingRewardData(addresses, targetNetworkMap);
199
197
  this.state.updateStakingReward(result, 'slowInterval');
200
- this.logger.log('Set staking reward state done', result);
201
198
  }
202
199
  async subscribeStakingRewardFastInterval(address) {
203
200
  const addresses = this.state.getDecodedAddresses(address);
@@ -226,13 +223,39 @@ export class KoniSubscription {
226
223
  const [poolingStakingRewards, amplitudeUnclaimedStakingRewards] = await Promise.all([getPoolingStakingRewardData(pooledAddresses, targetChainMap, this.state.getSubstrateApiMap()), getAmplitudeUnclaimedStakingReward(this.state.getSubstrateApiMap(), addresses, chainInfoMap, activeNetworks)]);
227
224
  const result = [...poolingStakingRewards, ...amplitudeUnclaimedStakingRewards];
228
225
  this.state.updateStakingReward(result, 'fastInterval');
229
- this.logger.log('Set staking reward state with fast interval done', result);
226
+ }
227
+ async fetchingStakingFromApi() {
228
+ try {
229
+ const response = await axios.get('https://staking-data.subwallet.app/api/staking/get');
230
+ if (response.status === 200) {
231
+ return response.data;
232
+ }
233
+ } catch (e) {
234
+ this.logger.error(e);
235
+ }
236
+ return {};
230
237
  }
231
238
  async fetchChainStakingMetadata(chainInfoMap, chainStateMap, substrateApiMap) {
232
- await Promise.all(Object.values(chainInfoMap).map(async chainInfo => {
239
+ const filteredChainInfoMap = {};
240
+ Object.values(chainInfoMap).forEach(chainInfo => {
233
241
  const chainState = chainStateMap[chainInfo.slug];
234
242
  if (chainState !== null && chainState !== void 0 && chainState.active && _isChainSupportSubstrateStaking(chainInfo)) {
235
- const chainStakingMetadata = await getChainStakingMetadata(chainInfo.slug, substrateApiMap[chainInfo.slug]);
243
+ filteredChainInfoMap[chainInfo.slug] = chainInfo;
244
+ }
245
+ });
246
+ if (Object.values(filteredChainInfoMap).length === 0) {
247
+ return;
248
+ }
249
+
250
+ // Fetch data from helper API
251
+ const dataFromApi = await this.fetchingStakingFromApi();
252
+ await Promise.all(Object.values(filteredChainInfoMap).map(async chainInfo => {
253
+ // Use fetch API data if available
254
+ if (dataFromApi[chainInfo.slug]) {
255
+ this.state.updateChainStakingMetadata(dataFromApi[chainInfo.slug]);
256
+ } else {
257
+ console.warn('Not found staking data from api', chainInfo.slug);
258
+ const chainStakingMetadata = await getChainStakingMetadata(chainInfo, substrateApiMap[chainInfo.slug]);
236
259
  this.state.updateChainStakingMetadata(chainStakingMetadata);
237
260
  }
238
261
  }));
@@ -249,8 +272,7 @@ export class KoniSubscription {
249
272
  if (currentAddress === ALL_ACCOUNT_KEY) {
250
273
  addresses = await this.state.getStakingOwnersByChains(Object.keys(filteredChainInfoMap));
251
274
  }
252
- const validAddresses = addresses.filter(address => !isEthereumAddress(address));
253
- await Promise.all(validAddresses.map(async address => {
275
+ await Promise.all(addresses.map(async address => {
254
276
  const isEvmAddress = isEthereumAddress(address);
255
277
  await Promise.all(Object.values(filteredChainInfoMap).map(async chainInfo => {
256
278
  if (isEvmAddress && !_isChainEvmCompatible(chainInfo)) {