@subwallet/extension-base 1.0.1 → 1.0.2-1b

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 (220) hide show
  1. package/background/KoniTypes.d.ts +25 -36
  2. package/background/KoniTypes.js +12 -7
  3. package/background/errors/TransactionError.js +21 -1
  4. package/cjs/background/KoniTypes.js +14 -8
  5. package/cjs/background/errors/TransactionError.js +20 -0
  6. package/cjs/constants/index.js +13 -28
  7. package/cjs/koni/api/dotsama/balance.js +60 -224
  8. package/cjs/koni/api/dotsama/transfer.js +30 -29
  9. package/cjs/koni/api/nft/acala_nft/index.js +4 -1
  10. package/cjs/koni/api/nft/bit.country/index.js +4 -1
  11. package/cjs/koni/api/nft/evm_nft/index.js +7 -3
  12. package/cjs/koni/api/nft/index.js +3 -6
  13. package/cjs/koni/api/nft/karura_nft/index.js +4 -1
  14. package/cjs/koni/api/nft/rmrk_nft/index.js +8 -1
  15. package/cjs/koni/api/nft/statemine_nft/index.js +4 -1
  16. package/cjs/koni/api/nft/unique_nft/index.js +6 -1
  17. package/cjs/koni/api/nft/wasm_nft/index.js +169 -111
  18. package/cjs/koni/api/nft/wasm_nft/utils.js +11 -7
  19. package/cjs/koni/api/staking/bonding/amplitude.js +18 -10
  20. package/cjs/koni/api/staking/bonding/astar.js +37 -238
  21. package/cjs/koni/api/staking/bonding/index.js +26 -14
  22. package/cjs/koni/api/staking/bonding/paraChain.js +100 -11
  23. package/cjs/koni/api/staking/bonding/relayChain.js +174 -16
  24. package/cjs/koni/api/staking/bonding/utils.js +55 -10
  25. package/cjs/koni/api/tokens/wasm/index.js +5 -4
  26. package/cjs/koni/api/tokens/wasm/utils.js +63 -0
  27. package/cjs/koni/api/xcm/index.js +0 -111
  28. package/cjs/koni/api/xcm/polkadotXcm.js +2 -2
  29. package/cjs/koni/api/xcm/utils.js +18 -13
  30. package/cjs/koni/api/xcm/xTokens.js +3 -5
  31. package/cjs/koni/api/xcm/xcmPallet.js +9 -6
  32. package/cjs/koni/background/cron.js +179 -77
  33. package/cjs/koni/background/handlers/Extension.js +231 -195
  34. package/cjs/koni/background/handlers/State.js +147 -111
  35. package/cjs/koni/background/handlers/Tabs.js +48 -39
  36. package/cjs/koni/background/subscription.js +64 -56
  37. package/cjs/packageInfo.js +1 -1
  38. package/cjs/page/index.js +5 -0
  39. package/cjs/services/chain-service/constants.js +1 -11
  40. package/cjs/services/chain-service/handler/SubstrateChainHandler.js +13 -8
  41. package/cjs/services/chain-service/handler/light-client/index.js +2 -0
  42. package/cjs/services/chain-service/index.js +39 -6
  43. package/cjs/services/chain-service/utils.js +4 -0
  44. package/cjs/services/event-service/index.js +75 -0
  45. package/cjs/services/event-service/types.js +11 -0
  46. package/cjs/services/history-service/index.js +46 -21
  47. package/cjs/services/history-service/subsquid-multi-chain-history.js +19 -11
  48. package/cjs/services/keyring-service/index.js +101 -0
  49. package/cjs/services/migration-service/index.js +13 -10
  50. package/cjs/{koni/migration/scripts/RemoveWrongCrowdloan.js → services/migration-service/scripts/AutoEnableChainsTokens.js} +11 -6
  51. package/cjs/services/migration-service/scripts/MigrateNetworkSettings.js +39 -19
  52. package/cjs/services/migration-service/scripts/MigrateSettings.js +31 -0
  53. package/cjs/services/migration-service/scripts/MigrateTransactionHistory.js +72 -0
  54. package/cjs/services/migration-service/scripts/index.js +13 -4
  55. package/cjs/services/price-service/coingecko.js +15 -3
  56. package/cjs/services/price-service/index.js +15 -18
  57. package/cjs/services/request-service/constants.js +8 -2
  58. package/cjs/services/request-service/handler/AuthRequestHandler.js +43 -12
  59. package/cjs/services/request-service/index.js +3 -0
  60. package/cjs/services/storage-service/DatabaseService.js +53 -34
  61. package/cjs/services/storage-service/databases/index.js +1 -1
  62. package/cjs/services/storage-service/db-stores/BaseStoreWithAddressAndChain.js +2 -8
  63. package/cjs/services/storage-service/db-stores/Nft.js +8 -18
  64. package/cjs/services/storage-service/db-stores/Transaction.js +10 -7
  65. package/cjs/services/subscan-service/index.js +107 -0
  66. package/cjs/services/subscan-service/subscan-chain-map.js +74 -0
  67. package/cjs/services/subscan-service/types.js +1 -0
  68. package/cjs/services/transaction-service/event-parser/index.js +20 -48
  69. package/cjs/services/transaction-service/index.js +66 -22
  70. package/cjs/services/transaction-service/utils.js +4 -6
  71. package/cjs/utils/address.js +9 -1
  72. package/cjs/utils/index.js +30 -26
  73. package/constants/index.d.ts +8 -13
  74. package/constants/index.js +8 -13
  75. package/koni/api/dotsama/balance.d.ts +0 -1
  76. package/koni/api/dotsama/balance.js +33 -197
  77. package/koni/api/dotsama/transfer.js +5 -4
  78. package/koni/api/nft/acala_nft/index.js +3 -1
  79. package/koni/api/nft/bit.country/index.js +3 -1
  80. package/koni/api/nft/evm_nft/index.js +6 -3
  81. package/koni/api/nft/index.d.ts +1 -2
  82. package/koni/api/nft/index.js +3 -6
  83. package/koni/api/nft/karura_nft/index.js +3 -1
  84. package/koni/api/nft/nft.d.ts +1 -0
  85. package/koni/api/nft/rmrk_nft/index.js +8 -1
  86. package/koni/api/nft/statemine_nft/index.js +3 -1
  87. package/koni/api/nft/unique_nft/index.js +5 -1
  88. package/koni/api/nft/wasm_nft/index.d.ts +0 -2
  89. package/koni/api/nft/wasm_nft/index.js +167 -109
  90. package/koni/api/nft/wasm_nft/utils.d.ts +7 -5
  91. package/koni/api/nft/wasm_nft/utils.js +7 -5
  92. package/koni/api/staking/bonding/amplitude.d.ts +1 -2
  93. package/koni/api/staking/bonding/amplitude.js +22 -13
  94. package/koni/api/staking/bonding/astar.d.ts +2 -11
  95. package/koni/api/staking/bonding/astar.js +39 -231
  96. package/koni/api/staking/bonding/index.d.ts +5 -2
  97. package/koni/api/staking/bonding/index.js +27 -17
  98. package/koni/api/staking/bonding/paraChain.d.ts +4 -1
  99. package/koni/api/staking/bonding/paraChain.js +101 -14
  100. package/koni/api/staking/bonding/relayChain.d.ts +6 -2
  101. package/koni/api/staking/bonding/relayChain.js +172 -17
  102. package/koni/api/staking/bonding/utils.d.ts +15 -2
  103. package/koni/api/staking/bonding/utils.js +53 -11
  104. package/koni/api/tokens/wasm/index.js +5 -4
  105. package/koni/api/tokens/wasm/utils.d.ts +6 -0
  106. package/koni/api/tokens/wasm/utils.js +54 -0
  107. package/koni/api/xcm/index.js +1 -112
  108. package/koni/api/xcm/polkadotXcm.js +3 -3
  109. package/koni/api/xcm/utils.d.ts +5 -6
  110. package/koni/api/xcm/utils.js +15 -10
  111. package/koni/api/xcm/xTokens.js +5 -7
  112. package/koni/api/xcm/xcmPallet.js +10 -9
  113. package/koni/background/cron.d.ts +6 -1
  114. package/koni/background/cron.js +179 -76
  115. package/koni/background/handlers/Extension.d.ts +2 -2
  116. package/koni/background/handlers/Extension.js +161 -125
  117. package/koni/background/handlers/State.d.ts +21 -20
  118. package/koni/background/handlers/State.js +144 -111
  119. package/koni/background/handlers/Tabs.js +30 -20
  120. package/koni/background/subscription.d.ts +1 -1
  121. package/koni/background/subscription.js +64 -58
  122. package/package.json +63 -18
  123. package/packageInfo.js +1 -1
  124. package/page/index.d.ts +2 -0
  125. package/page/index.js +4 -0
  126. package/services/chain-service/constants.d.ts +0 -1
  127. package/services/chain-service/constants.js +0 -9
  128. package/services/chain-service/handler/SubstrateChainHandler.js +14 -9
  129. package/services/chain-service/handler/light-client/index.d.ts +17 -1
  130. package/services/chain-service/handler/light-client/index.js +1 -1
  131. package/services/chain-service/helper/psp22_abi.json +1041 -881
  132. package/services/chain-service/helper/psp34_abi.json +2963 -1807
  133. package/services/chain-service/index.d.ts +6 -4
  134. package/services/chain-service/index.js +40 -9
  135. package/services/chain-service/utils.d.ts +1 -0
  136. package/services/chain-service/utils.js +3 -0
  137. package/services/event-service/index.d.ts +22 -0
  138. package/services/event-service/index.js +63 -0
  139. package/services/event-service/types.d.ts +28 -0
  140. package/services/event-service/types.js +4 -0
  141. package/services/history-service/index.d.ts +5 -3
  142. package/services/history-service/index.js +46 -21
  143. package/services/history-service/subsquid-multi-chain-history.js +22 -13
  144. package/services/keyring-service/index.d.ts +19 -0
  145. package/services/keyring-service/index.js +93 -0
  146. package/services/migration-service/index.js +11 -9
  147. package/services/migration-service/scripts/AutoEnableChainsTokens.d.ts +4 -0
  148. package/services/migration-service/scripts/AutoEnableChainsTokens.js +13 -0
  149. package/services/migration-service/scripts/MigrateNetworkSettings.js +37 -18
  150. package/services/migration-service/scripts/MigrateSettings.d.ts +4 -0
  151. package/services/migration-service/scripts/MigrateSettings.js +23 -0
  152. package/services/migration-service/scripts/MigrateTransactionHistory.d.ts +4 -0
  153. package/services/migration-service/scripts/MigrateTransactionHistory.js +64 -0
  154. package/services/migration-service/scripts/index.d.ts +1 -0
  155. package/services/migration-service/scripts/index.js +10 -3
  156. package/services/price-service/coingecko.js +15 -3
  157. package/services/price-service/index.d.ts +5 -3
  158. package/services/price-service/index.js +15 -18
  159. package/services/request-service/constants.d.ts +1 -0
  160. package/services/request-service/constants.js +6 -1
  161. package/services/request-service/handler/AuthRequestHandler.d.ts +8 -1
  162. package/services/request-service/handler/AuthRequestHandler.js +44 -13
  163. package/services/request-service/index.d.ts +7 -1
  164. package/services/request-service/index.js +3 -0
  165. package/services/storage-service/DatabaseService.d.ts +1 -0
  166. package/services/storage-service/DatabaseService.js +53 -34
  167. package/services/storage-service/databases/index.js +1 -1
  168. package/services/storage-service/db-stores/BaseStoreWithAddressAndChain.d.ts +1 -1
  169. package/services/storage-service/db-stores/BaseStoreWithAddressAndChain.js +2 -8
  170. package/services/storage-service/db-stores/Nft.d.ts +3 -3
  171. package/services/storage-service/db-stores/Nft.js +8 -17
  172. package/services/storage-service/db-stores/Transaction.js +10 -7
  173. package/services/subscan-service/index.d.ts +20 -0
  174. package/services/subscan-service/index.js +99 -0
  175. package/services/subscan-service/subscan-chain-map.d.ts +5 -0
  176. package/services/subscan-service/subscan-chain-map.js +63 -0
  177. package/services/subscan-service/types.d.ts +27 -0
  178. package/services/subscan-service/types.js +1 -0
  179. package/services/transaction-service/event-parser/index.d.ts +2 -2
  180. package/services/transaction-service/event-parser/index.js +21 -49
  181. package/services/transaction-service/index.d.ts +4 -2
  182. package/services/transaction-service/index.js +66 -22
  183. package/services/transaction-service/utils.js +5 -6
  184. package/utils/address.d.ts +1 -0
  185. package/utils/address.js +9 -2
  186. package/utils/index.d.ts +2 -1
  187. package/utils/index.js +26 -23
  188. package/cjs/background/errors/EvmRpcError.js +0 -21
  189. package/cjs/background/errors/SubWalletProviderError.js +0 -17
  190. package/cjs/constants/ethereum.js +0 -19
  191. package/cjs/errors/SubWalletProviderError.js +0 -17
  192. package/cjs/koni/api/xcm/astar.js +0 -160
  193. package/cjs/koni/api/xcm/moonbeamXcm.js +0 -80
  194. package/cjs/koni/api/xcm/statemintXcm.js +0 -197
  195. package/cjs/koni/api/xcm/substrateXcm.js +0 -213
  196. package/cjs/koni/migration/Base.js +0 -20
  197. package/cjs/koni/migration/index.js +0 -45
  198. package/cjs/koni/migration/scripts/ChangeRouteToHome.js +0 -22
  199. package/cjs/koni/migration/scripts/ClearOldStorage.js +0 -24
  200. package/cjs/koni/migration/scripts/RemoveWrongTransactionHistoriesFromStore.js +0 -36
  201. package/cjs/koni/migration/scripts/ResetTransactionHistoryEventIdx.js +0 -21
  202. package/cjs/koni/migration/scripts/index.js +0 -22
  203. package/cjs/koni/page/index.js +0 -16
  204. package/cjs/services/asset-service/index.js +0 -91
  205. package/cjs/services/storage-service/db-stores/ExtraDelegationInfo.js +0 -17
  206. package/cjs/stores/Balance.js +0 -18
  207. package/cjs/stores/Crowdloan.js +0 -18
  208. package/cjs/stores/CustomEvmToken.js +0 -18
  209. package/cjs/stores/NetworkMap.js +0 -18
  210. package/cjs/stores/Nft.js +0 -18
  211. package/cjs/stores/NftCollection.js +0 -18
  212. package/cjs/stores/Price.js +0 -18
  213. package/cjs/stores/Staking.js +0 -18
  214. package/cjs/stores/StakingReward.js +0 -18
  215. package/cjs/utils/eth/parseTransactionData.js +0 -284
  216. package/koni/page/index.d.ts +0 -2
  217. package/koni/page/index.js +0 -9
  218. /package/cjs/{koni/page → page}/SubWalleEvmProvider.js +0 -0
  219. /package/{koni/page → page}/SubWalleEvmProvider.d.ts +0 -0
  220. /package/{koni/page → page}/SubWalleEvmProvider.js +0 -0
