@subwallet/extension-base 1.2.14-0 → 1.2.16-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 (96) hide show
  1. package/background/KoniTypes.d.ts +6 -1
  2. package/cjs/core/substrate/nominationpools-pallet.js +2 -1
  3. package/cjs/koni/api/nft/config.js +9 -5
  4. package/cjs/koni/api/nft/index.js +9 -1
  5. package/cjs/koni/api/nft/unique_network_nft/index.js +12 -20
  6. package/cjs/koni/background/handlers/Extension.js +45 -7
  7. package/cjs/koni/background/handlers/State.js +11 -1
  8. package/cjs/packageInfo.js +1 -1
  9. package/cjs/services/balance-service/helpers/subscribe/index.js +1 -1
  10. package/cjs/services/balance-service/helpers/subscribe/substrate/gear.js +135 -0
  11. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +9 -62
  12. package/cjs/services/balance-service/transfer/token.js +4 -3
  13. package/cjs/services/chain-service/constants.js +1 -0
  14. package/cjs/services/chain-service/handler/SubstrateApi.js +3 -1
  15. package/cjs/services/chain-service/handler/SubstrateChainHandler.js +21 -26
  16. package/cjs/services/chain-service/health-check/constants/index.js +4 -4
  17. package/cjs/services/chain-service/health-check/utils/asset-info.js +23 -6
  18. package/cjs/services/chain-service/health-check/utils/chain-info.js +25 -2
  19. package/cjs/services/chain-service/health-check/utils/new-utils/asset-asset-validate.js +160 -0
  20. package/cjs/services/chain-service/health-check/utils/new-utils/asset-validate.js +45 -0
  21. package/cjs/services/chain-service/health-check/utils/new-utils/chain-asset-validate.js +73 -0
  22. package/cjs/services/chain-service/health-check/utils/new-utils/chain-validate.js +34 -0
  23. package/cjs/services/chain-service/index.js +77 -3
  24. package/cjs/services/chain-service/types.js +1 -1
  25. package/cjs/services/chain-service/utils/index.js +18 -12
  26. package/cjs/services/earning-service/handlers/liquid-staking/acala.js +49 -19
  27. package/cjs/services/earning-service/service.js +3 -0
  28. package/cjs/services/migration-service/scripts/databases/ClearMetadataDatabase.js +16 -0
  29. package/cjs/services/migration-service/scripts/index.js +7 -7
  30. package/cjs/services/price-service/coingecko.js +57 -32
  31. package/cjs/services/price-service/index.js +30 -11
  32. package/cjs/services/transaction-service/index.js +12 -7
  33. package/cjs/utils/gear/combine.js +28 -0
  34. package/cjs/utils/gear/grc20.js +56 -49
  35. package/cjs/utils/gear/index.js +22 -0
  36. package/cjs/utils/gear/vft.js +173 -0
  37. package/cjs/utils/metadata.js +45 -34
  38. package/core/substrate/nominationpools-pallet.js +2 -1
  39. package/koni/api/nft/config.d.ts +1 -0
  40. package/koni/api/nft/config.js +3 -1
  41. package/koni/api/nft/index.js +9 -1
  42. package/koni/api/nft/unique_network_nft/index.js +12 -20
  43. package/koni/background/handlers/Extension.d.ts +2 -0
  44. package/koni/background/handlers/Extension.js +37 -1
  45. package/koni/background/handlers/State.d.ts +2 -0
  46. package/koni/background/handlers/State.js +11 -1
  47. package/package.json +44 -8
  48. package/packageInfo.js +1 -1
  49. package/services/balance-service/helpers/subscribe/index.js +1 -1
  50. package/services/balance-service/helpers/subscribe/substrate/gear.d.ts +4 -0
  51. package/services/balance-service/helpers/subscribe/substrate/gear.js +123 -0
  52. package/services/balance-service/helpers/subscribe/substrate/index.js +10 -61
  53. package/services/balance-service/transfer/token.js +5 -4
  54. package/services/chain-service/constants.d.ts +1 -0
  55. package/services/chain-service/constants.js +1 -0
  56. package/services/chain-service/handler/SubstrateApi.d.ts +1 -1
  57. package/services/chain-service/handler/SubstrateApi.js +3 -1
  58. package/services/chain-service/handler/SubstrateChainHandler.d.ts +1 -0
  59. package/services/chain-service/handler/SubstrateChainHandler.js +22 -27
  60. package/services/chain-service/health-check/constants/index.js +4 -4
  61. package/services/chain-service/health-check/utils/asset-info.d.ts +1 -0
  62. package/services/chain-service/health-check/utils/asset-info.js +20 -4
  63. package/services/chain-service/health-check/utils/chain-info.d.ts +4 -2
  64. package/services/chain-service/health-check/utils/chain-info.js +20 -0
  65. package/services/chain-service/health-check/utils/new-utils/asset-asset-validate.d.ts +10 -0
  66. package/services/chain-service/health-check/utils/new-utils/asset-asset-validate.js +146 -0
  67. package/services/chain-service/health-check/utils/new-utils/asset-validate.d.ts +3 -0
  68. package/services/chain-service/health-check/utils/new-utils/asset-validate.js +38 -0
  69. package/services/chain-service/health-check/utils/new-utils/chain-asset-validate.d.ts +5 -0
  70. package/services/chain-service/health-check/utils/new-utils/chain-asset-validate.js +64 -0
  71. package/services/chain-service/health-check/utils/new-utils/chain-validate.d.ts +4 -0
  72. package/services/chain-service/health-check/utils/new-utils/chain-validate.js +26 -0
  73. package/services/chain-service/index.d.ts +4 -0
  74. package/services/chain-service/index.js +78 -4
  75. package/services/chain-service/types.d.ts +6 -0
  76. package/services/chain-service/types.js +1 -1
  77. package/services/chain-service/utils/index.d.ts +1 -0
  78. package/services/chain-service/utils/index.js +16 -12
  79. package/services/earning-service/handlers/liquid-staking/acala.js +46 -17
  80. package/services/earning-service/service.js +3 -0
  81. package/services/migration-service/scripts/databases/ClearMetadataDatabase.js +16 -0
  82. package/services/migration-service/scripts/index.js +7 -7
  83. package/services/price-service/coingecko.js +54 -32
  84. package/services/price-service/index.js +29 -11
  85. package/services/transaction-service/index.js +13 -8
  86. package/types/metadata.d.ts +9 -2
  87. package/utils/gear/combine.d.ts +10 -0
  88. package/utils/gear/combine.js +18 -0
  89. package/utils/gear/grc20.d.ts +18 -20
  90. package/utils/gear/grc20.js +53 -45
  91. package/utils/gear/index.d.ts +2 -0
  92. package/utils/gear/index.js +3 -1
  93. package/utils/gear/vft.d.ts +36 -0
  94. package/utils/gear/vft.js +162 -0
  95. package/utils/metadata.d.ts +7 -2
  96. package/utils/metadata.js +41 -31
