@subwallet/extension-base 1.0.4-0 → 1.0.5-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/background/KoniTypes.d.ts +37 -16
  2. package/background/KoniTypes.js +2 -0
  3. package/background/errors/TransactionError.js +4 -0
  4. package/background/handlers/State.d.ts +1 -1
  5. package/background/handlers/State.js +2 -8
  6. package/background/handlers/subscriptions.js +0 -1
  7. package/background/types.d.ts +2 -2
  8. package/cjs/background/KoniTypes.js +2 -0
  9. package/cjs/background/errors/TransactionError.js +4 -0
  10. package/cjs/background/handlers/State.js +1 -7
  11. package/cjs/background/handlers/subscriptions.js +0 -1
  12. package/cjs/constants/index.js +6 -6
  13. package/cjs/koni/api/coingecko.js +1 -4
  14. package/cjs/koni/api/dotsama/balance.js +7 -5
  15. package/cjs/koni/api/dotsama/crowdloan.js +0 -4
  16. package/cjs/koni/api/dotsama/transfer.js +0 -4
  17. package/cjs/koni/api/nft/acala_nft/index.js +1 -1
  18. package/cjs/koni/api/nft/bit.country/index.js +1 -1
  19. package/cjs/koni/api/nft/evm_nft/index.js +2 -3
  20. package/cjs/koni/api/nft/index.js +1 -2
  21. package/cjs/koni/api/nft/karura_nft/index.js +1 -1
  22. package/cjs/koni/api/nft/quartz_nft/index.js +1 -1
  23. package/cjs/koni/api/nft/rmrk_nft/index.js +2 -3
  24. package/cjs/koni/api/nft/statemine_nft/index.js +1 -1
  25. package/cjs/koni/api/nft/transfer.js +5 -5
  26. package/cjs/koni/api/nft/unique_nft/index.js +1 -1
  27. package/cjs/koni/api/nft/unique_nft/uniqueNftV2.js +0 -1
  28. package/cjs/koni/api/nft/wasm_nft/index.js +1 -2
  29. package/cjs/koni/api/staking/bonding/amplitude.js +9 -2
  30. package/cjs/koni/api/staking/bonding/astar.js +37 -13
  31. package/cjs/koni/api/staking/bonding/paraChain.js +10 -2
  32. package/cjs/koni/api/staking/bonding/relayChain.js +21 -4
  33. package/cjs/koni/api/staking/bonding/utils.js +4 -0
  34. package/cjs/koni/api/staking/relayChain.js +0 -1
  35. package/cjs/koni/api/staking/subsquidStaking.js +0 -2
  36. package/cjs/koni/api/tokens/wasm/index.js +0 -1
  37. package/cjs/koni/api/tokens/wasm/utils.js +0 -1
  38. package/cjs/koni/api/xcm/index.js +0 -1
  39. package/cjs/koni/background/cron.js +0 -45
  40. package/cjs/koni/background/handlers/Extension.js +204 -132
  41. package/cjs/koni/background/handlers/State.js +30 -3
  42. package/cjs/koni/background/handlers/Tabs.js +34 -2
  43. package/cjs/koni/background/handlers/index.js +3 -2
  44. package/cjs/koni/background/subscription.js +0 -26
  45. package/cjs/packageInfo.js +1 -1
  46. package/cjs/services/chain-service/constants.js +1 -1
  47. package/cjs/services/chain-service/handler/EvmChainHandler.js +1 -1
  48. package/cjs/services/chain-service/handler/SubstrateChainHandler.js +3 -10
  49. package/cjs/services/chain-service/handler/light-client/index.js +9 -6
  50. package/cjs/services/chain-service/index.js +75 -28
  51. package/cjs/services/chain-service/utils.js +3 -0
  52. package/cjs/services/history-service/helpers/recoverHistoryStatus.js +108 -0
  53. package/cjs/services/history-service/index.js +60 -5
  54. package/cjs/services/history-service/subsquid-multi-chain-history.js +3 -2
  55. package/cjs/services/history-service/testChainMap.js +724 -0
  56. package/cjs/services/keyring-service/index.js +9 -2
  57. package/cjs/services/migration-service/index.js +7 -7
  58. package/cjs/services/migration-service/scripts/MigrateAuthUrls.js +39 -0
  59. package/cjs/services/migration-service/scripts/MigrateAutoLock.js +30 -0
  60. package/cjs/services/migration-service/scripts/MigrateChainPatrol.js +30 -0
  61. package/cjs/services/migration-service/scripts/index.js +7 -1
  62. package/cjs/services/price-service/coingecko.js +1 -1
  63. package/cjs/services/price-service/index.js +0 -4
  64. package/cjs/services/request-service/handler/AuthRequestHandler.js +8 -1
  65. package/cjs/services/request-service/handler/EvmRequestHandler.js +21 -0
  66. package/cjs/services/request-service/handler/MetadataRequestHandler.js +6 -0
  67. package/cjs/services/request-service/handler/SubstrateRequestHandler.js +6 -0
  68. package/cjs/services/request-service/index.js +6 -0
  69. package/cjs/services/setting-service/SettingService.js +4 -9
  70. package/cjs/services/setting-service/constants.js +18 -2
  71. package/cjs/services/storage-service/DatabaseService.js +16 -44
  72. package/cjs/services/storage-service/databases/index.js +1 -1
  73. package/cjs/services/storage-service/db-stores/BaseStore.js +3 -0
  74. package/cjs/services/transaction-service/constants.js +11 -0
  75. package/cjs/services/transaction-service/index.js +31 -9
  76. package/cjs/services/transaction-service/utils.js +25 -14
  77. package/constants/index.d.ts +1 -1
  78. package/constants/index.js +1 -1
  79. package/koni/api/coingecko.js +1 -4
  80. package/koni/api/dotsama/balance.js +7 -5
  81. package/koni/api/dotsama/crowdloan.js +0 -4
  82. package/koni/api/dotsama/transfer.js +0 -4
  83. package/koni/api/nft/acala_nft/index.js +1 -1
  84. package/koni/api/nft/bit.country/index.js +1 -1
  85. package/koni/api/nft/evm_nft/index.js +2 -3
  86. package/koni/api/nft/index.js +1 -2
  87. package/koni/api/nft/karura_nft/index.js +1 -1
  88. package/koni/api/nft/quartz_nft/index.js +1 -1
  89. package/koni/api/nft/rmrk_nft/index.js +2 -3
  90. package/koni/api/nft/statemine_nft/index.js +1 -1
  91. package/koni/api/nft/transfer.js +5 -5
  92. package/koni/api/nft/unique_nft/index.js +1 -1
  93. package/koni/api/nft/unique_nft/uniqueNftV2.js +0 -1
  94. package/koni/api/nft/wasm_nft/index.js +1 -2
  95. package/koni/api/staking/bonding/amplitude.js +9 -2
  96. package/koni/api/staking/bonding/astar.d.ts +2 -1
  97. package/koni/api/staking/bonding/astar.js +36 -13
  98. package/koni/api/staking/bonding/paraChain.js +10 -2
  99. package/koni/api/staking/bonding/relayChain.js +21 -4
  100. package/koni/api/staking/bonding/utils.js +4 -0
  101. package/koni/api/staking/relayChain.js +0 -1
  102. package/koni/api/staking/subsquidStaking.js +0 -2
  103. package/koni/api/tokens/wasm/index.js +0 -1
  104. package/koni/api/tokens/wasm/utils.js +0 -1
  105. package/koni/api/xcm/index.js +0 -1
  106. package/koni/background/cron.js +0 -45
  107. package/koni/background/handlers/Extension.d.ts +3 -0
  108. package/koni/background/handlers/Extension.js +120 -51
  109. package/koni/background/handlers/State.d.ts +4 -1
  110. package/koni/background/handlers/State.js +30 -3
  111. package/koni/background/handlers/Tabs.d.ts +1 -0
  112. package/koni/background/handlers/Tabs.js +32 -1
  113. package/koni/background/handlers/index.js +3 -2
  114. package/koni/background/subscription.d.ts +0 -1
  115. package/koni/background/subscription.js +0 -26
  116. package/package.json +65 -39
  117. package/packageInfo.js +1 -1
  118. package/services/chain-service/constants.js +1 -1
  119. package/services/chain-service/handler/EvmChainHandler.js +1 -1
  120. package/services/chain-service/handler/SubstrateChainHandler.js +3 -10
  121. package/services/chain-service/handler/light-client/index.js +8 -6
  122. package/services/chain-service/helper/api-helper/spec/acala.d.ts +3 -3
  123. package/services/chain-service/index.d.ts +2 -1
  124. package/services/chain-service/index.js +75 -28
  125. package/services/chain-service/utils.js +3 -0
  126. package/services/history-service/helpers/recoverHistoryStatus.d.ts +11 -0
  127. package/services/history-service/helpers/recoverHistoryStatus.js +98 -0
  128. package/services/history-service/index.d.ts +6 -0
  129. package/services/history-service/index.js +61 -6
  130. package/services/history-service/subsquid-multi-chain-history.js +3 -2
  131. package/services/history-service/testChainMap.d.ts +3 -0
  132. package/services/history-service/testChainMap.js +716 -0
  133. package/services/keyring-service/index.d.ts +1 -0
  134. package/services/keyring-service/index.js +9 -2
  135. package/services/migration-service/index.js +7 -7
  136. package/services/migration-service/scripts/MigrateAuthUrls.d.ts +4 -0
  137. package/services/migration-service/scripts/MigrateAuthUrls.js +31 -0
  138. package/services/migration-service/scripts/MigrateAutoLock.d.ts +4 -0
  139. package/services/migration-service/scripts/MigrateAutoLock.js +22 -0
  140. package/services/migration-service/scripts/MigrateChainPatrol.d.ts +4 -0
  141. package/services/migration-service/scripts/MigrateChainPatrol.js +22 -0
  142. package/services/migration-service/scripts/index.js +7 -1
  143. package/services/price-service/coingecko.js +1 -1
  144. package/services/price-service/index.js +0 -4
  145. package/services/request-service/handler/AuthRequestHandler.d.ts +1 -0
  146. package/services/request-service/handler/AuthRequestHandler.js +8 -1
  147. package/services/request-service/handler/EvmRequestHandler.d.ts +1 -0
  148. package/services/request-service/handler/EvmRequestHandler.js +21 -0
  149. package/services/request-service/handler/MetadataRequestHandler.d.ts +1 -0
  150. package/services/request-service/handler/MetadataRequestHandler.js +6 -0
  151. package/services/request-service/handler/SubstrateRequestHandler.d.ts +1 -0
  152. package/services/request-service/handler/SubstrateRequestHandler.js +6 -0
  153. package/services/request-service/index.d.ts +1 -0
  154. package/services/request-service/index.js +6 -0
  155. package/services/setting-service/SettingService.d.ts +1 -0
  156. package/services/setting-service/SettingService.js +5 -10
  157. package/services/setting-service/constants.d.ts +4 -1
  158. package/services/setting-service/constants.js +14 -1
  159. package/services/storage-service/DatabaseService.d.ts +1 -0
  160. package/services/storage-service/DatabaseService.js +16 -44
  161. package/services/storage-service/databases/index.js +1 -1
  162. package/services/storage-service/db-stores/BaseStore.d.ts +1 -0
  163. package/services/storage-service/db-stores/BaseStore.js +3 -0
  164. package/services/transaction-service/constants.d.ts +1 -0
  165. package/services/transaction-service/constants.js +4 -0
  166. package/services/transaction-service/index.d.ts +2 -0
  167. package/services/transaction-service/index.js +32 -10
  168. package/services/transaction-service/utils.d.ts +1 -1
  169. package/services/transaction-service/utils.js +24 -13