@@ -1,11 +1,13 @@
1
1
  import { _AssetRef, _AssetType, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types';
2
2
  import { AssetSetting, ValidateNetworkResponse } from '@subwallet/extension-base/background/KoniTypes';
3
3
  import { _ChainConnectionStatus, _ChainState, _EvmApi, _NetworkUpsertParams, _SubstrateApi, _ValidateCustomAssetRequest, _ValidateCustomAssetResponse } from '@subwallet/extension-base/services/chain-service/types';
4
+ import { EventService } from '@subwallet/extension-base/services/event-service';
4
5
  import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
5
6
  import { BehaviorSubject, Subject } from 'rxjs';
6
7
  export declare class ChainService {
7
8
  private dataMap;
8
9
  private dbService;
10
+ private eventService;
9
11
  private lockChainInfoMap;
10
12
  private substrateChainHandler;
11
13
  private evmChainHandler;
@@ -18,7 +20,7 @@ export declare class ChainService {
18
20
  private assetSettingSubject;
19
21
  private logger;
20
22
  private refreshChainStateTimeout;
21
- constructor(dbService: DatabaseService);
23
+ constructor(dbService: DatabaseService, eventService: EventService);
22
24
  getXcmRefMap(): Record<string, _AssetRef>;
23
25
  getEvmApi(slug: string): _EvmApi;
24
26
  getEvmApiMap(): Record<string, _EvmApi>;
@@ -50,7 +52,7 @@ export declare class ChainService {
50
52
  getChainInfoByKey(key: string): _ChainInfo;
51
53
  getActiveChainInfos(): Record<string, _ChainInfo>;
52
54
  getAssetBySlug(slug: string): _ChainAsset;
53
- getFungibleTokensByChain(chainSlug: string): Record<string, _ChainAsset>;
55
+ getFungibleTokensByChain(chainSlug: string, checkActive?: boolean): Record<string, _ChainAsset>;
54
56
  getXcmEqualAssetByChain(destinationChainSlug: string, originTokenSlug: string): _ChainAsset | undefined;
55
57
  getAssetByChainAndType(chainSlug: string, assetTypes: _AssetType[]): Record<string, _ChainAsset>;
56
58
  getSmartContractNfts(): _ChainAsset[];
@@ -93,10 +95,10 @@ export declare class ChainService {
93
95
  private refreshChainStateInterval;
94
96
  private updateApiMapStatus;
95
97
  initAssetSettings(): Promise<void>;
96
- setAssetSettings(assetSettings: Record<string, AssetSetting>): void;
98
+ setAssetSettings(assetSettings: Record<string, AssetSetting>, emitEvent?: boolean): void;
97
99
  getStoreAssetSettings(): Promise<Record<string, AssetSetting>>;
98
100
  getAssetSettings(): Promise<Record<string, AssetSetting>>;
99
- updateAssetSetting(assetSlug: string, assetSetting: AssetSetting): Promise<void>;
101
+ updateAssetSetting(assetSlug: string, assetSetting: AssetSetting): Promise<boolean | undefined>;
100
102
  updateAssetSettingByChain(chainSlug: string, visible: boolean): Promise<void>;
101
103
  subscribeAssetSettings(): BehaviorSubject<Record<string, AssetSetting>>;
102
104
  }
@@ -21,8 +21,6 @@ export class ChainService {
21
21
  assetRegistry: {},
22
22
  assetRefMap: {}
23
23
  };
24
- // to save chain, token settings from user
25
-
26
24
  lockChainInfoMap = false; // prevent unwanted changes (edit, enable, disable) to chainInfoMap
27
25
 
28
26
  // TODO: consider BehaviorSubject
@@ -35,8 +33,9 @@ export class ChainService {
35
33
  // Todo: Update to new store indexed DB
36
34
  store = new AssetSettingStore();
37
35
  assetSettingSubject = new BehaviorSubject({});
38
- constructor(dbService) {
36
+ constructor(dbService, eventService) {
39
37
  this.dbService = dbService;
38
+ this.eventService = eventService;
40
39
  this.substrateChainHandler = new SubstrateChainHandler();
41
40
  this.evmChainHandler = new EvmChainHandler();
42
41
  this.chainInfoMapSubject.next(this.dataMap.chainInfoMap);
@@ -208,10 +207,13 @@ export class ChainService {
208
207
  getAssetBySlug(slug) {
209
208
  return this.getAssetRegistry()[slug];
210
209
  }
211
- getFungibleTokensByChain(chainSlug) {
210
+ getFungibleTokensByChain(chainSlug, checkActive = false) {
212
211
  const result = {};
212
+ const assetSettings = this.assetSettingSubject.value;
213
213
  Object.values(this.getAssetRegistry()).forEach(chainAsset => {
214
- if (chainAsset.originChain === chainSlug && _isAssetFungibleToken(chainAsset)) {
214
+ var _assetSettings$chainA;
215
+ const _filterActive = !checkActive || ((_assetSettings$chainA = assetSettings[chainAsset.slug]) === null || _assetSettings$chainA === void 0 ? void 0 : _assetSettings$chainA.visible);
216
+ if (chainAsset.originChain === chainSlug && _isAssetFungibleToken(chainAsset) && _filterActive) {
215
217
  result[chainAsset.slug] = chainAsset;
216
218
  }
217
219
  });
@@ -275,6 +277,7 @@ export class ChainService {
275
277
  this.dbService.removeFromChainStore([slug]).catch(console.error);
276
278
  this.updateChainSubscription();
277
279
  this.lockChainInfoMap = false;
280
+ this.eventService.emit('chain.updateState', slug);
278
281
  return true;
279
282
  }
280
283
  resetChainInfoMap(excludedChains) {
@@ -308,6 +311,10 @@ export class ChainService {
308
311
  token.slug = `${_CUSTOM_PREFIX}${defaultSlug}`;
309
312
  }
310
313
  }
314
+ if (token.originChain && _isAssetFungibleToken(token)) {
315
+ var _this$getChainInfoByK;
316
+ token.hasValue = !((_this$getChainInfoByK = this.getChainInfoByKey(token.originChain)) !== null && _this$getChainInfoByK !== void 0 && _this$getChainInfoByK.isTestnet);
317
+ }
311
318
  const assetRegistry = this.getAssetRegistry();
312
319
  assetRegistry[token.slug] = token;
313
320
  this.dbService.updateAssetStore(token).catch(e => this.logger.error(e));
@@ -335,6 +342,9 @@ export class ChainService {
335
342
  this.dbService.removeFromBalanceStore(targetAssets).catch(e => this.logger.error(e));
336
343
  this.dbService.removeFromAssetStore(targetAssets).catch(e => this.logger.error(e));
337
344
  this.assetRegistrySubject.next(assetRegistry);
345
+ targetAssets.forEach(assetSlug => {
346
+ this.eventService.emit('asset.updateState', assetSlug);
347
+ });
338
348
  }
339
349
 
340
350
  // Business logic
@@ -404,6 +414,7 @@ export class ChainService {
404
414
  currentProvider: chainStateMap[chainSlug].currentProvider
405
415
  }).catch(console.error);
406
416
  this.lockChainInfoMap = false;
417
+ this.eventService.emit('chain.updateState', chainSlug);
407
418
  return true;
408
419
  }
409
420
  enableChain(chainSlug) {
@@ -438,6 +449,7 @@ export class ChainService {
438
449
  }).catch(console.error);
439
450
  this.updateChainStateMapSubscription();
440
451
  this.lockChainInfoMap = false;
452
+ this.eventService.emit('chain.updateState', chainSlug);
441
453
  return true;
442
454
  }
443
455
  checkExistedPredefinedChain(genesisHash, evmChainId) {
@@ -659,6 +671,8 @@ export class ChainService {
659
671
  ...targetChainInfo,
660
672
  active: targetChainState.active,
661
673
  currentProvider: targetChainState.currentProvider
674
+ }).then(() => {
675
+ this.eventService.emit('chain.updateState', chainSlug);
662
676
  }).catch(e => this.logger.error(e));
663
677
  }
664
678
  insertChain(params) {
@@ -743,6 +757,8 @@ export class ChainService {
743
757
  active: true,
744
758
  currentProvider: params.chainEditInfo.currentProvider,
745
759
  ...chainInfo
760
+ }).then(() => {
761
+ this.eventService.emit('chain.add', newChainSlug);
746
762
  }).catch(e => this.logger.error(e));
747
763
  return nativeTokenSlug;
748
764
  }
@@ -1086,12 +1102,24 @@ export class ChainService {
1086
1102
  };
1087
1103
  }
1088
1104
  });
1089
- this.setAssetSettings(assetSettings);
1105
+ this.setAssetSettings(assetSettings, false);
1106
+ }
1107
+ this.eventService.emit('asset.ready', true);
1108
+ }
1109
+ setAssetSettings(assetSettings, emitEvent = true) {
1110
+ const updateAssets = [];
1111
+ if (emitEvent) {
1112
+ Object.keys(assetSettings).forEach(slug => {
1113
+ var _this$assetSettingSub;
1114
+ if (((_this$assetSettingSub = this.assetSettingSubject.value[slug]) === null || _this$assetSettingSub === void 0 ? void 0 : _this$assetSettingSub.visible) !== assetSettings[slug].visible) {
1115
+ updateAssets.push(slug);
1116
+ }
1117
+ });
1090
1118
  }
1091
- console.log('Done init asset settings');
1092
- }
1093
- setAssetSettings(assetSettings) {
1094
1119
  this.assetSettingSubject.next(assetSettings);
1120
+ updateAssets.forEach(slug => {
1121
+ this.eventService.emit('asset.updateState', slug);
1122
+ });
1095
1123
  this.store.set('AssetSetting', assetSettings);
1096
1124
  }
1097
1125
  async getStoreAssetSettings() {
@@ -1108,6 +1136,7 @@ export class ChainService {
1108
1136
  }
1109
1137
  async updateAssetSetting(assetSlug, assetSetting) {
1110
1138
  const currentAssetSettings = await this.getAssetSettings();
1139
+ let needUpdateSubject;
1111
1140
 
1112
1141
  // Update settings
1113
1142
  currentAssetSettings[assetSlug] = assetSetting;
@@ -1119,8 +1148,10 @@ export class ChainService {
1119
1148
  // if chain not enabled, then automatically enable
1120
1149
  if (chainState && !chainState.active) {
1121
1150
  this.enableChain(chainState.slug);
1151
+ needUpdateSubject = true;
1122
1152
  }
1123
1153
  }
1154
+ return needUpdateSubject;
1124
1155
  }
1125
1156
  async updateAssetSettingByChain(chainSlug, visible) {
1126
1157
  const storedAssetSettings = await this.getAssetSettings();
@@ -34,6 +34,7 @@ export declare function _getNftTypesSupportedByChain(chainInfo: _ChainInfo): _As
34
34
  export declare function _getTokenTypesSupportedByChain(chainInfo: _ChainInfo): _AssetType[];
35
35
  export declare function _getChainNativeTokenBasicInfo(chainInfo: _ChainInfo): BasicTokenInfo;
36
36
  export declare function _getChainNativeTokenSlug(chainInfo: _ChainInfo): string;
37
+ export declare function _isLocalToken(tokenInfo: _ChainAsset): boolean;
37
38
  export declare function _isTokenEvmSmartContract(tokenInfo: _ChainAsset): boolean;
38
39
  export declare function _isTokenWasmSmartContract(tokenInfo: _ChainAsset): boolean;
39
40
  export declare function _isAssetSmartContractNft(assetInfo: _ChainAsset): boolean;
@@ -206,6 +206,9 @@ export function _getChainNativeTokenSlug(chainInfo) {
206
206
  }
207
207
  return `${chainInfo.slug}-${_AssetType.NATIVE}-${_getChainNativeTokenBasicInfo(chainInfo).symbol}`;
208
208
  }
209
+ export function _isLocalToken(tokenInfo) {
210
+ return tokenInfo.assetType === _AssetType.LOCAL;
211
+ }
209
212
  export function _isTokenEvmSmartContract(tokenInfo) {
210
213
  return [_AssetType.ERC721, _AssetType.ERC20].includes(tokenInfo.assetType);
211
214
  }
@@ -0,0 +1,22 @@
1
+ import { EventItem, EventRegistry, EventType } from '@subwallet/extension-base/services/event-service/types';
2
+ import EventEmitter from 'eventemitter3';
3
+ export declare class EventService extends EventEmitter<EventRegistry> {
4
+ private lazyTime;
5
+ private timeoutId;
6
+ private pendingEvents;
7
+ private lazyEmitter;
8
+ readonly waitKeyringReady: Promise<boolean>;
9
+ readonly waitAccountReady: Promise<boolean>;
10
+ readonly waitChainReady: Promise<boolean>;
11
+ readonly waitAssetReady: Promise<boolean>;
12
+ constructor(options?: {
13
+ lazyTime: number;
14
+ });
15
+ private generateWaitPromise;
16
+ private setLazyTimeout;
17
+ private emitLazy;
18
+ onLazy(callback: (events: EventItem<EventType>[], eventTypes: EventType[]) => void): void;
19
+ offLazy(callback: (events: EventItem<EventType>[], eventTypes: EventType[]) => void): void;
20
+ onceLazy(callback: (events: EventItem<EventType>[], eventTypes: EventType[]) => void): void;
21
+ emit<T extends EventType>(eventType: T, ...args: EventEmitter.EventArgs<EventRegistry, T>): boolean;
22
+ }
@@ -0,0 +1,63 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ // Stateless service handle runtime event on background
5
+
6
+ import EventEmitter from 'eventemitter3';
7
+ export class EventService extends EventEmitter {
8
+ pendingEvents = [];
9
+ lazyEmitter = new EventEmitter();
10
+ constructor(options = {
11
+ lazyTime: 300
12
+ }) {
13
+ super();
14
+ this.lazyTime = options.lazyTime;
15
+ this.timeoutId = null;
16
+ this.waitKeyringReady = this.generateWaitPromise('keyring.ready');
17
+ this.waitAccountReady = this.generateWaitPromise('account.ready');
18
+ this.waitChainReady = this.generateWaitPromise('chain.ready');
19
+ this.waitAssetReady = this.generateWaitPromise('asset.ready');
20
+ }
21
+ generateWaitPromise(eventType) {
22
+ return new Promise(resolve => {
23
+ this.once(eventType, isReady => {
24
+ resolve(isReady);
25
+ });
26
+ });
27
+ }
28
+ setLazyTimeout() {
29
+ if (this.timeoutId) {
30
+ clearTimeout(this.timeoutId);
31
+ }
32
+ this.timeoutId = setTimeout(() => {
33
+ this.emitLazy();
34
+ }, this.lazyTime);
35
+ }
36
+ emitLazy() {
37
+ try {
38
+ this.lazyEmitter.emit('lazy', this.pendingEvents, this.pendingEvents.map(e => e.type));
39
+ } catch (e) {
40
+ console.error('Get error in some listener of lazy event', e);
41
+ }
42
+ this.pendingEvents = [];
43
+ this.timeoutId = null;
44
+ }
45
+ onLazy(callback) {
46
+ this.lazyEmitter.on('lazy', callback);
47
+ }
48
+ offLazy(callback) {
49
+ this.lazyEmitter.off('lazy', callback);
50
+ }
51
+ onceLazy(callback) {
52
+ this.lazyEmitter.once('lazy', callback);
53
+ }
54
+ emit(eventType, ...args) {
55
+ console.debug('Emit event: ', eventType, ...args);
56
+ this.pendingEvents.push({
57
+ type: eventType,
58
+ data: args
59
+ });
60
+ this.setLazyTimeout();
61
+ return super.emit(eventType, ...args);
62
+ }
63
+ }
@@ -0,0 +1,28 @@
1
+ import { CurrentAccountInfo } from '@subwallet/extension-base/background/KoniTypes';
2
+ import { SWTransaction } from '@subwallet/extension-base/services/transaction-service/types';
3
+ export interface EventRegistry {
4
+ 'keyring.ready': [boolean];
5
+ 'account.updateCurrent': [CurrentAccountInfo];
6
+ 'account.ready': [boolean];
7
+ 'account.add': [string];
8
+ 'account.update': [string];
9
+ 'account.remove': [string];
10
+ 'chain.ready': [boolean];
11
+ 'chain.add': [string];
12
+ 'chain.updateState': [string];
13
+ 'asset.ready': [boolean];
14
+ 'asset.updateState': [string];
15
+ 'transaction.done': [SWTransaction];
16
+ 'transaction.failed': [SWTransaction | undefined];
17
+ 'transaction.submitStaking': [string];
18
+ 'transaction.transferNft': [SWTransaction | undefined];
19
+ }
20
+ export declare type EventType = keyof EventRegistry;
21
+ export declare const COMMON_RELOAD_EVENTS: EventType[];
22
+ export interface EventItem<T extends EventType> {
23
+ type: T;
24
+ data: EventRegistry[T];
25
+ }
26
+ export interface EventEmitterRegistry extends EventRegistry {
27
+ lazy: EventItem<EventType>[];
28
+ }
@@ -0,0 +1,4 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export const COMMON_RELOAD_EVENTS = ['account.updateCurrent', 'asset.updateState', 'account.add', 'chain.updateState', 'account.remove', 'chain.add'];
@@ -1,12 +1,14 @@
1
1
  import { TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
2
2
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
3
+ import { EventService } from '@subwallet/extension-base/services/event-service';
3
4
  import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
4
5
  import { BehaviorSubject } from 'rxjs';
5
6
  export declare class HistoryService {
6
7
  private dbService;
7
8
  private chainService;
9
+ private eventService;
8
10
  private historySubject;
9
- constructor(dbService: DatabaseService, chainService: ChainService);
11
+ constructor(dbService: DatabaseService, chainService: ChainService, eventService: EventService);
10
12
  private fetchPromise;
11
13
  private nextFetch;
12
14
  private fetchAndLoadHistories;
@@ -15,8 +17,8 @@ export declare class HistoryService {
15
17
  refreshHistoryInterval(): void;
16
18
  getHistories(): Promise<TransactionHistoryItem<import("@subwallet/extension-base/background/KoniTypes").ExtrinsicType.TRANSFER_BALANCE>[]>;
17
19
  getHistorySubject(): Promise<BehaviorSubject<TransactionHistoryItem<import("@subwallet/extension-base/background/KoniTypes").ExtrinsicType.TRANSFER_BALANCE>[]>>;
18
- insertHistory(historyItem: TransactionHistoryItem): Promise<void>;
19
- updateHistory(chain: string, extrinsicHash: string, historyItem: Partial<TransactionHistoryItem>): Promise<void>;
20
+ updateHistories(chain: string, extrinsicHash: string, updateData: Partial<TransactionHistoryItem>): Promise<void>;
21
+ insertHistories(historyItems: TransactionHistoryItem[]): Promise<void>;
20
22
  addHistoryItems(historyItems: TransactionHistoryItem[]): Promise<void>;
21
23
  removeHistoryByAddress(address: string): Promise<void>;
22
24
  }
@@ -2,25 +2,31 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { CRON_REFRESH_HISTORY_INTERVAL } from '@subwallet/extension-base/constants';
5
+ import { keyring } from '@subwallet/ui-keyring';
5
6
  import { accounts } from '@subwallet/ui-keyring/observable/accounts';
6
7
  import { BehaviorSubject } from 'rxjs';
7
8
  import { fetchMultiChainHistories } from "./subsquid-multi-chain-history.js";
8
9
  export class HistoryService {
9
10
  historySubject = new BehaviorSubject([]);
10
- constructor(dbService, chainService) {
11
+ constructor(dbService, chainService, eventService) {
11
12
  this.dbService = dbService;
12
13
  this.chainService = chainService;
13
-
14
+ this.eventService = eventService;
14
15
  // Load history from database
15
16
  this.dbService.getHistories().then(histories => {
16
17
  this.historySubject.next(histories);
17
18
  }).catch(console.error);
18
19
 
19
- // Add some delay to avoid fetching many times when start extension background
20
- setTimeout(() => {
21
- // Create history interval and refresh it if changes accounts list
22
- accounts.subject.subscribe(this.refreshHistoryInterval.bind(this));
23
- }, 3333);
20
+ // Wait for keyring and chain ready and start
21
+ Promise.all([this.eventService.waitKeyringReady, this.eventService.waitChainReady]).then(() => {
22
+ this.getHistories().catch(console.log);
23
+ this.eventService.on('account.add', () => {
24
+ this.refreshHistoryInterval();
25
+ });
26
+ this.eventService.on('account.remove', address => {
27
+ this.removeHistoryByAddress(address).catch(console.error);
28
+ });
29
+ }).catch(console.error);
24
30
  }
25
31
  fetchPromise = null;
26
32
  nextFetch = undefined;
@@ -43,8 +49,8 @@ export class HistoryService {
43
49
  record.fromName = accountMap[(_record$from = record.from) === null || _record$from === void 0 ? void 0 : _record$from.toLowerCase()];
44
50
  record.toName = accountMap[(_record$to = record.to) === null || _record$to === void 0 ? void 0 : _record$to.toLowerCase()];
45
51
  });
46
- await this.dbService.upsertHistory(historyRecords);
47
- return await this.dbService.getHistories();
52
+ await this.addHistoryItems(historyRecords);
53
+ return historyRecords;
48
54
  }
49
55
  async fetchHistories(addresses) {
50
56
  if (!this.fetchPromise) {
@@ -60,13 +66,16 @@ export class HistoryService {
60
66
  clearTimeout(this.nextFetch);
61
67
  this.invalidCache();
62
68
  this.getHistories().catch(console.error);
63
- this.nextFetch = setTimeout(this.refreshHistoryInterval.bind(this), CRON_REFRESH_HISTORY_INTERVAL);
69
+ this.nextFetch = setTimeout(() => {
70
+ this.refreshHistoryInterval();
71
+ }, CRON_REFRESH_HISTORY_INTERVAL);
64
72
  }
65
73
  async getHistories() {
66
- const addressList = Object.keys(accounts.subject.value);
67
- if (!this.fetchPromise) {
68
- const historyRecords = await this.fetchHistories(addressList);
69
- this.historySubject.next(historyRecords);
74
+ const addressList = keyring.getAccounts().map(a => a.address);
75
+ const currentHistories = this.historySubject.value;
76
+ if (!this.fetchPromise || currentHistories.length === 0) {
77
+ await this.fetchHistories(addressList);
78
+ this.historySubject.next(await this.dbService.getHistories());
70
79
  }
71
80
  return this.historySubject.getValue();
72
81
  }
@@ -74,11 +83,7 @@ export class HistoryService {
74
83
  await this.getHistories();
75
84
  return this.historySubject;
76
85
  }
77
- async insertHistory(historyItem) {
78
- await this.dbService.upsertHistory([historyItem]);
79
- this.historySubject.next(await this.dbService.getHistories());
80
- }
81
- async updateHistory(chain, extrinsicHash, historyItem) {
86
+ async updateHistories(chain, extrinsicHash, updateData) {
82
87
  const existedRecords = await this.dbService.getHistories({
83
88
  chain,
84
89
  extrinsicHash
@@ -86,15 +91,35 @@ export class HistoryService {
86
91
  const updatedRecords = existedRecords.map(r => {
87
92
  return {
88
93
  ...r,
89
- ...historyItem
94
+ ...updateData
90
95
  };
91
96
  });
92
97
  await this.addHistoryItems(updatedRecords);
93
98
  }
94
- async addHistoryItems(historyItems) {
99
+
100
+ // Insert history without check override origin 'app'
101
+ async insertHistories(historyItems) {
95
102
  await this.dbService.upsertHistory(historyItems);
96
103
  this.historySubject.next(await this.dbService.getHistories());
97
104
  }
105
+
106
+ // Insert history with check override origin 'app'
107
+ async addHistoryItems(historyItems) {
108
+ // Prevent override record with original is 'app'
109
+ const appRecords = this.historySubject.value.filter(item => item.origin === 'app');
110
+ const excludeKeys = appRecords.map(item => {
111
+ return `${item.chain}-${item.extrinsicHash}`;
112
+ });
113
+ const updateRecords = historyItems.filter(item => {
114
+ const key = `${item.chain}-${item.extrinsicHash}`;
115
+
116
+ // !excludeKeys.includes(key) && console.log('Cancel update', key);
117
+
118
+ return item.origin === 'app' || !excludeKeys.includes(key);
119
+ });
120
+ await this.dbService.upsertHistory(updateRecords);
121
+ this.historySubject.next(await this.dbService.getHistories());
122
+ }
98
123
  async removeHistoryByAddress(address) {
99
124
  await this.dbService.stores.transaction.removeAllByAddress(address);
100
125
  this.historySubject.next(await this.dbService.getHistories());
@@ -57,11 +57,15 @@ function autoFormatAddress(address) {
57
57
  return '';
58
58
  }
59
59
  }
60
- function generateSignature({
61
- r,
62
- s,
63
- v
64
- }) {
60
+ function generateSignature(input) {
61
+ if (!input) {
62
+ return '';
63
+ }
64
+ const {
65
+ r,
66
+ s,
67
+ v
68
+ } = input;
65
69
  const rHex = r.startsWith('0x') ? r.slice(2) : r;
66
70
  const sHex = s.startsWith('0x') ? s.slice(2) : s;
67
71
  const vHex = parseInt(v).toString(16);
@@ -108,10 +112,15 @@ export function parseSubsquidTransactionData(address, type, historyItem, chainIn
108
112
  to = autoFormatAddress(parsedArgs.to);
109
113
  from = autoFormatAddress(parsedArgs.from);
110
114
  extrinsicHash = parsedArgs.transactionHash;
111
- amount = transaction.value;
115
+ amount = transaction.value || '0';
112
116
  fee = (parseInt(transaction.gasPrice) * parseInt(transaction.gasLimit)).toString();
113
117
  signature = generateSignature(transaction.signature);
114
118
  success = extrinsic.success;
119
+
120
+ // Special fix for moonbeam
121
+ if ((historyItem.chainId === 'moonbeam' || historyItem.chainId === 'moonriver') && typeof amount === 'object') {
122
+ amount = amount[0];
123
+ }
115
124
  break;
116
125
  }
117
126
 
@@ -156,7 +165,7 @@ export function parseSubsquidTransactionData(address, type, historyItem, chainIn
156
165
  }
157
166
  return {
158
167
  address,
159
- origin: MULTI_CHAIN_URL,
168
+ origin: 'subsquid',
160
169
  time: toTimestamp(historyItem.timestamp),
161
170
  chainType,
162
171
  from,
@@ -238,14 +247,14 @@ export async function fetchMultiChainHistories(addresses, chainMap, maxPage = 25
238
247
  console.warn(`Not found chain info for chain id: ${chainId}`);
239
248
  return;
240
249
  }
241
- try {
242
- usedAddresses.forEach(address => {
250
+ usedAddresses.forEach(address => {
251
+ try {
243
252
  const transactionData = parseSubsquidTransactionData(address, name, historyItem, chainInfo, parseData(args), parseData(_data));
244
253
  histories.push(transactionData);
245
- });
246
- } catch (e) {
247
- console.warn('Parse transaction data failed', e);
248
- }
254
+ } catch (e) {
255
+ console.warn('Parse transaction data failed', address, e);
256
+ }
257
+ });
249
258
  });
250
259
  return histories;
251
260
  }
@@ -0,0 +1,19 @@
1
+ import { CurrentAccountInfo, KeyringState } from '@subwallet/extension-base/background/KoniTypes';
2
+ import { EventService } from '@subwallet/extension-base/services/event-service';
3
+ import { SubjectInfo } from '@subwallet/ui-keyring/observable/types';
4
+ import { BehaviorSubject } from 'rxjs';
5
+ export declare class KeyringService {
6
+ private readonly currentAccountStore;
7
+ readonly currentAccountSubject: BehaviorSubject<CurrentAccountInfo>;
8
+ readonly accountsSubject: BehaviorSubject<SubjectInfo>;
9
+ private beforeAccount;
10
+ readonly keyringStateSubject: BehaviorSubject<KeyringState>;
11
+ private eventService;
12
+ constructor(eventService: EventService);
13
+ private subscribeAccounts;
14
+ get keyringState(): KeyringState;
15
+ updateKeyringState(isReady?: boolean): void;
16
+ get accounts(): SubjectInfo;
17
+ get currentAccount(): CurrentAccountInfo;
18
+ setCurrentAccount(currentAccountData: CurrentAccountInfo): void;
19
+ }
@@ -0,0 +1,93 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { CurrentAccountStore } from '@subwallet/extension-base/stores';
5
+ import { keyring } from '@subwallet/ui-keyring';
6
+ import { BehaviorSubject } from 'rxjs';
7
+ export class KeyringService {
8
+ currentAccountStore = new CurrentAccountStore();
9
+ currentAccountSubject = new BehaviorSubject({
10
+ address: '',
11
+ currentGenesisHash: null
12
+ });
13
+ accountsSubject = keyring.accounts.subject;
14
+ beforeAccount = keyring.accounts.subject.value;
15
+ keyringStateSubject = new BehaviorSubject({
16
+ isReady: false,
17
+ hasMasterPassword: false,
18
+ isLocked: false
19
+ });
20
+ constructor(eventService) {
21
+ this.eventService = eventService;
22
+ this.currentAccountStore.get('CurrentAccountInfo', rs => {
23
+ this.currentAccountSubject.next(rs);
24
+ });
25
+ this.subscribeAccounts().catch(console.error);
26
+ }
27
+ async subscribeAccounts() {
28
+ // Wait until account ready
29
+ await new Promise(resolve => {
30
+ const onReady = () => {
31
+ this.eventService.off('account.ready', onReady);
32
+ resolve(true);
33
+ };
34
+ this.eventService.on('account.ready', onReady);
35
+ });
36
+ this.beforeAccount = {
37
+ ...this.accountsSubject.value
38
+ };
39
+ this.accountsSubject.subscribe(subjectInfo => {
40
+ // Check if accounts changed
41
+ const beforeAddresses = Object.keys(this.beforeAccount);
42
+ const afterAddresses = Object.keys(subjectInfo);
43
+ if (beforeAddresses.length > afterAddresses.length) {
44
+ const removedAddresses = beforeAddresses.filter(address => !afterAddresses.includes(address));
45
+
46
+ // Remove account
47
+ removedAddresses.forEach(address => {
48
+ console.log('account.remove', address);
49
+ this.eventService.emit('account.remove', address);
50
+ });
51
+ } else if (beforeAddresses.length < afterAddresses.length) {
52
+ const addedAddresses = afterAddresses.filter(address => !beforeAddresses.includes(address));
53
+
54
+ // Add account
55
+ addedAddresses.forEach(address => {
56
+ console.log('account.add', address);
57
+ this.eventService.emit('account.add', address);
58
+ });
59
+ } else {
60
+ // Handle case update later
61
+ }
62
+ this.beforeAccount = {
63
+ ...subjectInfo
64
+ };
65
+ });
66
+ }
67
+ get keyringState() {
68
+ return this.keyringStateSubject.value;
69
+ }
70
+ updateKeyringState(isReady = true) {
71
+ var _keyring$keyring, _keyring$keyring2;
72
+ if (!this.keyringState.isReady && isReady) {
73
+ this.eventService.emit('keyring.ready', true);
74
+ this.eventService.emit('account.ready', true);
75
+ }
76
+ this.keyringStateSubject.next({
77
+ hasMasterPassword: !!((_keyring$keyring = keyring.keyring) !== null && _keyring$keyring !== void 0 && _keyring$keyring.hasMasterPassword),
78
+ isLocked: !!((_keyring$keyring2 = keyring.keyring) !== null && _keyring$keyring2 !== void 0 && _keyring$keyring2.isLocked),
79
+ isReady: isReady
80
+ });
81
+ }
82
+ get accounts() {
83
+ return this.accountsSubject.value;
84
+ }
85
+ get currentAccount() {
86
+ return this.currentAccountSubject.value;
87
+ }
88
+ setCurrentAccount(currentAccountData) {
89
+ this.currentAccountSubject.next(currentAccountData);
90
+ this.eventService.emit('account.updateCurrent', currentAccountData);
91
+ this.currentAccountStore.set('CurrentAccountInfo', currentAccountData);
92
+ }
93
+ }