@@ -11,14 +11,14 @@ import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chai
11
11
  import { _ChainConnectionStatus, _CUSTOM_PREFIX, _NFT_CONTRACT_STANDARDS, _SMART_CONTRACT_STANDARDS } from '@subwallet/extension-base/services/chain-service/types';
12
12
  import { _isAssetAutoEnable, _isAssetCanPayTxFee, _isAssetFungibleToken, _isChainEnabled, _isCustomAsset, _isCustomChain, _isCustomProvider, _isEqualContractAddress, _isEqualSmartContractAsset, _isMantaZkAsset, _isPureEvmChain, _isPureSubstrateChain, _parseAssetRefKey, fetchPatchData, randomizeProvider, updateLatestChainInfo } from '@subwallet/extension-base/services/chain-service/utils';
13
13
  import AssetSettingStore from '@subwallet/extension-base/stores/AssetSetting';
14
- import { addLazy, fetchStaticData, filterAssetsByChainAndType, MODULE_SUPPORT } from '@subwallet/extension-base/utils';
14
+ import { addLazy, calculateMetadataHash, fetchStaticData, filterAssetsByChainAndType, getShortMetadata, MODULE_SUPPORT } from '@subwallet/extension-base/utils';
15
15
  import { BehaviorSubject, Subject } from 'rxjs';
16
16
  import Web3 from 'web3';
17
17
  import { logger as createLogger } from '@polkadot/util/logger';
18
18
  const filterChainInfoMap = (data, ignoredChains) => {
19
19
  return Object.fromEntries(Object.entries(data).filter(([slug, info]) => !info.bitcoinInfo && !ignoredChains.includes(slug)));
20
20
  };
21
- const ignoredList = ['bevm', 'bevmTest', 'bevm_testnet', 'layerEdge_testnet', 'merlinEvm', 'botanixEvmTest', 'syscoin_evm', 'rollux_evm'];
21
+ const ignoredList = ['bevm', 'bevmTest', 'bevm_testnet', 'layerEdge_testnet', 'merlinEvm', 'botanixEvmTest', 'syscoin_evm', 'syscoin_evm_testnet', 'rollux_evm', 'rollux_testnet', 'boolAlpha', 'boolBeta_testnet', 'core', 'satoshivm', 'satoshivm_testnet'];
22
22
  const filterAssetInfoMap = (chainInfo, assets) => {
23
23
  return Object.fromEntries(Object.entries(assets).filter(([, info]) => chainInfo[info.originChain]));
24
24
  };
@@ -233,7 +233,7 @@ export class ChainService {
233
233
  return Object.entries(this.dataMap.chainStateMap).filter(([, chainState]) => _isChainEnabled(chainState)).map(([key]) => key);
234
234
  }
235
235
  getSupportedSmartContractTypes() {
236
- return [_AssetType.ERC20, _AssetType.ERC721, _AssetType.PSP22, _AssetType.PSP34, _AssetType.GRC20, _AssetType.GRC721];
236
+ return [_AssetType.ERC20, _AssetType.ERC721, _AssetType.PSP22, _AssetType.PSP34, _AssetType.GRC20, _AssetType.GRC721, _AssetType.VFT];
237
237
  }