@@ -358,7 +358,6 @@ export class ChainService {
358
358
  this.assetRegistrySubject.next(this.getAssetRegistry());
359
359
  this.initApis();
360
360
  await this.initAssetSettings();
361
- this.logger.log('Initiated chains, assets and APIs');
362
361
  }
363
362
  initApis() {
364
363
  // TODO: this might be async
@@ -471,31 +470,43 @@ export class ChainService {
471
470
  return duplicatedSlug;
472
471
  }
473
472
  async fetchLatestData(src, defaultValue) {
474
- try {
475
- const timeout = await new Promise(resolve => {
476
- const id = setTimeout(() => {
477
- clearTimeout(id);
478
- resolve(null);
479
- }, 1000);
480
- });
481
- let result = defaultValue;
482
- const resp = (await Promise.race([timeout, fetch(src)])) || null;
483
- if (!resp) {
484
- return result;
485
- }
486
- if (resp.ok) {
487
- try {
488
- result = await resp.json();
489
- } catch (err) {
490
- console.warn('Error parsing latest data', src, err);
491
- }
492
- }
493
- return result;
494
- } catch (e) {
495
- console.warn('Error fetching latest data', src, e);
496
- return defaultValue;
497
- }
473
+ return Promise.resolve(defaultValue);
474
+ // try {
475
+ // const timeout = new Promise((resolve) => {
476
+ // const id = setTimeout(() => {
477
+ // clearTimeout(id);
478
+ // resolve(null);
479
+ // }, 1500);
480
+ // });
481
+ // let result = defaultValue;
482
+ // const resp = await Promise.race([
483
+ // timeout,
484
+ // fetch(src)
485
+ // ]) as Response || null;
486
+ //
487
+ // if (!resp) {
488
+ // console.warn('Error fetching latest data', src);
489
+ //
490
+ // return result;
491
+ // }
492
+ //
493
+ // if (resp.ok) {
494
+ // try {
495
+ // result = await resp.json();
496
+ // console.log('Fetched latest data', src);
497
+ // } catch (err) {
498
+ // console.warn('Error parsing latest data', src, err);
499
+ // }
500
+ // }
501
+ //
502
+ // return result;
503
+ // } catch (e) {
504
+ // console.warn('Error fetching latest data', src, e);
505
+ //
506
+ // return defaultValue;
507
+ // }
498
508
  }
509
+
499
510
  async initChains() {
500
511
  const storedChainSettings = await this.dbService.getAllChainStore();
501
512
  const latestChainInfoMap = await this.fetchLatestData(_CHAIN_INFO_SRC, ChainInfoMap);
@@ -1128,7 +1139,6 @@ export class ChainService {
1128
1139
  });
1129
1140
  await Promise.all(promiseList);
1130
1141
  if (update) {
1131
- console.log('Update chain connection state');
1132
1142
  this.chainStateMapSubject.next(chainStateMap);
1133
1143
  }
1134
1144
  }