238
238
  getActiveChainInfoMap() {
239
239
  const result = {};
@@ -655,6 +655,34 @@ export class ChainService {
655
655
  }
656
656
  const onUpdateStatus = status => {
657
657
  const slug = chainInfo.slug;
658
+ const isActive = this.getChainStateByKey(slug).active;
659
+ const isConnectProblem = status !== _ChainConnectionStatus.CONNECTING && status !== _ChainConnectionStatus.CONNECTED;
660
+ const isLightRpc = endpoint.startsWith('light');
661
+ if (isActive && isConnectProblem && !isLightRpc) {
662
+ const reportApiUrl = 'https://api-cache.subwallet.app/api/health-check/report-rpc';
663
+ const requestBody = {
664
+ chainSlug: slug,
665
+ chainStatus: status,
666
+ rpcReport: {
667
+ [providerName]: endpoint
668
+ },
669
+ configStatus: {
670
+ countUnstable: 10,
671
+ countDie: 20
672
+ }
673
+ };
674
+ fetch(reportApiUrl, {
675
+ // can get status from this response
676
+ method: 'POST',
677
+ headers: {
678
+ 'X-API-KEY': '9b1c94a5e1f3a2d9f8b2a4d6e1f3a2d9',
679
+ 'Content-Type': 'application/json'
680
+ },
681
+ body: JSON.stringify(requestBody)
682
+ })
683
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
684
+ .then(() => {}).catch(error => console.error('Error connecting to the report API:', error));
685
+ }
658
686
  this.updateChainConnectionStatus(slug, status);
659
687
  };
660
688
  if (chainInfo.substrateInfo !== null && chainInfo.substrateInfo !== undefined) {
@@ -664,6 +692,7 @@ export class ChainService {
664
692
  //
665
693
  // this.substrateChainHandler.setSubstrateApi(chainInfo.slug, chainApi);
666
694
  // } else {
695
+
667
696
  const chainApi = await this.substrateChainHandler.initApi(chainInfo.slug, endpoint, {
668
697
  providerName,
669
698
  onUpdateStatus
@@ -1420,7 +1449,7 @@ export class ChainService {
1420
1449
  async getSmartContractTokenInfo(contractAddress, tokenType, originChain, contractCaller) {
1421
1450
  if ([_AssetType.ERC721, _AssetType.ERC20].includes(tokenType)) {
1422
1451
  return await this.evmChainHandler.getEvmContractTokenInfo(contractAddress, tokenType, originChain);
1423
- } else if ([_AssetType.PSP34, _AssetType.PSP22, _AssetType.GRC20].includes(tokenType)) {
1452
+ } else if ([_AssetType.PSP34, _AssetType.PSP22, _AssetType.GRC20, _AssetType.VFT].includes(tokenType)) {
1424
1453
  return await this.substrateChainHandler.getSubstrateContractTokenInfo(contractAddress, tokenType, originChain, contractCaller);
1425
1454
  }
1426
1455
  return {
@@ -1638,6 +1667,9 @@ export class ChainService {
1638
1667
  this.deleteCustomAssets(customToken);
1639
1668
  }
1640
1669
  }
1670
+
1671
+ /* Metadata */
1672
+
1641
1673
  getMetadata(chain) {
1642
1674
  return this.dbService.stores.metadata.getMetadata(chain);
1643
1675
  }
@@ -1647,6 +1679,48 @@ export class ChainService {
1647
1679
  getMetadataByHash(hash) {
1648
1680
  return this.dbService.stores.metadata.getMetadataByGenesisHash(hash);
1649
1681
  }
1682
+ getExtraInfo(chain) {
1683
+ var _chainInfo$substrateI2, _chainInfo$substrateI3, _chainInfo$substrateI4, _chainInfo$substrateI5, _chainInfo$substrateI6, _chainInfo$substrateI7;
1684
+ const chainInfo = this.getChainInfoByKey(chain);
1685
+ return {
1686
+ decimals: (_chainInfo$substrateI2 = (_chainInfo$substrateI3 = chainInfo.substrateInfo) === null || _chainInfo$substrateI3 === void 0 ? void 0 : _chainInfo$substrateI3.decimals) !== null && _chainInfo$substrateI2 !== void 0 ? _chainInfo$substrateI2 : 0,
1687
+ tokenSymbol: (_chainInfo$substrateI4 = (_chainInfo$substrateI5 = chainInfo.substrateInfo) === null || _chainInfo$substrateI5 === void 0 ? void 0 : _chainInfo$substrateI5.symbol) !== null && _chainInfo$substrateI4 !== void 0 ? _chainInfo$substrateI4 : 'Unit',
1688
+ base58Prefix: (_chainInfo$substrateI6 = (_chainInfo$substrateI7 = chainInfo.substrateInfo) === null || _chainInfo$substrateI7 === void 0 ? void 0 : _chainInfo$substrateI7.addressPrefix) !== null && _chainInfo$substrateI6 !== void 0 ? _chainInfo$substrateI6 : 42
1689
+ };
1690
+ }
1691
+ async calculateMetadataHash(chain) {
1692
+ const metadata = await this.getMetadata(chain);
1693
+ if (!metadata || !metadata.hexV15) {
1694
+ return undefined;
1695
+ }
1696
+ const extraInfo = this.getExtraInfo(chain);
1697
+ const specVersion = parseInt(metadata.specVersion);
1698
+ const specName = metadata.specName;
1699
+ const hexV15 = metadata.hexV15;
1700
+ return calculateMetadataHash({
1701
+ ...extraInfo,
1702
+ specVersion,
1703
+ specName
1704
+ }, hexV15);
1705
+ }
1706
+ async shortenMetadata(chain, txBlob) {
1707
+ const metadata = await this.getMetadata(chain);
1708
+ if (!metadata || !metadata.hexV15) {
1709
+ return undefined;
1710
+ }
1711
+ const extraInfo = this.getExtraInfo(chain);
1712
+ const specVersion = parseInt(metadata.specVersion);
1713
+ const specName = metadata.specName;
1714
+ const hexV15 = metadata.hexV15;
1715
+ return getShortMetadata(txBlob, {
1716
+ ...extraInfo,
1717
+ specVersion,
1718
+ specName
1719
+ }, hexV15);
1720
+ }
1721
+
1722
+ /* Metadata */
1723
+
1650
1724
  getSubscanChainMap(reverse) {
1651
1725
  const result = {};
1652
1726
  const chainInfoMap = this.getChainInfoMap();
@@ -18,6 +18,11 @@ export declare enum _ChainConnectionStatus {
18
18
  UNSTABLE = "UNSTABLE",
19
19
  CONNECTING = "CONNECTING"
20
20
  }
21
+ export interface ReportRpc {
22
+ runningRpc: Record<string, string>;
23
+ unstableRpc: Record<string, string>;
24
+ dieRpc: Record<string, string>;
25
+ }
21
26
  export interface _ChainState {
22
27
  slug: string;
23
28
  active: boolean;
@@ -66,6 +71,7 @@ export interface _SubstrateApiState {
66
71
  export interface _SubstrateApi extends _SubstrateApiState, _ChainBaseApi {
67
72
  api: ApiPromise;
68
73
  isReady: Promise<_SubstrateApi>;
74
+ connect: (_callbackUpdateMetadata?: (substrateApi: _SubstrateApi) => void) => void;
69
75
  specName: string;
70
76
  specVersion: string;
71
77
  systemChain: string;
@@ -12,6 +12,6 @@ export let _ChainConnectionStatus;
12
12
  _ChainConnectionStatus["CONNECTING"] = "CONNECTING";
13
13
  })(_ChainConnectionStatus || (_ChainConnectionStatus = {}));
14
14
  export const _CUSTOM_PREFIX = 'custom-';
15
- export const _FUNGIBLE_CONTRACT_STANDARDS = [_AssetType.ERC20, _AssetType.PSP22, _AssetType.GRC20];
15
+ export const _FUNGIBLE_CONTRACT_STANDARDS = [_AssetType.ERC20, _AssetType.PSP22, _AssetType.GRC20, _AssetType.VFT];
16
16
  export const _NFT_CONTRACT_STANDARDS = [_AssetType.PSP34, _AssetType.ERC721];
17
17
  export const _SMART_CONTRACT_STANDARDS = [..._FUNGIBLE_CONTRACT_STANDARDS, ..._NFT_CONTRACT_STANDARDS];
@@ -48,6 +48,7 @@ export declare function _isChainSupportWasmNft(chainInfo: _ChainInfo): boolean;
48
48
  export declare function _isChainSupportEvmERC20(chainInfo: _ChainInfo): boolean;
49
49
  export declare function _isChainSupportWasmPSP22(chainInfo: _ChainInfo): boolean;
50
50
  export declare function _isChainSupportGRC20(chainInfo: _ChainInfo): boolean;
51
+ export declare function _isChainSupportVFT(chainInfo: _ChainInfo): boolean;
51
52
  export declare const _isSupportOrdinal: (chain: string) => boolean;
52
53
  export declare function _getNftTypesSupportedByChain(chainInfo: _ChainInfo): _AssetType[];
53
54
  export declare function _getTokenTypesSupportedByChain(chainInfo: _ChainInfo): _AssetType[];
@@ -181,6 +181,10 @@ export function _isChainSupportGRC20(chainInfo) {
181
181
  var _chainInfo$substrateI12, _chainInfo$substrateI13;
182
182
  return ((_chainInfo$substrateI12 = chainInfo.substrateInfo) === null || _chainInfo$substrateI12 === void 0 ? void 0 : (_chainInfo$substrateI13 = _chainInfo$substrateI12.supportSmartContract) === null || _chainInfo$substrateI13 === void 0 ? void 0 : _chainInfo$substrateI13.includes(_AssetType.GRC20)) || false;
183
183
  }
184
+ export function _isChainSupportVFT(chainInfo) {
185
+ var _chainInfo$substrateI14, _chainInfo$substrateI15;
186
+ return ((_chainInfo$substrateI14 = chainInfo.substrateInfo) === null || _chainInfo$substrateI14 === void 0 ? void 0 : (_chainInfo$substrateI15 = _chainInfo$substrateI14.supportSmartContract) === null || _chainInfo$substrateI15 === void 0 ? void 0 : _chainInfo$substrateI15.includes(_AssetType.VFT)) || false;
187
+ }
184
188
  export const _isSupportOrdinal = chain => {
185
189
  const chains = ['polkadot', 'astar', 'bifrost_dot', 'moonbeam'];
186
190
  return chains.includes(chain);
@@ -207,7 +211,7 @@ export function _getTokenTypesSupportedByChain(chainInfo) {
207
211
  const result = [];
208
212
  if (chainInfo.substrateInfo && chainInfo.substrateInfo.supportSmartContract) {
209
213
  chainInfo.substrateInfo.supportSmartContract.forEach(assetType => {
210
- if ([_AssetType.PSP22, _AssetType.GRC20].includes(assetType)) {
214
+ if ([_AssetType.PSP22, _AssetType.GRC20, _AssetType.VFT].includes(assetType)) {
211
215
  result.push(assetType);
212
216
  }
213
217
  });
@@ -264,7 +268,7 @@ export function _isAssetSmartContractNft(assetInfo) {
264
268
  return [_AssetType.PSP34, _AssetType.ERC721].includes(assetInfo.assetType);
265
269
  }
266
270
  export function _isTokenGearSmartContract(tokenInfo) {
267
- return [_AssetType.GRC20, _AssetType.GRC721].includes(tokenInfo.assetType);
271
+ return [_AssetType.GRC20, _AssetType.GRC721, _AssetType.VFT].includes(tokenInfo.assetType);
268
272
  }
269
273
  export function _parseAssetRefKey(originTokenSlug, destinationTokenSlug) {
270
274
  return `${originTokenSlug}___${destinationTokenSlug}`;
@@ -296,12 +300,12 @@ export function _isRelayChain(chainInfo) {
296
300
  return _isSubstrateRelayChain(chainInfo) || _isPureEvmChain(chainInfo);
297
301
  }
298
302
  export function _isSubstrateRelayChain(chainInfo) {
299
- var _chainInfo$substrateI14;
300
- return ((_chainInfo$substrateI14 = chainInfo.substrateInfo) === null || _chainInfo$substrateI14 === void 0 ? void 0 : _chainInfo$substrateI14.chainType) === _SubstrateChainType.RELAYCHAIN;
303
+ var _chainInfo$substrateI16;
304
+ return ((_chainInfo$substrateI16 = chainInfo.substrateInfo) === null || _chainInfo$substrateI16 === void 0 ? void 0 : _chainInfo$substrateI16.chainType) === _SubstrateChainType.RELAYCHAIN;
301
305
  }
302
306
  export function _isSubstrateParaChain(chainInfo) {
303
- var _chainInfo$substrateI15;
304
- return chainInfo.substrateInfo !== null && chainInfo.substrateInfo.paraId !== null && ((_chainInfo$substrateI15 = chainInfo.substrateInfo) === null || _chainInfo$substrateI15 === void 0 ? void 0 : _chainInfo$substrateI15.chainType) === _SubstrateChainType.PARACHAIN;
307
+ var _chainInfo$substrateI17;
308
+ return chainInfo.substrateInfo !== null && chainInfo.substrateInfo.paraId !== null && ((_chainInfo$substrateI17 = chainInfo.substrateInfo) === null || _chainInfo$substrateI17 === void 0 ? void 0 : _chainInfo$substrateI17.chainType) === _SubstrateChainType.PARACHAIN;
305
309
  }
306
310
  export function _getEvmAbiExplorer(chainInfo) {
307
311
  var _chainInfo$evmInfo4;
@@ -346,8 +350,8 @@ export function _getBlockExplorerFromChain(chainInfo) {
346
350
  var _chainInfo$evmInfo5;
347
351
  blockExplorer = chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$evmInfo5 = chainInfo.evmInfo) === null || _chainInfo$evmInfo5 === void 0 ? void 0 : _chainInfo$evmInfo5.blockExplorer;
348
352
  } else {
349
- var _chainInfo$substrateI16;
350
- blockExplorer = chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI16 = chainInfo.substrateInfo) === null || _chainInfo$substrateI16 === void 0 ? void 0 : _chainInfo$substrateI16.blockExplorer;
353
+ var _chainInfo$substrateI18;
354
+ blockExplorer = chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI18 = chainInfo.substrateInfo) === null || _chainInfo$substrateI18 === void 0 ? void 0 : _chainInfo$substrateI18.blockExplorer;
351
355
  }
352
356
  if (!blockExplorer) {
353
357
  return undefined;
@@ -373,8 +377,8 @@ export const _isAssetAutoEnable = chainAsset => {
373
377
  return chainAsset.metadata ? !!chainAsset.metadata.autoEnable : false;
374
378
  };
375
379
  export function _getCrowdloanUrlFromChain(chainInfo) {
376
- var _chainInfo$substrateI17;
377
- return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI17 = chainInfo.substrateInfo) === null || _chainInfo$substrateI17 === void 0 ? void 0 : _chainInfo$substrateI17.crowdloanUrl) || '';
380
+ var _chainInfo$substrateI19;
381
+ return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI19 = chainInfo.substrateInfo) === null || _chainInfo$substrateI19 === void 0 ? void 0 : _chainInfo$substrateI19.crowdloanUrl) || '';
378
382
  }
379
383
  export function _isCustomProvider(providerKey) {
380
384
  return providerKey.startsWith(_CUSTOM_PREFIX);
@@ -410,8 +414,8 @@ export function _isMantaZkAsset(chainAsset) {
410
414
  return _MANTA_ZK_CHAIN_GROUP.includes(chainAsset.originChain) && chainAsset.symbol.startsWith(_ZK_ASSET_PREFIX);
411
415
  }
412
416
  export function _getChainExistentialDeposit(chainInfo) {
413
- var _chainInfo$substrateI18;
414
- return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI18 = chainInfo.substrateInfo) === null || _chainInfo$substrateI18 === void 0 ? void 0 : _chainInfo$substrateI18.existentialDeposit) || '0';
417
+ var _chainInfo$substrateI20;
418
+ return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI20 = chainInfo.substrateInfo) === null || _chainInfo$substrateI20 === void 0 ? void 0 : _chainInfo$substrateI20.existentialDeposit) || '0';
415
419
  }
416
420
  export function randomizeProvider(providers, excludedKeys) {
417
421
  if (Object.keys(providers).length === 0) {
@@ -2,6 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
5
+ import { _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
5
6
  import { _getTokenOnChainInfo } from '@subwallet/extension-base/services/chain-service/utils';
6
7
  import { fakeAddress } from '@subwallet/extension-base/services/earning-service/constants';
7
8
  import { EarningStatus, UnstakingStatus, YieldStepType } from '@subwallet/extension-base/types';
@@ -9,6 +10,9 @@ import { BN, BN_TEN, BN_ZERO } from '@polkadot/util';
9
10
  import BaseLiquidStakingPoolHandler from "./base.js";
10
11
  const GRAPHQL_API = 'https://api.polkawallet.io/acala-liquid-staking-subql';
11
12
  const EXCHANGE_RATE_REQUEST = 'query { dailySummaries(first:30, orderBy:TIMESTAMP_DESC) {nodes { exchangeRate timestamp }}}';
13
+ function convertDerivativeToken(amount, exchangeRate, decimals) {
14
+ return amount.mul(new BN(exchangeRate)).div(BN_TEN.pow(new BN(decimals)));
15
+ }
12
16
  export default class AcalaLiquidStakingPoolHandler extends BaseLiquidStakingPoolHandler {
13
17
  altInputAsset = 'polkadot-NATIVE-DOT';
14
18
  derivativeAssets = ['acala-LOCAL-LDOT'];
@@ -22,8 +26,7 @@ export default class AcalaLiquidStakingPoolHandler extends BaseLiquidStakingPool
22
26
  defaultUnstake: true,
23
27
  fastUnstake: true,
24
28
  cancelUnstake: false,
25
- withdraw: false,
26
- // TODO: Change after verify unstake info
29
+ withdraw: true,
27
30
  claimReward: false
28
31
  };
29
32
  constructor(state, chain) {
@@ -111,30 +114,55 @@ export default class AcalaLiquidStakingPoolHandler extends BaseLiquidStakingPool
111
114
  return;
112
115
  }
113
116
  const balances = _balances;
114
- const redeemRequests = await substrateApi.api.query.homa.redeemRequests.multi(useAddresses);
115
- // This rate is multiple with decimals
116
- const exchangeRate = await this.getExchangeRate();
117
- const decimals = BN_TEN.pow(new BN(this.rateDecimals));
117
+ const [redeemRequests, exchangeRate, _currentEra] = await Promise.all([substrateApi.api.query.homa.redeemRequests.multi(useAddresses), this.getExchangeRate(), substrateApi.api.query.homa.relayChainCurrentEra()]);
118
+ const currentEra = _currentEra.toPrimitive();
118
119
  for (let i = 0; i < balances.length; i++) {
119
120
  const balanceItem = balances[i];
120
121
  const address = useAddresses[i];
121
122
  const activeTotalBalance = balanceItem.free || BN_ZERO;
122
- let totalBalance = activeTotalBalance.mul(new BN(exchangeRate)).div(decimals);
123
+ let totalBalance = convertDerivativeToken(activeTotalBalance, exchangeRate, this.rateDecimals);
123
124
  let unlockingBalance = BN_ZERO;
124
125
  const unstakings = [];
126
+
127
+ // Handle redeem request
125
128
  const redeemRequest = redeemRequests[i].toPrimitive();
126
129
  if (redeemRequest) {
127
- // If withdrawable = false, redeem request is claimed
128
- const [redeemAmount, withdrawable] = redeemRequest;
129
-
130
- // Redeem amount in derivative token
131
- const amount = new BN(redeemAmount).mul(new BN(exchangeRate)).div(decimals);
132
- totalBalance = totalBalance.add(amount);
133
- unlockingBalance = unlockingBalance.add(amount);
130
+ const [derivativeRedeemAmount, _] = redeemRequest;
131
+ const redeemAmount = convertDerivativeToken(new BN(derivativeRedeemAmount), exchangeRate, this.rateDecimals);
132
+ totalBalance = totalBalance.add(redeemAmount);
133
+ unlockingBalance = unlockingBalance.add(redeemAmount);
134
134
  unstakings.push({
135
135
  chain: this.chain,
136
- status: withdrawable ? UnstakingStatus.CLAIMABLE : UnstakingStatus.UNLOCKING,
137
- claimable: amount.toString()
136
+ status: UnstakingStatus.UNLOCKING,
137
+ claimable: redeemAmount.toString(),
138
+ waitingTime: 28 * _STAKING_ERA_LENGTH_MAP.polkadot // up to 29 day (in case non-fast-match
139
+ });
140
+ }
141
+
142
+ // Handle unbondings
143
+ const unbondings = await substrateApi.api.query.homa.unbondings.entries(address);
144
+ if (unbondings.length > 0) {
145
+ unbondings.forEach(([unbondingInfo, unbondingValue]) => {
146
+ // @ts-ignore
147
+ const _targetEra = unbondingInfo.toHuman()[1];
148
+ const targetEra = parseInt(_targetEra.replaceAll(',', ''));
149
+ const amount = new BN(unbondingValue.toPrimitive());
150
+ totalBalance = totalBalance.add(amount);
151
+ unlockingBalance = unlockingBalance.add(amount);
152
+ if (targetEra > currentEra) {
153
+ unstakings.push({
154
+ chain: this.chain,
155
+ status: UnstakingStatus.UNLOCKING,
156
+ claimable: amount.toString(),
157
+ waitingTime: (targetEra - currentEra) * _STAKING_ERA_LENGTH_MAP.polkadot // Todo: Handle exact timestamp?
158
+ });
159
+ } else {
160
+ unstakings.push({
161
+ chain: this.chain,
162
+ status: UnstakingStatus.CLAIMABLE,
163
+ claimable: amount.toString()
164
+ });
165
+ }
138
166
  });
139
167
  }
140
168
  const result = {
@@ -225,7 +253,8 @@ export default class AcalaLiquidStakingPoolHandler extends BaseLiquidStakingPool
225
253
  }
226
254
  async handleYieldUnstake(amount, address, selectedTarget) {
227
255
  const chainApi = await this.substrateApi.isReady;
228
- const extrinsic = chainApi.api.tx.homa.requestRedeem(amount, false);
256
+ const extrinsic = chainApi.api.tx.homa.requestRedeem(amount, true); // set true to allow fast match
257
+
229
258
  return [ExtrinsicType.UNSTAKE_LDOT, extrinsic];
230
259
  }
231
260
  async handleYieldWithdraw(address, unstakingInfo) {
@@ -137,6 +137,9 @@ export default class EarningService {
137
137
  if (event.type === 'account.remove') {
138
138
  removedAddresses.push(event.data[0]);
139
139
  }
140
+ if (event.type === 'account.add') {
141
+ delayReload = true;
142
+ }
140
143
  if (event.type === 'chain.updateState') {
141
144
  const chainState = this.state.getChainStateByKey(event.data[0]);
142
145
  if (chainState && !_isChainEnabled(chainState)) {
@@ -2,10 +2,26 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import BaseMigrationJob from '@subwallet/extension-base/services/migration-service/Base';
5
+ import { cacheMetadata, waitTimeout } from '@subwallet/extension-base/utils';
5
6
  export default class ClearMetadataDatabase extends BaseMigrationJob {
6
7
  async run() {
7
8
  // Clear all old metadata data
8
9
  await this.state.dbService.stores.metadata.clear();
10
+ const activeChains = this.state.chainService.getActiveChains();
11
+ const chainInfoMap = this.state.chainService.getChainInfoMap();
12
+ const reloadChains = activeChains.filter(chain => {
13
+ var _chainInfoMap$chain$s;
14
+ return !!((_chainInfoMap$chain$s = chainInfoMap[chain].substrateInfo) !== null && _chainInfoMap$chain$s !== void 0 && _chainInfoMap$chain$s.genesisHash);
15
+ });
16
+ for (const chain of reloadChains) {
17
+ const substrateApi = this.state.chainService.getSubstrateApi(chain);
18
+ const callback = substrateApi => {
19
+ cacheMetadata(chain, substrateApi, this.state.chainService);
20
+ };
21
+ Promise.race([substrateApi.isReady, waitTimeout(2000)]).finally(() => {
22
+ substrateApi === null || substrateApi === void 0 ? void 0 : substrateApi.connect(callback);
23
+ });
24
+ }
9
25
  return Promise.resolve();
10
26
  }
11
27
  }
@@ -1,14 +1,11 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import AutoEnableSomeTokens from '@subwallet/extension-base/services/migration-service/scripts/databases/AutoEnableSomeTokens';
5
- import ReloadMetadata from '@subwallet/extension-base/services/migration-service/scripts/databases/ReloadMetadata';
6
- import DeleteEarningData from '@subwallet/extension-base/services/migration-service/scripts/DeleteEarningData';
7
- import MigrateRemoveGenesisHash from '@subwallet/extension-base/services/migration-service/scripts/MigrateRemoveGenesisHash';
8
- import MigrateTransactionHistoryBySymbol from '@subwallet/extension-base/services/migration-service/scripts/MigrateTransactionHistoryBySymbol';
4
+ import AutoEnableSomeTokens from "./databases/AutoEnableSomeTokens.js";
9
5
  import ClearMetadataDatabase from "./databases/ClearMetadataDatabase.js";
10
6
  import MigrateAssetSetting from "./databases/MigrateAssetSetting.js";
11
7
  import MigrateEarningVersion from "./databases/MigrateEarningVersion.js";
8
+ import ReloadMetadata from "./databases/ReloadMetadata.js";
12
9
  import MigrateEthProvider from "./providers/MigrateEthProvider.js";
13
10
  import MigratePioneerProvider from "./providers/MigratePioneerProvider.js";
14
11
  import MigrateProvidersV1M1P24 from "./providers/MigrateProvidersV1M1P24.js";
@@ -16,6 +13,7 @@ import MigratePolygonUSDCProvider from "./tokens/MigratePolygonUSDCProvider.js";
16
13
  import AutoEnableChainsTokens from "./AutoEnableChainsTokens.js";
17
14
  import DeleteChain from "./DeleteChain.js";
18
15
  import DeleteChainStaking from "./DeleteChainStaking.js";
16
+ import DeleteEarningData from "./DeleteEarningData.js";
19
17
  import EnableVaraChain from "./EnableVaraChain.js";
20
18
  import MigrateAuthUrls from "./MigrateAuthUrls.js";
21
19
  import MigrateAutoLock from "./MigrateAutoLock.js";
@@ -24,9 +22,11 @@ import MigrateImportedToken from "./MigrateImportedToken.js";
24
22
  import MigrateLedgerAccount from "./MigrateLedgerAccount.js";
25
23
  import MigrateLedgerAccountV2 from "./MigrateLedgerAccountV2.js";
26
24
  import MigrateNetworkSettings from "./MigrateNetworkSettings.js";
25
+ import MigrateRemoveGenesisHash from "./MigrateRemoveGenesisHash.js";
27
26
  import MigrateSettings from "./MigrateSettings.js";
28
27
  import MigrateTokenDecimals from "./MigrateTokenDecimals.js";
29
28
  import MigrateTransactionHistory from "./MigrateTransactionHistory.js";
29
+ import MigrateTransactionHistoryBySymbol from "./MigrateTransactionHistoryBySymbol.js";
30
30
  import MigrateWalletReference from "./MigrateWalletReference.js";
31
31
  export const EVERYTIME = '__everytime__';
32
32
  export default {
@@ -56,8 +56,8 @@ export default {
56
56
  '1.1.69-03': MigrateAssetSetting,
57
57
  '1.1.69-02': MigrateTransactionHistoryBySymbol,
58
58
  '1.2.69-01': MigrateRemoveGenesisHash,
59
- '1.2.1-01': ClearMetadataDatabase,
60
- '1.2.13-01': ReloadMetadata
59
+ '1.2.13-01': ReloadMetadata,
60
+ '1.2.14-01': ClearMetadataDatabase
61
61
  // [`${EVERYTIME}-1.1.42-02`]: MigrateTransactionHistoryBySymbol
62
62
  // [`${EVERYTIME}-1`]: AutoEnableChainsTokens
63
63
  };
@@ -2,12 +2,22 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { staticData, StaticKey } from '@subwallet/extension-base/utils/staticData';
5
+ import { isArray } from '@polkadot/util';
5
6
  const DEFAULT_CURRENCY = 'USD';
6
7
  let useBackupApi = false;
7
8
  export const getExchangeRateMap = async () => {
9
+ let response;
8
10
  try {
9
- const response = await fetch('https://api-cache.subwallet.app/exchange-rate');
10
- const responseDataExchangeRate = (await response.json()) || {};
11
+ var _response, _response2;
12
+ try {
13
+ response = await fetch('https://api-cache.subwallet.app/exchange-rate');
14
+ } catch (e) {}
15
+ if (((_response = response) === null || _response === void 0 ? void 0 : _response.status) !== 200) {
16
+ try {
17
+ response = await fetch('https://static-cache.subwallet.app/exchange-rate/data.json');
18
+ } catch (e) {}
19
+ }
20
+ const responseDataExchangeRate = (await ((_response2 = response) === null || _response2 === void 0 ? void 0 : _response2.json())) || {};
11
21
  const exchangeRateMap = Object.keys(responseDataExchangeRate.conversion_rates).reduce((map, exchangeKey) => {
12
22
  if (!staticData[StaticKey.CURRENCY_SYMBOL][exchangeKey]) {
13
23
  return map;
@@ -20,42 +30,54 @@ export const getExchangeRateMap = async () => {
20
30
  }, {});
21
31
  return exchangeRateMap;
22
32
  } catch (e) {
23
- console.warn('Failed to get exchange rate');
24
33
  return {};
25
34
  }
26
35
  };
27
36
  export const getPriceMap = async (priceIds, currency = 'USD') => {
28
- var _rs, _rs2;
29
37
  const idStr = Array.from(priceIds).join(',');
30
- let rs;
31
- if (!useBackupApi) {
32
- try {
33
- rs = await fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=${currency.toLowerCase()}&per_page=250&ids=${idStr}`);
34
- } catch (err) {
38
+ let response;
39
+ try {
40
+ var _response3, _response5;
41
+ if (!useBackupApi) {
42
+ try {
43
+ response = await fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=${currency.toLowerCase()}&per_page=250&ids=${idStr}`);
44
+ } catch (err) {
45
+ useBackupApi = true;
46
+ }
47
+ }
48
+ if (useBackupApi || ((_response3 = response) === null || _response3 === void 0 ? void 0 : _response3.status) !== 200) {
49
+ var _response4;
35
50
  useBackupApi = true;
51
+ try {
52
+ response = await fetch(`https://api-cache.subwallet.app/api/price/get?ids=${idStr}`);
53
+ } catch (e) {}
54
+ if (((_response4 = response) === null || _response4 === void 0 ? void 0 : _response4.status) !== 200) {
55
+ try {
56
+ response = await fetch('https://static-cache.subwallet.app/price/data.json');
57
+ } catch (e) {}
58
+ }
36
59
  }
60
+ const generateDataPriceRaw = (await ((_response5 = response) === null || _response5 === void 0 ? void 0 : _response5.json())) || [];
61
+ const responseDataPrice = isArray(generateDataPriceRaw) ? generateDataPriceRaw : Object.entries(generateDataPriceRaw).map(([id, value]) => ({
62
+ ...value,
63
+ id
64
+ }));
65
+ const currencyData = staticData[StaticKey.CURRENCY_SYMBOL][currency || DEFAULT_CURRENCY];
66
+ const priceMap = {};
67
+ const price24hMap = {};
68
+ responseDataPrice.forEach(val => {
69
+ const currentPrice = val.current_price || 0;
70
+ const price24h = currentPrice - (val.price_change_24h || 0);
71
+ priceMap[val.id] = currentPrice;
72
+ price24hMap[val.id] = price24h;
73
+ });
74
+ return {
75
+ currency,
76
+ currencyData,
77
+ priceMap,
78
+ price24hMap
79
+ };
80
+ } catch (e) {
81
+ return {};
37
82
  }
38
- if (useBackupApi || ((_rs = rs) === null || _rs === void 0 ? void 0 : _rs.status) !== 200) {
39
- useBackupApi = true;
40
- rs = await fetch(`https://chain-data.subwallet.app/api/price/get?ids=${idStr}`);
41
- }
42
- if (((_rs2 = rs) === null || _rs2 === void 0 ? void 0 : _rs2.status) !== 200) {
43
- console.warn('Failed to get token price');
44
- }
45
- const responseDataPrice = (await rs.json()) || [];
46
- const currencyData = staticData[StaticKey.CURRENCY_SYMBOL][currency || DEFAULT_CURRENCY];
47
- const priceMap = {};
48
- const price24hMap = {};
49
- responseDataPrice.forEach(val => {
50
- const currentPrice = val.current_price || 0;
51
- const price24h = currentPrice - (val.price_change_24h || 0);
52
- priceMap[val.id] = currentPrice;
53
- price24hMap[val.id] = price24h;
54
- });
55
- return {
56
- currency,
57
- currencyData,
58
- priceMap,
59
- price24hMap
60
- };
61
83
  };
@@ -6,9 +6,10 @@ import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
6
6
  import { getExchangeRateMap, getPriceMap } from '@subwallet/extension-base/services/price-service/coingecko';
7
7
  import { SWStorage } from '@subwallet/extension-base/storage';
8
8
  import { CurrentCurrencyStore } from '@subwallet/extension-base/stores';
9
+ import { wait } from '@subwallet/extension-base/utils';
9
10
  import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
10
11
  import { staticData, StaticKey } from '@subwallet/extension-base/utils/staticData';
11
- import { BehaviorSubject } from 'rxjs';
12
+ import { BehaviorSubject, combineLatest } from 'rxjs';
12
13
  const DEFAULT_CURRENCY = 'USD';
13
14
  const DEFAULT_PRICE_SUBJECT = {
14
15
  currency: DEFAULT_CURRENCY,
@@ -22,6 +23,9 @@ const DEFAULT_PRICE_SUBJECT = {
22
23
  price24hMap: {},
23
24
  exchangeRateMap: {}
24
25
  };
26
+ const checkFetchSuccess = (obj1, obj2) => {
27
+ return Object.keys(obj1).length > 0 && Object.keys(obj2).length > 0;
28
+ };
25
29
  export class PriceService {
26
30
  priceIds = new Set();
27
31
  currency = new CurrentCurrencyStore();
@@ -43,10 +47,15 @@ export class PriceService {
43
47
  this.init().then(() => this.getCurrentCurrency(updateCurrency)).catch(console.error);
44
48
  }
45
49
  async getTokenPrice(priceIds, currency, resolve, reject) {
46
- await Promise.all([getExchangeRateMap(), getPriceMap(priceIds, currency)]).then(([exchangeRateMap, priceMap]) => {
47
- this.rawExchangeRateMap.next(exchangeRateMap);
48
- this.rawPriceSubject.next(priceMap);
49
- });
50
+ const getPriceData = async () => {
51
+ await Promise.all([getExchangeRateMap(), getPriceMap(priceIds, currency)]).then(([exchangeRateMap, priceMap]) => {
52
+ if (checkFetchSuccess(priceMap, exchangeRateMap)) {
53
+ this.rawExchangeRateMap.next(exchangeRateMap);
54
+ this.rawPriceSubject.next(priceMap);
55
+ }
56
+ });
57
+ };
58
+ await Promise.race([getPriceData(), wait(10 * 1000)]);
50
59
  }
51
60
  getCurrentCurrencySubject() {
52
61
  return this.currency.getSubject();
@@ -82,17 +91,27 @@ export class PriceService {
82
91
  })();
83
92
  }
84
93
  async calculatePriceMap(currency) {
85
- const {
94
+ let {
86
95
  price24hMap,
87
96
  priceMap
88
97
  } = this.rawPriceSubject.value;
89
- const exchangeRateData = this.rawExchangeRateMap.value;
98
+ let exchangeRateData = this.rawExchangeRateMap.value;
99
+ const priceStored = await this.dbService.getPriceStore(currency);
90
100
  const currencyKey = currency || DEFAULT_CURRENCY;
91
101
  if (Object.keys(this.rawPriceSubject.value).length === 0) {
92
- return;
102
+ if (priceStored !== null && priceStored !== void 0 && priceStored.exchangeRateMap) {
103
+ exchangeRateData = priceStored.exchangeRateMap;
104
+ }
93
105
  }
94
106
  if (Object.keys(exchangeRateData).length === 0) {
95
- return;
107
+ if (priceStored !== null && priceStored !== void 0 && priceStored.price24hMap) {
108
+ price24hMap = {
109
+ ...priceStored.price24hMap
110
+ };
111
+ priceMap = {
112
+ ...priceStored.priceMap
113
+ };
114
+ }
96
115
  }
97
116
  const finalPriceMap = {
98
117
  priceMap: {
@@ -158,8 +177,7 @@ export class PriceService {
158
177
  this.refreshPriceMapByAction();
159
178
  }
160
179
  };
161
- this.getCurrentCurrencySubject().subscribe(currency => {
162
- console.log('Currency changed', currency);
180
+ combineLatest([this.getCurrentCurrencySubject(), this.rawPriceSubject, this.rawExchangeRateMap]).subscribe(([currency]) => {
163
181
  this.calculatePriceMap(currency).then(data => {
164
182
  if (data) {
165
183
  this.priceSubject.next(data);