@@ -1181,13 +1191,12 @@ export class ChainService {
1181
1191
  }
1182
1192
  return this.assetSettingSubject.value;
1183
1193
  }
1184
- async updateAssetSetting(assetSlug, assetSetting) {
1194
+ async updateAssetSetting(assetSlug, assetSetting, autoEnableNativeToken) {
1185
1195
  const currentAssetSettings = await this.getAssetSettings();
1186
1196
  let needUpdateSubject;
1187
1197
 
1188
1198
  // Update settings
1189
1199
  currentAssetSettings[assetSlug] = assetSetting;
1190
- this.setAssetSettings(currentAssetSettings);
1191
1200
  if (assetSetting.visible) {
1192
1201
  const assetInfo = this.getAssetBySlug(assetSlug);
1193
1202
  const chainState = this.getChainStateByKey(assetInfo.originChain);
@@ -1196,8 +1205,15 @@ export class ChainService {
1196
1205
  if (chainState && !chainState.active) {
1197
1206
  this.enableChain(chainState.slug);
1198
1207
  needUpdateSubject = true;
1208
+ if (autoEnableNativeToken) {
1209
+ const nativeAsset = this.getNativeTokenInfo(assetInfo.originChain);
1210
+ currentAssetSettings[nativeAsset.slug] = {
1211
+ visible: true
1212
+ };
1213
+ }
1199
1214
  }
1200
1215
  }
1216
+ this.setAssetSettings(currentAssetSettings);
1201
1217
  return needUpdateSubject;
1202
1218
  }
1203
1219
  async updateAssetSettingByChain(chainSlug, visible) {
@@ -1220,4 +1236,35 @@ export class ChainService {
1220
1236
  async getAssetLogoMap() {
1221
1237
  return await this.fetchLatestData(_ASSET_LOGO_MAP_SRC, AssetLogoMap);
1222
1238
  }
1239
+ resetWallet(resetAll) {
1240
+ if (resetAll) {
1241
+ this.setAssetSettings({});
1242
+
1243
+ // Disconnect chain
1244
+ const activeChains = this.getActiveChainInfos();
1245
+ for (const chain of Object.keys(activeChains)) {
1246
+ if (!_DEFAULT_ACTIVE_CHAINS.includes(chain)) {
1247
+ this.disableChain(chain);
1248
+ }
1249
+ }
1250
+
1251
+ // Remove custom chain
1252
+ const allChains = this.getChainInfoMap();
1253
+ for (const chain of Object.keys(allChains)) {
1254
+ if (_isCustomChain(chain)) {
1255
+ this.removeCustomChain(chain);
1256
+ }
1257
+ }
1258
+
1259
+ // Remove custom asset
1260
+ const assetSettings = this.getAssetSettings();
1261
+ const customToken = [];
1262
+ for (const asset of Object.keys(assetSettings)) {
1263
+ if (_isCustomAsset(asset)) {
1264
+ customToken.push(asset);
1265
+ }
1266
+ }
1267
+ this.deleteCustomAssets(customToken);
1268
+ }
1269
+ }
1223
1270
  }
@@ -285,6 +285,9 @@ export function _getAssetDecimals(assetInfo) {
285
285
  }
286
286
  export function _getBlockExplorerFromChain(chainInfo) {
287
287
  let blockExplorer;
288
+ if (!chainInfo) {
289
+ return;
290
+ }
288
291
  if (_isPureEvmChain(chainInfo)) {
289
292
  var _chainInfo$evmInfo4;
290
293
  blockExplorer = chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$evmInfo4 = chainInfo.evmInfo) === null || _chainInfo$evmInfo4 === void 0 ? void 0 : _chainInfo$evmInfo4.blockExplorer;
@@ -0,0 +1,11 @@
1
+ import { TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
2
+ import { ChainService } from '@subwallet/extension-base/services/chain-service';
3
+ export declare enum HistoryRecoverStatus {
4
+ SUCCESS = "SUCCESS",
5
+ FAILED = "FAILED",
6
+ API_INACTIVE = "API_INACTIVE",
7
+ LACK_INFO = "LACK_INFO",
8
+ FAIL_DETECT = "FAIL_DETECT",
9
+ UNKNOWN = "UNKNOWN"
10
+ }
11
+ export declare const historyRecover: (history: TransactionHistoryItem, chainService: ChainService) => Promise<HistoryRecoverStatus>;
@@ -0,0 +1,98 @@
1
+ // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export let HistoryRecoverStatus;
5
+ (function (HistoryRecoverStatus) {
6
+ HistoryRecoverStatus["SUCCESS"] = "SUCCESS";
7
+ HistoryRecoverStatus["FAILED"] = "FAILED";
8
+ HistoryRecoverStatus["API_INACTIVE"] = "API_INACTIVE";
9
+ HistoryRecoverStatus["LACK_INFO"] = "LACK_INFO";
10
+ HistoryRecoverStatus["FAIL_DETECT"] = "FAIL_DETECT";
11
+ HistoryRecoverStatus["UNKNOWN"] = "UNKNOWN";
12
+ })(HistoryRecoverStatus || (HistoryRecoverStatus = {}));
13
+ const substrateRecover = async (history, chainService) => {
14
+ const {
15
+ blockHash,
16
+ chain,
17
+ extrinsicHash
18
+ } = history;
19
+ try {
20
+ const substrateApi = chainService.getSubstrateApi(chain);
21
+ if (substrateApi) {
22
+ const _api = await substrateApi.isReady;
23
+ const api = _api.api;
24
+ if (!blockHash) {
25
+ console.log(`Fail to find extrinsic ${extrinsicHash} on ${chain}: No block hash`);
26
+ return HistoryRecoverStatus.LACK_INFO;
27
+ }
28
+ const block = await api.rpc.chain.getBlock(blockHash);
29
+ const allEvents = await api.query.system.events.at(blockHash);
30
+ const extrinsics = block.block.extrinsics;
31
+ let index;
32
+ extrinsics.forEach((extrinsic, _idx) => {
33
+ if (extrinsicHash === extrinsic.hash.toHex()) {
34
+ index = _idx;
35
+ }
36
+ });
37
+ if (index === undefined) {
38
+ console.log(`Fail to find extrinsic ${extrinsicHash} on ${chain}`);
39
+ return HistoryRecoverStatus.FAIL_DETECT;
40
+ }
41
+ const events = allEvents.filter(({
42
+ phase
43
+ }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.eq(index));
44
+ for (const {
45
+ event
46
+ } of events) {
47
+ if (api.events.system.ExtrinsicSuccess.is(event)) {
48
+ return HistoryRecoverStatus.SUCCESS;
49
+ } else if (api.events.system.ExtrinsicFailed.is(event)) {
50
+ return HistoryRecoverStatus.FAILED;
51
+ }
52
+ }
53
+ return HistoryRecoverStatus.FAIL_DETECT;
54
+ } else {
55
+ console.error(`Fail to update history ${chain}-${extrinsicHash}: Api not active`);
56
+ return HistoryRecoverStatus.API_INACTIVE;
57
+ }
58
+ } catch (e) {
59
+ console.error(`Fail to update history ${chain}-${extrinsicHash}:`, e.message);
60
+ return HistoryRecoverStatus.UNKNOWN;
61
+ }
62
+ };
63
+ const evmRecover = async (history, chainService) => {
64
+ const {
65
+ chain,
66
+ extrinsicHash
67
+ } = history;
68
+ try {
69
+ const evmApi = chainService.getEvmApi(chain);
70
+ if (evmApi) {
71
+ const _api = await evmApi.isReady;
72
+ const api = _api.api;
73
+ const block = await api.eth.getTransactionReceipt(extrinsicHash);
74
+ return block.status ? HistoryRecoverStatus.SUCCESS : HistoryRecoverStatus.FAILED;
75
+ } else {
76
+ console.error(`Fail to update history ${chain}-${extrinsicHash}: Api not active`);
77
+ return HistoryRecoverStatus.API_INACTIVE;
78
+ }
79
+ } catch (e) {
80
+ console.error(`Fail to update history ${chain}-${extrinsicHash}:`, e.message);
81
+ return HistoryRecoverStatus.UNKNOWN;
82
+ }
83
+ };
84
+
85
+ // undefined: Cannot check status
86
+ // true: Transaction success
87
+ // false: Transaction failed
88
+ export const historyRecover = async (history, chainService) => {
89
+ const {
90
+ chainType
91
+ } = history;
92
+ if (chainType) {
93
+ const checkFunction = chainType === 'substrate' ? substrateRecover : evmRecover;
94
+ return await checkFunction(history, chainService);
95
+ } else {
96
+ return HistoryRecoverStatus.LACK_INFO;
97
+ }
98
+ };
@@ -6,6 +6,7 @@ import { KeyringService } from '@subwallet/extension-base/services/keyring-servi
6
6
  import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
7
7
  import { BehaviorSubject } from 'rxjs';
8
8
  export declare class HistoryService implements StoppableServiceInterface, PersistDataServiceInterface, CronServiceInterface {
9
+ #private;
9
10
  private dbService;
10
11
  private chainService;
11
12
  private eventService;
@@ -14,6 +15,7 @@ export declare class HistoryService implements StoppableServiceInterface, Persis
14
15
  constructor(dbService: DatabaseService, chainService: ChainService, eventService: EventService, keyringService: KeyringService);
15
16
  private fetchPromise;
16
17
  private interval;
18
+ private recoverInterval;
17
19
  private fetchAndLoadHistories;
18
20
  getHistories(): Promise<TransactionHistoryItem<import("@subwallet/extension-base/background/KoniTypes").ExtrinsicType.TRANSFER_BALANCE>[]>;
19
21
  getHistorySubject(): Promise<BehaviorSubject<TransactionHistoryItem<import("@subwallet/extension-base/background/KoniTypes").ExtrinsicType.TRANSFER_BALANCE>[]>>;
@@ -27,12 +29,16 @@ export declare class HistoryService implements StoppableServiceInterface, Persis
27
29
  persistData(): Promise<void>;
28
30
  startCron(): Promise<void>;
29
31
  stopCron(): Promise<void>;
32
+ startRecoverHistories(): Promise<void>;
33
+ stopRecoverHistories(): Promise<void>;
34
+ recoverHistories(): Promise<void>;
30
35
  startPromiseHandler: {
31
36
  resolve: (value: void) => void;
32
37
  reject: (reason?: unknown) => void;
33
38
  promise: Promise<void>;
34
39
  };
35
40
  init(): Promise<void>;
41
+ getProcessingHistory(): Promise<void>;
36
42
  start(): Promise<void>;
37
43
  waitForStarted(): Promise<void>;
38
44
  stopPromiseHandler: {
@@ -1,14 +1,17 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-base
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import { CRON_REFRESH_HISTORY_INTERVAL } from '@subwallet/extension-base/constants';
4
+ import { ExtrinsicStatus } from '@subwallet/extension-base/background/KoniTypes';
5
+ import { CRON_RECOVER_HISTORY_INTERVAL, CRON_REFRESH_HISTORY_INTERVAL } from '@subwallet/extension-base/constants';
5
6
  import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
7
+ import { historyRecover, HistoryRecoverStatus } from '@subwallet/extension-base/services/history-service/helpers/recoverHistoryStatus';
6
8
  import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
7
9
  import { keyring } from '@subwallet/ui-keyring';
8
10
  import { BehaviorSubject } from 'rxjs';
9
11
  import { fetchMultiChainHistories } from "./subsquid-multi-chain-history.js";
10
12
  export class HistoryService {
11
13
  historySubject = new BehaviorSubject([]);
14
+ #processingHistories = {};
12
15
  constructor(dbService, chainService, eventService, keyringService) {
13
16
  this.dbService = dbService;
14
17
  this.chainService = chainService;
@@ -18,6 +21,7 @@ export class HistoryService {
18
21
  }
19
22
  fetchPromise = null;
20
23
  interval = undefined;
24
+ recoverInterval = undefined;
21
25
  async fetchAndLoadHistories(addresses) {
22
26
  if (!addresses || addresses.length === 0) {
23
27
  return [];
@@ -88,9 +92,6 @@ export class HistoryService {
88
92
  });
89
93
  const updateRecords = historyItems.filter(item => {
90
94
  const key = `${item.chain}-${item.extrinsicHash}`;
91
-
92
- // !excludeKeys.includes(key) && console.log('Cancel update', key);
93
-
94
95
  return item.origin === 'app' || !excludeKeys.includes(key);
95
96
  });
96
97
  await this.dbService.upsertHistory(updateRecords);
@@ -119,12 +120,56 @@ export class HistoryService {
119
120
  this.fetchPromise = null;
120
121
  return Promise.resolve();
121
122
  }
123
+ async startRecoverHistories() {
124
+ await this.recoverHistories();
125
+ this.recoverInterval = setInterval(() => {
126
+ this.recoverHistories().catch(console.error);
127
+ }, CRON_RECOVER_HISTORY_INTERVAL);
128
+ }
129
+ stopRecoverHistories() {
130
+ clearInterval(this.recoverInterval);
131
+ return Promise.resolve();
132
+ }
133
+ async recoverHistories() {
134
+ const list = [];
135
+ for (const processingHistory of Object.values(this.#processingHistories)) {
136
+ const chainState = this.chainService.getChainStateByKey(processingHistory.chain);
137
+ if (chainState.active) {
138
+ list.push(processingHistory);
139
+ }
140
+ if (list.length >= 10) {
141
+ break;
142
+ }
143
+ }
144
+ const promises = list.map(history => historyRecover(history, this.chainService));
145
+ const result = await Promise.all(promises);
146
+ result.forEach((status, index) => {
147
+ const extrinsicHash = list[index].extrinsicHash;
148
+ switch (status) {
149
+ case HistoryRecoverStatus.API_INACTIVE:
150
+ break;
151
+ case HistoryRecoverStatus.FAILED:
152
+ case HistoryRecoverStatus.SUCCESS:
153
+ this.updateHistoryByExtrinsicHash(extrinsicHash, {
154
+ status: status === HistoryRecoverStatus.SUCCESS ? ExtrinsicStatus.SUCCESS : ExtrinsicStatus.FAIL
155
+ }).catch(console.error);
156
+ delete this.#processingHistories[extrinsicHash];
157
+ break;
158
+ default:
159
+ delete this.#processingHistories[extrinsicHash];
160
+ }
161
+ });
162
+ if (!Object.keys(this.#processingHistories).length) {
163
+ await this.stopRecoverHistories();
164
+ }
165
+ }
122
166
  startPromiseHandler = createPromiseHandler();
123
167
  async init() {
124
168
  this.status = ServiceStatus.INITIALIZING;
125
169
  await this.loadData();
126
170
  Promise.all([this.eventService.waitKeyringReady, this.eventService.waitChainReady]).then(() => {
127
171
  this.getHistories().catch(console.log);
172
+ this.getProcessingHistory().catch(console.log);
128
173
  this.eventService.on('account.add', () => {
129
174
  (async () => {
130
175
  await this.stopCron();
@@ -137,12 +182,22 @@ export class HistoryService {
137
182
  }).catch(console.error);
138
183
  this.status = ServiceStatus.INITIALIZED;
139
184
  }
185
+ async getProcessingHistory() {
186
+ const histories = await this.dbService.getHistories();
187
+ this.#processingHistories = {};
188
+ histories.filter(history => {
189
+ return history.status === 'processing';
190
+ }).forEach(history => {
191
+ this.#processingHistories[history.extrinsicHash] = history;
192
+ });
193
+ this.startRecoverHistories().catch(console.error);
194
+ }
140
195
  async start() {
141
196
  try {
142
- console.debug('Start history service');
143
197
  this.startPromiseHandler = createPromiseHandler();
144
198
  this.status = ServiceStatus.STARTING;
145
199
  await this.startCron();
200
+ await this.startRecoverHistories();
146
201
  this.status = ServiceStatus.STARTED;
147
202
  this.startPromiseHandler.resolve();
148
203
  } catch (e) {
@@ -154,12 +209,12 @@ export class HistoryService {
154
209
  }
155
210
  stopPromiseHandler = createPromiseHandler();
156
211
  async stop() {
157
- console.debug('Stop history service');
158
212
  try {
159
213
  this.stopPromiseHandler = createPromiseHandler();
160
214
  this.status = ServiceStatus.STOPPING;
161
215
  await this.persistData();
162
216
  await this.stopCron();
217
+ await this.stopRecoverHistories();
163
218
  this.stopPromiseHandler.resolve();
164
219
  this.status = ServiceStatus.STOPPED;
165
220
  } catch (e) {
@@ -110,7 +110,7 @@ export function parseSubsquidTransactionData(address, type, historyItem, chainIn
110
110
  const parsedArgs = args;
111
111
  const transaction = data.call.data.args.transaction.value;
112
112
  to = autoFormatAddress(parsedArgs.to);
113
- from = autoFormatAddress(parsedArgs.from);
113
+ from = autoFormatAddress(parsedArgs.from || address);
114
114
  extrinsicHash = parsedArgs.transactionHash || extrinsic.hash;
115
115
  amount = transaction.value || '0';
116
116
  fee = (parseInt(transaction.gasPrice) * parseInt(transaction.gasLimit)).toString();
@@ -244,7 +244,8 @@ export async function fetchMultiChainHistories(addresses, chainMap, maxPage = 25
244
244
  const usedAddresses = relatedAddresses.filter(a => lowerAddresses.includes(a.toLowerCase()));
245
245
  const chainInfo = chainMap[chainId];
246
246
  if (chainInfo === undefined) {
247
- console.warn(`Not found chain info for chain id: ${chainId}`);
247
+ console.warn(`Not found chain info for chain id: ${chainId}`); // TODO: resolve conflicting chainId
248
+
248
249
  return;
249
250
  }
250
251
  usedAddresses.forEach(address => {
@@ -0,0 +1,3 @@
1
+ import { _ChainInfo } from '@subwallet/chain-list/types';
2
+ export declare const TEST_CHAIN_LIST: _ChainInfo[];
3
+ export declare const TEST_CHAIN_MAP: Record<string, _ChainInfo>;