@subwallet/extension-base 1.3.32-0 → 1.3.33-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.
@@ -142,6 +142,19 @@ export interface PriceJson {
142
142
  exchangeRateMap: Record<string, ExchangeRateJSON>;
143
143
  priceMap: Record<string, number>;
144
144
  price24hMap: Record<string, number>;
145
+ lastUpdatedMap: Record<string, Date>;
146
+ }
147
+ export interface HistoryTokenPriceJSON {
148
+ history: PriceChartPoint[];
149
+ }
150
+ export interface ResponseSubscribeCurrentTokenPrice {
151
+ id: string;
152
+ price: CurrentTokenPrice;
153
+ }
154
+ export interface CurrentTokenPrice {
155
+ value: number;
156
+ value24h: number;
157
+ time: number;
145
158
  }
146
159
  export interface ExchangeRateJSON {
147
160
  exchange: number;
@@ -301,6 +314,11 @@ export interface OptionInputAddress {
301
314
  }
302
315
  export declare type LanguageType = 'en' | 'zh' | 'fr' | 'tr' | 'pl' | 'th' | 'ur' | 'vi' | 'ja' | 'ru';
303
316
  export declare type CurrencyType = 'USD' | 'BRL' | 'CNY' | 'EUR' | 'GBP' | 'HKD' | 'JPY' | 'RUB' | 'VND';
317
+ export declare type PriceChartTimeframe = '1D' | '1W' | '1M' | '3M' | 'YTD' | '1Y' | 'ALL';
318
+ export interface PriceChartPoint {
319
+ time: number;
320
+ value: number;
321
+ }
304
322
  export declare type LanguageOptionType = {
305
323
  text: string;
306
324
  value: LanguageType;
@@ -351,6 +369,10 @@ export declare type RequestChangeLanguage = {
351
369
  export declare type RequestChangePriceCurrency = {
352
370
  currency: CurrencyType;
353
371
  };
372
+ export declare type RequestGetHistoryTokenPriceData = {
373
+ priceId: string;
374
+ timeframe: PriceChartTimeframe;
375
+ };
354
376
  export declare type RequestChangeShowBalance = {
355
377
  enable: boolean;
356
378
  };
@@ -1651,6 +1673,8 @@ export interface KoniRequestSignatures {
1651
1673
  'pri(stakingReward.getSubscription)': [RequestSubscribeStakingReward, StakingRewardJson, StakingRewardJson];
1652
1674
  'pri(price.getPrice)': [RequestPrice, PriceJson];
1653
1675
  'pri(price.getSubscription)': [RequestSubscribePrice, PriceJson, PriceJson];
1676
+ 'pri(price.getHistory)': [RequestGetHistoryTokenPriceData, HistoryTokenPriceJSON];
1677
+ 'pri(price.subscribeCurrentTokenPrice)': [string, ResponseSubscribeCurrentTokenPrice, CurrentTokenPrice];
1654
1678
  'pri(balance.getBalance)': [RequestBalance, BalanceJson];
1655
1679
  'pri(balance.getSubscription)': [RequestSubscribeBalance, BalanceJson, BalanceJson];
1656
1680
  'pri(crowdloan.getCrowdloan)': [RequestCrowdloan, CrowdloanJson];
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.isProductionMode = exports.BACKEND_API_URL = void 0;
6
+ exports.isProductionMode = exports.BACKEND_PRICE_HISTORY_URL = exports.BACKEND_API_URL = void 0;
7
7
  // Copyright 2019-2022 @subwallet/extension-base authors & contributors
8
8
  // SPDX-License-Identifier: Apache-2.0
9
9
 
@@ -12,4 +12,6 @@ const branchName = process.env.BRANCH_NAME || 'subwallet-dev';
12
12
  const isProductionMode = PRODUCTION_BRANCHES.indexOf(branchName) > -1;
13
13
  exports.isProductionMode = isProductionMode;
14
14
  const BACKEND_API_URL = process.env.SUBWALLET_API || (isProductionMode ? 'https://sw-services.subwallet.app/api' : 'https://be-dev.subwallet.app/api');
15
- exports.BACKEND_API_URL = BACKEND_API_URL;
15
+ exports.BACKEND_API_URL = BACKEND_API_URL;
16
+ const BACKEND_PRICE_HISTORY_URL = process.env.SUBWALLET_PRICE_HISTORY_API || (isProductionMode ? 'https://price-history.subwallet.app/api' : 'https://price-history-dev.subwallet.app/api');
17
+ exports.BACKEND_PRICE_HISTORY_URL = BACKEND_PRICE_HISTORY_URL;
@@ -918,10 +918,32 @@ class KoniExtension {
918
918
  async getPrice() {
919
919
  return this.#koniState.priceService.getPrice();
920
920
  }
921
- async setPriceCurrency(_ref29) {
921
+ async getHistoryTokenPrice(_ref29) {
922
922
  let {
923
- currency
923
+ priceId,
924
+ timeframe
924
925
  } = _ref29;
926
+ return this.#koniState.priceService.getHistoryTokenPriceData(priceId, timeframe);
927
+ }
928
+ subscribeCurrentTokenPrice(priceId, id, port) {
929
+ const cb = (0, _subscriptions.createSubscription)(id, port);
930
+ const {
931
+ currentPrice,
932
+ unsubscribe
933
+ } = this.#koniState.priceService.subscribeCurrentTokenPrice(priceId, cb);
934
+ this.createUnsubscriptionHandle(id, unsubscribe);
935
+ port.onDisconnect.addListener(() => {
936
+ this.cancelSubscription(id);
937
+ });
938
+ return {
939
+ id,
940
+ price: currentPrice
941
+ };
942
+ }
943
+ async setPriceCurrency(_ref30) {
944
+ let {
945
+ currency
946
+ } = _ref30;
925
947
  return await this.#koniState.priceService.setPriceCurrency(currency);
926
948
  }
927
949
  subscribePrice(id, port) {
@@ -1129,11 +1151,11 @@ class KoniExtension {
1129
1151
  // Re-filter
1130
1152
  return historySubject.getValue().filter(item => addresses.some(address => (0, _utils7.isSameAddress)(item.address, address)));
1131
1153
  }
1132
- subscribeHistoryByChainAndAddress(_ref30, id, port) {
1154
+ subscribeHistoryByChainAndAddress(_ref31, id, port) {
1133
1155
  let {
1134
1156
  address,
1135
1157
  chain
1136
- } = _ref30;
1158
+ } = _ref31;
1137
1159
  const cb = (0, _subscriptions.createSubscription)(id, port);
1138
1160
  const subscribeHistoriesResponse = this.#koniState.historyService.subscribeHistories(chain, address, cb);
1139
1161
  this.createUnsubscriptionHandle(id, subscribeHistoriesResponse.unsubscribe);
@@ -1700,28 +1722,28 @@ class KoniExtension {
1700
1722
  disableChain(networkKey) {
1701
1723
  return this.#koniState.disableChain(networkKey);
1702
1724
  }
1703
- async enableChain(_ref31) {
1725
+ async enableChain(_ref32) {
1704
1726
  let {
1705
1727
  chainSlug,
1706
1728
  enableTokens
1707
- } = _ref31;
1729
+ } = _ref32;
1708
1730
  return await this.#koniState.enableChain(chainSlug, enableTokens);
1709
1731
  }
1710
- async enableChainWithPriorityAssets(_ref32) {
1732
+ async enableChainWithPriorityAssets(_ref33) {
1711
1733
  let {
1712
1734
  chainSlug,
1713
1735
  enableTokens
1714
- } = _ref32;
1736
+ } = _ref33;
1715
1737
  return await this.#koniState.enableChainWithPriorityAssets(chainSlug, enableTokens);
1716
1738
  }
1717
1739
  async reconnectChain(chainSlug) {
1718
1740
  return this.#koniState.chainService.reconnectChain(chainSlug);
1719
1741
  }
1720
- async validateNetwork(_ref33) {
1742
+ async validateNetwork(_ref34) {
1721
1743
  let {
1722
1744
  existedChainSlug,
1723
1745
  provider
1724
- } = _ref33;
1746
+ } = _ref34;
1725
1747
  return await this.#koniState.validateCustomChain(provider, existedChainSlug);
1726
1748
  }
1727
1749
  resetDefaultNetwork() {
@@ -1793,13 +1815,13 @@ class KoniExtension {
1793
1815
  async validateCustomAsset(data) {
1794
1816
  return await this.#koniState.validateCustomAsset(data);
1795
1817
  }
1796
- async getAddressTransferableBalance(_ref34) {
1818
+ async getAddressTransferableBalance(_ref35) {
1797
1819
  let {
1798
1820
  address,
1799
1821
  extrinsicType,
1800
1822
  networkKey,
1801
1823
  token
1802
- } = _ref34;
1824
+ } = _ref35;
1803
1825
  if (token && _constants2._MANTA_ZK_CHAIN_GROUP.includes(networkKey)) {
1804
1826
  const tokenInfo = this.#koniState.chainService.getAssetBySlug(token);
1805
1827
  if (tokenInfo.symbol.startsWith(_constants2._ZK_ASSET_PREFIX)) {
@@ -1808,13 +1830,13 @@ class KoniExtension {
1808
1830
  }
1809
1831
  return await this.#koniState.balanceService.getTransferableBalance(address, networkKey, token, extrinsicType);
1810
1832
  }
1811
- async getAddressTotalBalance(_ref35) {
1833
+ async getAddressTotalBalance(_ref36) {
1812
1834
  let {
1813
1835
  address,
1814
1836
  extrinsicType,
1815
1837
  networkKey,
1816
1838
  token
1817
- } = _ref35;
1839
+ } = _ref36;
1818
1840
  return await this.#koniState.balanceService.getTotalBalance(address, networkKey, token, extrinsicType);
1819
1841
  }
1820
1842
  async subscribeMaxTransferable(request, id, port) {
@@ -1866,11 +1888,11 @@ class KoniExtension {
1866
1888
  freeBalance: freeBalanceSubject,
1867
1889
  fee: feeSubject
1868
1890
  }).subscribe({
1869
- next: _ref36 => {
1891
+ next: _ref37 => {
1870
1892
  let {
1871
1893
  fee,
1872
1894
  freeBalance
1873
- } = _ref36;
1895
+ } = _ref37;
1874
1896
  (0, _utils7.calculateMaxTransferable)(id, _request, freeBalance, fee).then(cb).catch(console.error);
1875
1897
  }
1876
1898
  });
@@ -1904,13 +1926,13 @@ class KoniExtension {
1904
1926
  });
1905
1927
  return (0, _utils7.calculateMaxTransferable)(id, _request, freeBalance, fee);
1906
1928
  }
1907
- async subscribeAddressTransferableBalance(_ref37, id, port) {
1929
+ async subscribeAddressTransferableBalance(_ref38, id, port) {
1908
1930
  let {
1909
1931
  address,
1910
1932
  extrinsicType,
1911
1933
  networkKey,
1912
1934
  token
1913
- } = _ref37;
1935
+ } = _ref38;
1914
1936
  const cb = (0, _subscriptions.createSubscription)(id, port);
1915
1937
  const convertData = data => {
1916
1938
  return {
@@ -1961,11 +1983,11 @@ class KoniExtension {
1961
1983
  isSendingSelf
1962
1984
  };
1963
1985
  }
1964
- async enableChains(_ref38) {
1986
+ async enableChains(_ref39) {
1965
1987
  let {
1966
1988
  chainSlugs,
1967
1989
  enableTokens
1968
- } = _ref38;
1990
+ } = _ref39;
1969
1991
  try {
1970
1992
  await Promise.all(chainSlugs.map(chainSlug => this.enableChain({
1971
1993
  chainSlug,
@@ -2098,30 +2120,30 @@ class KoniExtension {
2098
2120
 
2099
2121
  // Parse transaction
2100
2122
 
2101
- parseSubstrateTransaction(_ref39) {
2123
+ parseSubstrateTransaction(_ref40) {
2102
2124
  let {
2103
2125
  data,
2104
2126
  networkKey
2105
- } = _ref39;
2127
+ } = _ref40;
2106
2128
  const apiProps = this.#koniState.getSubstrateApi(networkKey);
2107
2129
  const apiPromise = apiProps.api;
2108
2130
  return (0, _parseTransaction.parseSubstrateTransaction)(data, apiPromise);
2109
2131
  }
2110
- async parseEVMRLP(_ref40) {
2132
+ async parseEVMRLP(_ref41) {
2111
2133
  let {
2112
2134
  data
2113
- } = _ref40;
2135
+ } = _ref41;
2114
2136
  return await (0, _parseTransaction2.parseEvmRlp)(data, this.#koniState.getChainInfoMap(), this.#koniState.getEvmApiMap());
2115
2137
  }
2116
2138
 
2117
2139
  // Sign
2118
2140
 
2119
- qrSignSubstrate(_ref41) {
2141
+ qrSignSubstrate(_ref42) {
2120
2142
  let {
2121
2143
  address,
2122
2144
  data,
2123
2145
  networkKey
2124
- } = _ref41;
2146
+ } = _ref42;
2125
2147
  const pair = _uiKeyring.keyring.getPair(address);
2126
2148
  (0, _util.assert)(pair, (0, _i18next.t)('Unable to find account'));
2127
2149
  if (pair.isLocked) {
@@ -2138,13 +2160,13 @@ class KoniExtension {
2138
2160
  signature: signed
2139
2161
  };
2140
2162
  }
2141
- async qrSignEVM(_ref42) {
2163
+ async qrSignEVM(_ref43) {
2142
2164
  let {
2143
2165
  address,
2144
2166
  chainId,
2145
2167
  message,
2146
2168
  type
2147
- } = _ref42;
2169
+ } = _ref43;
2148
2170
  let signed;
2149
2171
  const network = this.getNetworkJsonByChainId(chainId);
2150
2172
  if (!network) {
@@ -2228,11 +2250,11 @@ class KoniExtension {
2228
2250
  });
2229
2251
  return this.#koniState.getNominatorMetadata();
2230
2252
  }
2231
- async getBondingOptions(_ref43) {
2253
+ async getBondingOptions(_ref44) {
2232
2254
  let {
2233
2255
  chain,
2234
2256
  type
2235
- } = _ref43;
2257
+ } = _ref44;
2236
2258
  const apiProps = this.#koniState.getSubstrateApi(chain);
2237
2259
  const chainInfo = this.#koniState.getChainInfo(chain);
2238
2260
  const chainStakingMetadata = await this.#koniState.getStakingMetadataByChain(chain, type);
@@ -2422,12 +2444,12 @@ class KoniExtension {
2422
2444
  }
2423
2445
 
2424
2446
  // EVM Transaction
2425
- async parseContractInput(_ref44) {
2447
+ async parseContractInput(_ref45) {
2426
2448
  let {
2427
2449
  chainId,
2428
2450
  contract,
2429
2451
  data
2430
- } = _ref44;
2452
+ } = _ref45;
2431
2453
  const network = this.getNetworkJsonByChainId(chainId);
2432
2454
  return await (0, _parseTransaction2.parseContractInput)(data, contract, network);
2433
2455
  }
@@ -2527,10 +2549,10 @@ class KoniExtension {
2527
2549
 
2528
2550
  // Unlock wallet
2529
2551
 
2530
- keyringUnlock(_ref45) {
2552
+ keyringUnlock(_ref46) {
2531
2553
  let {
2532
2554
  password
2533
- } = _ref45;
2555
+ } = _ref46;
2534
2556
  try {
2535
2557
  _uiKeyring.keyring.unlockKeyring(password);
2536
2558
  // this.#koniState.initMantaPay(password)
@@ -2561,11 +2583,11 @@ class KoniExtension {
2561
2583
 
2562
2584
  // Export mnemonic
2563
2585
 
2564
- keyringExportMnemonic(_ref46) {
2586
+ keyringExportMnemonic(_ref47) {
2565
2587
  let {
2566
2588
  address,
2567
2589
  password
2568
- } = _ref46;
2590
+ } = _ref47;
2569
2591
  const pair = _uiKeyring.keyring.getPair(address);
2570
2592
  const result = pair.exportMnemonic(password);
2571
2593
  return {
@@ -2575,10 +2597,10 @@ class KoniExtension {
2575
2597
 
2576
2598
  // Reset wallet
2577
2599
 
2578
- async resetWallet(_ref47) {
2600
+ async resetWallet(_ref48) {
2579
2601
  let {
2580
2602
  resetAll
2581
- } = _ref47;
2603
+ } = _ref48;
2582
2604
  try {
2583
2605
  await this.#koniState.resetWallet(resetAll);
2584
2606
  return {
@@ -2594,10 +2616,10 @@ class KoniExtension {
2594
2616
  }
2595
2617
 
2596
2618
  // Signing substrate request
2597
- async signingApprovePasswordV2(_ref48) {
2619
+ async signingApprovePasswordV2(_ref49) {
2598
2620
  let {
2599
2621
  id
2600
- } = _ref48;
2622
+ } = _ref49;
2601
2623
  const queued = this.#koniState.getSignRequest(id);
2602
2624
  (0, _util.assert)(queued, (0, _i18next.t)('Unable to proceed. Please try again'));
2603
2625
  const {
@@ -2755,10 +2777,10 @@ class KoniExtension {
2755
2777
  getSupportedSmartContractTypes() {
2756
2778
  return this.#koniState.getSupportedSmartContractTypes();
2757
2779
  }
2758
- getTransaction(_ref49) {
2780
+ getTransaction(_ref50) {
2759
2781
  let {
2760
2782
  id
2761
- } = _ref49;
2783
+ } = _ref50;
2762
2784
  const {
2763
2785
  transaction,
2764
2786
  ...transactionResult
@@ -2768,8 +2790,8 @@ class KoniExtension {
2768
2790
  async subscribeTransactions(id, port) {
2769
2791
  const cb = (0, _subscriptions.createSubscription)(id, port);
2770
2792
  function convertRs(rs, processMap) {
2771
- return Object.fromEntries(Object.entries(rs).map(_ref50 => {
2772
- let [key, value] = _ref50;
2793
+ return Object.fromEntries(Object.entries(rs).map(_ref51 => {
2794
+ let [key, value] = _ref51;
2773
2795
  const {
2774
2796
  additionalValidator,
2775
2797
  eventsHandler,
@@ -2793,11 +2815,11 @@ class KoniExtension {
2793
2815
  const subscription = (0, _rxjs.combineLatest)({
2794
2816
  transactions: transactionsObservable,
2795
2817
  processMap: processTransactionObservable
2796
- }).subscribe(_ref51 => {
2818
+ }).subscribe(_ref52 => {
2797
2819
  let {
2798
2820
  processMap,
2799
2821
  transactions
2800
- } = _ref51;
2822
+ } = _ref52;
2801
2823
  cb(convertRs(transactions, processMap));
2802
2824
  });
2803
2825
  port.onDisconnect.addListener(() => {
@@ -2818,10 +2840,10 @@ class KoniExtension {
2818
2840
  });
2819
2841
  return notificationSubject.value;
2820
2842
  }
2821
- async reloadCron(_ref52) {
2843
+ async reloadCron(_ref53) {
2822
2844
  let {
2823
2845
  data
2824
- } = _ref52;
2846
+ } = _ref53;
2825
2847
  if (data === 'nft') {
2826
2848
  return await this.#koniState.reloadNft();
2827
2849
  } else if (data === 'staking') {
@@ -2864,10 +2886,10 @@ class KoniExtension {
2864
2886
  }
2865
2887
 
2866
2888
  // Phishing detect
2867
- async passPhishingPage(_ref53) {
2889
+ async passPhishingPage(_ref54) {
2868
2890
  let {
2869
2891
  url
2870
- } = _ref53;
2892
+ } = _ref54;
2871
2893
  return await this.#koniState.approvePassPhishingPage(url);
2872
2894
  }
2873
2895
 
@@ -2888,10 +2910,10 @@ class KoniExtension {
2888
2910
  /// Wallet connect
2889
2911
 
2890
2912
  // Connect
2891
- async connectWalletConnect(_ref54) {
2913
+ async connectWalletConnect(_ref55) {
2892
2914
  let {
2893
2915
  uri
2894
- } = _ref54;
2916
+ } = _ref55;
2895
2917
  await this.#koniState.walletConnectService.connect(uri);
2896
2918
  return true;
2897
2919
  }
@@ -2904,11 +2926,11 @@ class KoniExtension {
2904
2926
  });
2905
2927
  return this.#koniState.requestService.allConnectWCRequests;
2906
2928
  }
2907
- async approveWalletConnectSession(_ref55) {
2929
+ async approveWalletConnectSession(_ref56) {
2908
2930
  let {
2909
2931
  accounts: selectedAccounts,
2910
2932
  id
2911
- } = _ref55;
2933
+ } = _ref56;
2912
2934
  const request = this.#koniState.requestService.getConnectWCRequest(id);
2913
2935
  if ((0, _helpers2.isProposalExpired)(request.request.params)) {
2914
2936
  throw new Error('The proposal has been expired');
@@ -2920,8 +2942,8 @@ class KoniExtension {
2920
2942
  const availableNamespaces = {};
2921
2943
  const namespaces = {};
2922
2944
  const chainInfoMap = this.#koniState.getChainInfoMap();
2923
- Object.entries(requiredNamespaces).forEach(_ref56 => {
2924
- let [key, namespace] = _ref56;
2945
+ Object.entries(requiredNamespaces).forEach(_ref57 => {
2946
+ let [key, namespace] = _ref57;
2925
2947
  if ((0, _helpers2.isSupportWalletConnectNamespace)(key)) {
2926
2948
  if (namespace.chains) {
2927
2949
  const unSupportChains = namespace.chains.filter(chain => !(0, _helpers2.isSupportWalletConnectChain)(chain, chainInfoMap));
@@ -2934,8 +2956,8 @@ class KoniExtension {
2934
2956
  throw new Error((0, _utils8.getSdkError)('UNSUPPORTED_NAMESPACE_KEY').message + ' ' + key);
2935
2957
  }
2936
2958
  });
2937
- Object.entries(optionalNamespaces).forEach(_ref57 => {
2938
- let [key, namespace] = _ref57;
2959
+ Object.entries(optionalNamespaces).forEach(_ref58 => {
2960
+ let [key, namespace] = _ref58;
2939
2961
  if ((0, _helpers2.isSupportWalletConnectNamespace)(key)) {
2940
2962
  if (namespace.chains) {
2941
2963
  const supportChains = namespace.chains.filter(chain => (0, _helpers2.isSupportWalletConnectChain)(chain, chainInfoMap)) || [];
@@ -2959,8 +2981,8 @@ class KoniExtension {
2959
2981
  }
2960
2982
  }
2961
2983
  });
2962
- Object.entries(availableNamespaces).forEach(_ref58 => {
2963
- let [key, namespace] = _ref58;
2984
+ Object.entries(availableNamespaces).forEach(_ref59 => {
2985
+ let [key, namespace] = _ref59;
2964
2986
  if (namespace.chains) {
2965
2987
  const accounts = selectedAccounts.filter(address => {
2966
2988
  const [_namespace] = address.split(':');
@@ -2984,10 +3006,10 @@ class KoniExtension {
2984
3006
  request.resolve();
2985
3007
  return true;
2986
3008
  }
2987
- async rejectWalletConnectSession(_ref59) {
3009
+ async rejectWalletConnectSession(_ref60) {
2988
3010
  let {
2989
3011
  id
2990
- } = _ref59;
3012
+ } = _ref60;
2991
3013
  const request = this.#koniState.requestService.getConnectWCRequest(id);
2992
3014
  const wcId = request.request.id;
2993
3015
  if ((0, _helpers2.isProposalExpired)(request.request.params)) {
@@ -3009,10 +3031,10 @@ class KoniExtension {
3009
3031
  });
3010
3032
  return this.#koniState.walletConnectService.sessions;
3011
3033
  }
3012
- async disconnectWalletConnectSession(_ref60) {
3034
+ async disconnectWalletConnectSession(_ref61) {
3013
3035
  let {
3014
3036
  topic
3015
- } = _ref60;
3037
+ } = _ref61;
3016
3038
  await this.#koniState.walletConnectService.disconnect(topic);
3017
3039
  return true;
3018
3040
  }
@@ -3025,18 +3047,18 @@ class KoniExtension {
3025
3047
  });
3026
3048
  return this.#koniState.requestService.allNotSupportWCRequests;
3027
3049
  }
3028
- approveWalletConnectNotSupport(_ref61) {
3050
+ approveWalletConnectNotSupport(_ref62) {
3029
3051
  let {
3030
3052
  id
3031
- } = _ref61;
3053
+ } = _ref62;
3032
3054
  const request = this.#koniState.requestService.getNotSupportWCRequest(id);
3033
3055
  request.resolve();
3034
3056
  return true;
3035
3057
  }
3036
- rejectWalletConnectNotSupport(_ref62) {
3058
+ rejectWalletConnectNotSupport(_ref63) {
3037
3059
  let {
3038
3060
  id
3039
- } = _ref62;
3061
+ } = _ref63;
3040
3062
  const request = this.#koniState.requestService.getNotSupportWCRequest(id);
3041
3063
  request.reject(new Error('USER_REJECTED'));
3042
3064
  return true;
@@ -3044,11 +3066,11 @@ class KoniExtension {
3044
3066
 
3045
3067
  /// Manta
3046
3068
 
3047
- async enableMantaPay(_ref63) {
3069
+ async enableMantaPay(_ref64) {
3048
3070
  let {
3049
3071
  address,
3050
3072
  password
3051
- } = _ref63;
3073
+ } = _ref64;
3052
3074
  // always takes the current account
3053
3075
  function timeout() {
3054
3076
  return new Promise(resolve => setTimeout(resolve, 1500));
@@ -3138,11 +3160,11 @@ class KoniExtension {
3138
3160
  async disableMantaPay(address) {
3139
3161
  return this.#koniState.disableMantaPay(address);
3140
3162
  }
3141
- async isTonBounceableAddress(_ref64) {
3163
+ async isTonBounceableAddress(_ref65) {
3142
3164
  let {
3143
3165
  address,
3144
3166
  chain
3145
- } = _ref64;
3167
+ } = _ref65;
3146
3168
  try {
3147
3169
  const tonApi = this.#koniState.getTonApi(chain);
3148
3170
  const state = await tonApi.getAccountState(address);
@@ -3188,10 +3210,10 @@ class KoniExtension {
3188
3210
 
3189
3211
  /* Metadata */
3190
3212
 
3191
- async findRawMetadata(_ref65) {
3213
+ async findRawMetadata(_ref66) {
3192
3214
  let {
3193
3215
  genesisHash
3194
- } = _ref65;
3216
+ } = _ref66;
3195
3217
  const {
3196
3218
  metadata,
3197
3219
  specVersion,
@@ -3205,20 +3227,20 @@ class KoniExtension {
3205
3227
  userExtensions
3206
3228
  };
3207
3229
  }
3208
- async calculateMetadataHash(_ref66) {
3230
+ async calculateMetadataHash(_ref67) {
3209
3231
  let {
3210
3232
  chain
3211
- } = _ref66;
3233
+ } = _ref67;
3212
3234
  const hash = await this.#koniState.calculateMetadataHash(chain);
3213
3235
  return {
3214
3236
  metadataHash: hash || ''
3215
3237
  };
3216
3238
  }
3217
- async shortenMetadata(_ref67) {
3239
+ async shortenMetadata(_ref68) {
3218
3240
  let {
3219
3241
  chain,
3220
3242
  txBlob
3221
- } = _ref67;
3243
+ } = _ref68;
3222
3244
  const shorten = await this.#koniState.shortenMetadata(chain, txBlob);
3223
3245
  return {
3224
3246
  txMetadata: shorten || ''
@@ -3571,18 +3593,18 @@ class KoniExtension {
3571
3593
 
3572
3594
  /* Campaign */
3573
3595
 
3574
- unlockDotCheckCanMint(_ref68) {
3596
+ unlockDotCheckCanMint(_ref69) {
3575
3597
  let {
3576
3598
  address,
3577
3599
  network,
3578
3600
  slug
3579
- } = _ref68;
3601
+ } = _ref69;
3580
3602
  return this.#koniState.mintCampaignService.unlockDotCampaign.canMint(address, slug, network);
3581
3603
  }
3582
- unlockDotSubscribeMintedData(id, port, _ref69) {
3604
+ unlockDotSubscribeMintedData(id, port, _ref70) {
3583
3605
  let {
3584
3606
  transactionId
3585
- } = _ref69;
3607
+ } = _ref70;
3586
3608
  const cb = (0, _subscriptions.createSubscription)(id, port);
3587
3609
  const subscription = this.#koniState.mintCampaignService.unlockDotCampaign.subscribeMintedNft(transactionId, cb);
3588
3610
  this.createUnsubscriptionHandle(id, subscription.unsubscribe);
@@ -3614,10 +3636,10 @@ class KoniExtension {
3614
3636
  });
3615
3637
  return filterBanner(await this.#koniState.campaignService.getProcessingCampaign());
3616
3638
  }
3617
- async completeCampaignBanner(_ref70) {
3639
+ async completeCampaignBanner(_ref71) {
3618
3640
  let {
3619
3641
  slug
3620
- } = _ref70;
3642
+ } = _ref71;
3621
3643
  const campaign = await this.#koniState.dbService.getCampaign(slug);
3622
3644
  if (campaign) {
3623
3645
  await this.#koniState.dbService.upsertCampaign({
@@ -4133,8 +4155,8 @@ class KoniExtension {
4133
4155
  resolve();
4134
4156
  }
4135
4157
  };
4136
- this.#koniState.balanceService.subscribeTransferableBalance(address, waitXcmData.chain, waitXcmData.token, waitXcmData.nextTxType, onRs).then(_ref71 => {
4137
- let [_unsub, rs] = _ref71;
4158
+ this.#koniState.balanceService.subscribeTransferableBalance(address, waitXcmData.chain, waitXcmData.token, waitXcmData.nextTxType, onRs).then(_ref72 => {
4159
+ let [_unsub, rs] = _ref72;
4138
4160
  unsub = _unsub;
4139
4161
  onRs(rs);
4140
4162
  }).catch(console.error);
@@ -4336,6 +4358,10 @@ class KoniExtension {
4336
4358
  return await this.getPrice();
4337
4359
  case 'pri(price.getSubscription)':
4338
4360
  return await this.subscribePrice(id, port);
4361
+ case 'pri(price.getHistory)':
4362
+ return await this.getHistoryTokenPrice(request);
4363
+ case 'pri(price.subscribeCurrentTokenPrice)':
4364
+ return this.subscribeCurrentTokenPrice(request, id, port);
4339
4365
  case 'pri(settings.savePriceCurrency)':
4340
4366
  return await this.setPriceCurrency(request);
4341
4367
  case 'pri(balance.getBalance)':
@@ -98,7 +98,10 @@ class KoniState {
98
98
  constructor() {
99
99
  let providers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
100
100
  // Init subwallet api sdk
101
- _subwalletApiSdk.default.init(_constants.BACKEND_API_URL);
101
+ _subwalletApiSdk.default.init({
102
+ url: _constants.BACKEND_API_URL,
103
+ priceHistoryUrl: _constants.BACKEND_PRICE_HISTORY_URL
104
+ });
102
105
  this.providers = providers;
103
106
  this.eventService = new _eventService.EventService();
104
107
  this.dbService = new _DatabaseService.default(this.eventService);
@@ -13,6 +13,6 @@ const packageInfo = {
13
13
  name: '@subwallet/extension-base',
14
14
  path: typeof __dirname === 'string' ? __dirname : 'auto',
15
15
  type: 'cjs',
16
- version: '1.3.32-0'
16
+ version: '1.3.33-0'
17
17
  };
18
18
  exports.packageInfo = packageInfo;
@@ -3,9 +3,10 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.getPriceMap = exports.getExchangeRateMap = void 0;
6
+ exports.getPriceMap = exports.getHistoryPrice = exports.getExchangeRateMap = void 0;
7
7
  var _constants = require("@subwallet/extension-base/constants");
8
8
  var _staticData = require("@subwallet/extension-base/utils/staticData");
9
+ var _subwalletApiSdk = require("@subwallet/subwallet-api-sdk");
9
10
  var _util = require("@polkadot/util");
10
11
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
11
12
  // SPDX-License-Identifier: Apache-2.0
@@ -112,11 +113,13 @@ const getPriceMap = async function (priceIds) {
112
113
  const currencyData = _staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][currency || DEFAULT_CURRENCY];
113
114
  const priceMap = {};
114
115
  const price24hMap = {};
116
+ const lastUpdatedMap = {};
115
117
  responseDataPrice.forEach(val => {
116
118
  const currentPrice = val.current_price || 0;
117
119
  const price24h = currentPrice - (val.price_change_24h || 0);
118
120
  priceMap[val.id] = currentPrice;
119
121
  price24hMap[val.id] = price24h;
122
+ lastUpdatedMap[val.id] = new Date(val.last_updated || val.last_updated_at || Date.now());
120
123
  });
121
124
  const derivativeTokenSlugs = await fetchDerivativeTokenSlugs();
122
125
 
@@ -135,10 +138,26 @@ const getPriceMap = async function (priceIds) {
135
138
  currency,
136
139
  currencyData,
137
140
  priceMap,
138
- price24hMap
141
+ price24hMap,
142
+ lastUpdatedMap
139
143
  };
140
144
  } catch (e) {
141
145
  return {};
142
146
  }
143
147
  };
144
- exports.getPriceMap = getPriceMap;
148
+ exports.getPriceMap = getPriceMap;
149
+ const getHistoryPrice = async (priceId, type) => {
150
+ try {
151
+ var _subwalletApiSdk$pric;
152
+ const response = await ((_subwalletApiSdk$pric = _subwalletApiSdk.subwalletApiSdk.priceHistoryApi) === null || _subwalletApiSdk$pric === void 0 ? void 0 : _subwalletApiSdk$pric.getPriceHistory(priceId, type));
153
+ if (response) {
154
+ return response;
155
+ }
156
+ } catch (e) {
157
+ console.error('Error fetching price history:', e);
158
+ }
159
+ return {
160
+ history: []
161
+ };
162
+ };
163
+ exports.getHistoryPrice = getHistoryPrice;
@@ -27,7 +27,8 @@ const DEFAULT_PRICE_SUBJECT = {
27
27
  },
28
28
  priceMap: {},
29
29
  price24hMap: {},
30
- exchangeRateMap: {}
30
+ exchangeRateMap: {},
31
+ lastUpdatedMap: {}
31
32
  };
32
33
  const checkFetchSuccess = (obj1, obj2) => {
33
34
  return Object.keys(obj1).length > 0 && Object.keys(obj2).length > 0;
@@ -41,6 +42,7 @@ class PriceService {
41
42
  });
42
43
  this.rawPriceSubject = new _rxjs.BehaviorSubject({});
43
44
  this.rawExchangeRateMap = new _rxjs.BehaviorSubject({});
45
+ this.historyTokenPriceSubject = new _rxjs.BehaviorSubject({});
44
46
  this.status = _types.ServiceStatus.NOT_INITIALIZED;
45
47
  this.dbService = dbService;
46
48
  this.eventService = eventService;
@@ -99,6 +101,7 @@ class PriceService {
99
101
  }
100
102
  async calculatePriceMap(currency) {
101
103
  let {
104
+ lastUpdatedMap,
102
105
  price24hMap,
103
106
  priceMap
104
107
  } = this.rawPriceSubject.value;
@@ -129,7 +132,10 @@ class PriceService {
129
132
  },
130
133
  currency: currencyKey,
131
134
  exchangeRateMap: exchangeRateData,
132
- currencyData: _staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][currencyKey || DEFAULT_CURRENCY]
135
+ currencyData: _staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][currencyKey || DEFAULT_CURRENCY],
136
+ lastUpdatedMap: {
137
+ ...lastUpdatedMap
138
+ }
133
139
  };
134
140
  if (currencyKey === DEFAULT_CURRENCY) {
135
141
  return finalPriceMap;
@@ -171,6 +177,73 @@ class PriceService {
171
177
  });
172
178
  this.refreshTimeout = setTimeout(this.refreshPriceData.bind(this), _constants.CRON_REFRESH_PRICE_INTERVAL);
173
179
  }
180
+ async getHistoryTokenPriceData(priceId, timeframe) {
181
+ var _this$rawExchangeRate;
182
+ const id = (0, _utils.getTokenPriceHistoryId)(priceId, timeframe);
183
+ const currentData = this.historyTokenPriceSubject.value[id];
184
+ const now = Date.now();
185
+ const timeInterval = _utils.TIME_INTERVAL[timeframe];
186
+ let history = currentData ? structuredClone(currentData) : undefined;
187
+ const needsRefresh = !history || history.length === 0 || now - history[history.length - 1].time > timeInterval;
188
+ if (needsRefresh) {
189
+ const {
190
+ history: newHistory
191
+ } = await (0, _coingecko.getHistoryPrice)(priceId, timeframe);
192
+ if (newHistory.length > 0) {
193
+ history = newHistory;
194
+
195
+ // Update internal cache
196
+ this.historyTokenPriceSubject.next({
197
+ ...this.historyTokenPriceSubject.value,
198
+ [id]: structuredClone(history)
199
+ });
200
+ }
201
+ }
202
+ if (!history) {
203
+ return {
204
+ history: []
205
+ };
206
+ }
207
+
208
+ // Resolve current currency
209
+ const {
210
+ promise,
211
+ resolve
212
+ } = (0, _promise.createPromiseHandler)();
213
+ this.getCurrentCurrency(resolve);
214
+ const currencyKey = await promise;
215
+ const exchangeRate = (_this$rawExchangeRate = this.rawExchangeRateMap.value[currencyKey || DEFAULT_CURRENCY]) === null || _this$rawExchangeRate === void 0 ? void 0 : _this$rawExchangeRate.exchange;
216
+
217
+ // Convert value if needed
218
+ if (exchangeRate && currencyKey !== DEFAULT_CURRENCY) {
219
+ history = history.map(point => ({
220
+ ...point,
221
+ value: point.value * exchangeRate
222
+ }));
223
+ }
224
+ return {
225
+ history
226
+ };
227
+ }
228
+ subscribeCurrentTokenPrice(priceId, callback) {
229
+ const priceData = this.priceSubject.value;
230
+ const currentPrice = {
231
+ value: priceData.priceMap[priceId],
232
+ value24h: priceData.price24hMap[priceId],
233
+ time: priceData.lastUpdatedMap[priceId].getTime()
234
+ };
235
+ const unsubscribe = this.priceSubject.pipe((0, _rxjs.map)(valueSubject => ({
236
+ value: valueSubject.priceMap[priceId],
237
+ value24h: valueSubject.price24hMap[priceId],
238
+ time: valueSubject.lastUpdatedMap[priceId].getTime()
239
+ })), (0, _rxjs.distinctUntilChanged)()).subscribe(callback);
240
+ return {
241
+ unsubscribe: () => {
242
+ unsubscribe.unsubscribe();
243
+ },
244
+ currentPrice
245
+ };
246
+ }
174
247
  async init() {
175
248
  this.status = _types.ServiceStatus.INITIALIZING;
176
249
  // Fetch data from storage
@@ -101,6 +101,18 @@ Object.keys(_fetch).forEach(function (key) {
101
101
  }
102
102
  });
103
103
  });
104
+ var _price = require("./price");
105
+ Object.keys(_price).forEach(function (key) {
106
+ if (key === "default" || key === "__esModule") return;
107
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
108
+ if (key in exports && exports[key] === _price[key]) return;
109
+ Object.defineProperty(exports, key, {
110
+ enumerable: true,
111
+ get: function () {
112
+ return _price[key];
113
+ }
114
+ });
115
+ });
104
116
  var _cardano = require("./cardano");
105
117
  var _account2 = require("./account");
106
118
  Object.keys(_account2).forEach(function (key) {
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getTokenPriceHistoryId = exports.TIME_INTERVAL = void 0;
7
+ // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
8
+ // SPDX-License-Identifier: Apache-2.0
9
+
10
+ // Constants for time multipliers
11
+ const MINUTE = 60 * 1000;
12
+ const HOUR = 60 * MINUTE;
13
+ const DAY = 24 * HOUR;
14
+ const WEEK = 7 * DAY;
15
+ const TIME_INTERVAL = {
16
+ '1D': 5 * MINUTE,
17
+ '1W': HOUR,
18
+ '1M': 4 * HOUR,
19
+ '3M': 12 * HOUR,
20
+ YTD: DAY,
21
+ '1Y': DAY,
22
+ ALL: WEEK
23
+ };
24
+ exports.TIME_INTERVAL = TIME_INTERVAL;
25
+ const getTokenPriceHistoryId = (tokenId, timeframe) => {
26
+ return `${tokenId}-${timeframe}`.toLowerCase();
27
+ };
28
+ exports.getTokenPriceHistoryId = getTokenPriceHistoryId;
@@ -1,2 +1,3 @@
1
1
  export declare const isProductionMode: boolean;
2
2
  export declare const BACKEND_API_URL: string;
3
+ export declare const BACKEND_PRICE_HISTORY_URL: string;
@@ -4,4 +4,5 @@
4
4
  const PRODUCTION_BRANCHES = ['master', 'webapp', 'webapp-dev'];
5
5
  const branchName = process.env.BRANCH_NAME || 'subwallet-dev';
6
6
  export const isProductionMode = PRODUCTION_BRANCHES.indexOf(branchName) > -1;
7
- export const BACKEND_API_URL = process.env.SUBWALLET_API || (isProductionMode ? 'https://sw-services.subwallet.app/api' : 'https://be-dev.subwallet.app/api');
7
+ export const BACKEND_API_URL = process.env.SUBWALLET_API || (isProductionMode ? 'https://sw-services.subwallet.app/api' : 'https://be-dev.subwallet.app/api');
8
+ export const BACKEND_PRICE_HISTORY_URL = process.env.SUBWALLET_PRICE_HISTORY_API || (isProductionMode ? 'https://price-history.subwallet.app/api' : 'https://price-history-dev.subwallet.app/api');
@@ -90,6 +90,8 @@ export default class KoniExtension {
90
90
  private subscribeAssetSetting;
91
91
  private updateAssetSetting;
92
92
  private getPrice;
93
+ private getHistoryTokenPrice;
94
+ private subscribeCurrentTokenPrice;
93
95
  private setPriceCurrency;
94
96
  private subscribePrice;
95
97
  private getBalance;
@@ -874,6 +874,27 @@ export default class KoniExtension {
874
874
  async getPrice() {
875
875
  return this.#koniState.priceService.getPrice();
876
876
  }
877
+ async getHistoryTokenPrice({
878
+ priceId,
879
+ timeframe
880
+ }) {
881
+ return this.#koniState.priceService.getHistoryTokenPriceData(priceId, timeframe);
882
+ }
883
+ subscribeCurrentTokenPrice(priceId, id, port) {
884
+ const cb = createSubscription(id, port);
885
+ const {
886
+ currentPrice,
887
+ unsubscribe
888
+ } = this.#koniState.priceService.subscribeCurrentTokenPrice(priceId, cb);
889
+ this.createUnsubscriptionHandle(id, unsubscribe);
890
+ port.onDisconnect.addListener(() => {
891
+ this.cancelSubscription(id);
892
+ });
893
+ return {
894
+ id,
895
+ price: currentPrice
896
+ };
897
+ }
877
898
  async setPriceCurrency({
878
899
  currency
879
900
  }) {
@@ -4248,6 +4269,10 @@ export default class KoniExtension {
4248
4269
  return await this.getPrice();
4249
4270
  case 'pri(price.getSubscription)':
4250
4271
  return await this.subscribePrice(id, port);
4272
+ case 'pri(price.getHistory)':
4273
+ return await this.getHistoryTokenPrice(request);
4274
+ case 'pri(price.subscribeCurrentTokenPrice)':
4275
+ return this.subscribeCurrentTokenPrice(request, id, port);
4251
4276
  case 'pri(settings.savePriceCurrency)':
4252
4277
  return await this.setPriceCurrency(request);
4253
4278
  case 'pri(balance.getBalance)':
@@ -7,7 +7,7 @@ import { EvmProviderError } from '@subwallet/extension-base/background/errors/Ev
7
7
  import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers';
8
8
  import { isSubscriptionRunning, unsubscribe } from '@subwallet/extension-base/background/handlers/subscriptions';
9
9
  import { APIItemState, CardanoProviderErrorType, ChainType, EvmProviderErrorType, ExternalRequestPromiseStatus, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
10
- import { BACKEND_API_URL, MANTA_PAY_BALANCE_INTERVAL, REMIND_EXPORT_ACCOUNT } from '@subwallet/extension-base/constants';
10
+ import { BACKEND_API_URL, BACKEND_PRICE_HISTORY_URL, MANTA_PAY_BALANCE_INTERVAL, REMIND_EXPORT_ACCOUNT } from '@subwallet/extension-base/constants';
11
11
  import { convertErrorFormat, generateValidationProcess, validationAuthMiddleware, validationAuthWCMiddleware, validationCardanoSignDataMiddleware, validationConnectMiddleware, validationEvmDataTransactionMiddleware, validationEvmSignMessageMiddleware } from '@subwallet/extension-base/core/logic-validation';
12
12
  import { BalanceService } from '@subwallet/extension-base/services/balance-service';
13
13
  import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
@@ -89,7 +89,10 @@ export default class KoniState {
89
89
  waitStarting = null;
90
90
  constructor(providers = {}) {
91
91
  // Init subwallet api sdk
92
- subwalletApiSdk.init(BACKEND_API_URL);
92
+ subwalletApiSdk.init({
93
+ url: BACKEND_API_URL,
94
+ priceHistoryUrl: BACKEND_PRICE_HISTORY_URL
95
+ });
93
96
  this.providers = providers;
94
97
  this.eventService = new EventService();
95
98
  this.dbService = new DatabaseService(this.eventService);
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "./cjs/detectPackage.js"
18
18
  ],
19
19
  "type": "module",
20
- "version": "1.3.32-0",
20
+ "version": "1.3.33-0",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -2616,6 +2616,11 @@
2616
2616
  "require": "./cjs/utils/object.js",
2617
2617
  "default": "./utils/object.js"
2618
2618
  },
2619
+ "./utils/price": {
2620
+ "types": "./utils/price.d.ts",
2621
+ "require": "./cjs/utils/price.js",
2622
+ "default": "./utils/price.js"
2623
+ },
2619
2624
  "./utils/promise": {
2620
2625
  "types": "./utils/promise.d.ts",
2621
2626
  "require": "./cjs/utils/promise.js",
@@ -2700,12 +2705,12 @@
2700
2705
  "@sora-substrate/type-definitions": "^1.17.7",
2701
2706
  "@substrate/connect": "^0.8.9",
2702
2707
  "@subwallet/chain-list": "0.2.104",
2703
- "@subwallet/extension-base": "^1.3.32-0",
2704
- "@subwallet/extension-chains": "^1.3.32-0",
2705
- "@subwallet/extension-dapp": "^1.3.32-0",
2706
- "@subwallet/extension-inject": "^1.3.32-0",
2708
+ "@subwallet/extension-base": "^1.3.33-0",
2709
+ "@subwallet/extension-chains": "^1.3.33-0",
2710
+ "@subwallet/extension-dapp": "^1.3.33-0",
2711
+ "@subwallet/extension-inject": "^1.3.33-0",
2707
2712
  "@subwallet/keyring": "^0.1.11",
2708
- "@subwallet/subwallet-api-sdk": "^1.3.32-0",
2713
+ "@subwallet/subwallet-api-sdk": "^1.3.33-0",
2709
2714
  "@subwallet/ui-keyring": "^0.1.11",
2710
2715
  "@ton/core": "^0.56.3",
2711
2716
  "@ton/crypto": "^3.2.0",
package/packageInfo.js CHANGED
@@ -7,5 +7,5 @@ export const packageInfo = {
7
7
  name: '@subwallet/extension-base',
8
8
  path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto',
9
9
  type: 'esm',
10
- version: '1.3.32-0'
10
+ version: '1.3.33-0'
11
11
  };
@@ -1,3 +1,4 @@
1
- import { CurrencyType, ExchangeRateJSON, PriceJson } from '@subwallet/extension-base/background/KoniTypes';
1
+ import { CurrencyType, ExchangeRateJSON, HistoryTokenPriceJSON, PriceChartTimeframe, PriceJson } from '@subwallet/extension-base/background/KoniTypes';
2
2
  export declare const getExchangeRateMap: () => Promise<Record<CurrencyType, ExchangeRateJSON>>;
3
3
  export declare const getPriceMap: (priceIds: Set<string>, currency?: CurrencyType) => Promise<Omit<PriceJson, 'exchangeRateMap'>>;
4
+ export declare const getHistoryPrice: (priceId: string, type: PriceChartTimeframe) => Promise<HistoryTokenPriceJSON>;
@@ -3,6 +3,7 @@
3
3
 
4
4
  import { isProductionMode } from '@subwallet/extension-base/constants';
5
5
  import { staticData, StaticKey } from '@subwallet/extension-base/utils/staticData';
6
+ import { subwalletApiSdk } from '@subwallet/subwallet-api-sdk';
6
7
  import { isArray } from '@polkadot/util';
7
8
  const DEFAULT_CURRENCY = 'USD';
8
9
  const DERIVATIVE_TOKEN_SLUG_LIST = ['susds', 'savings-dai'];
@@ -101,11 +102,13 @@ export const getPriceMap = async (priceIds, currency = 'USD') => {
101
102
  const currencyData = staticData[StaticKey.CURRENCY_SYMBOL][currency || DEFAULT_CURRENCY];
102
103
  const priceMap = {};
103
104
  const price24hMap = {};
105
+ const lastUpdatedMap = {};
104
106
  responseDataPrice.forEach(val => {
105
107
  const currentPrice = val.current_price || 0;
106
108
  const price24h = currentPrice - (val.price_change_24h || 0);
107
109
  priceMap[val.id] = currentPrice;
108
110
  price24hMap[val.id] = price24h;
111
+ lastUpdatedMap[val.id] = new Date(val.last_updated || val.last_updated_at || Date.now());
109
112
  });
110
113
  const derivativeTokenSlugs = await fetchDerivativeTokenSlugs();
111
114
 
@@ -123,9 +126,24 @@ export const getPriceMap = async (priceIds, currency = 'USD') => {
123
126
  currency,
124
127
  currencyData,
125
128
  priceMap,
126
- price24hMap
129
+ price24hMap,
130
+ lastUpdatedMap
127
131
  };
128
132
  } catch (e) {
129
133
  return {};
130
134
  }
135
+ };
136
+ export const getHistoryPrice = async (priceId, type) => {
137
+ try {
138
+ var _subwalletApiSdk$pric;
139
+ const response = await ((_subwalletApiSdk$pric = subwalletApiSdk.priceHistoryApi) === null || _subwalletApiSdk$pric === void 0 ? void 0 : _subwalletApiSdk$pric.getPriceHistory(priceId, type));
140
+ if (response) {
141
+ return response;
142
+ }
143
+ } catch (e) {
144
+ console.error('Error fetching price history:', e);
145
+ }
146
+ return {
147
+ history: []
148
+ };
131
149
  };
@@ -1,4 +1,4 @@
1
- import { CurrencyType, PriceJson } from '@subwallet/extension-base/background/KoniTypes';
1
+ import { CurrencyType, CurrentTokenPrice, HistoryTokenPriceJSON, PriceChartTimeframe, PriceJson } from '@subwallet/extension-base/background/KoniTypes';
2
2
  import { CronServiceInterface, PersistDataServiceInterface, ServiceStatus, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
3
3
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
4
4
  import { EventService } from '@subwallet/extension-base/services/event-service';
@@ -12,6 +12,7 @@ export declare class PriceService implements StoppableServiceInterface, PersistD
12
12
  private priceSubject;
13
13
  private rawPriceSubject;
14
14
  private rawExchangeRateMap;
15
+ private historyTokenPriceSubject;
15
16
  private refreshTimeout;
16
17
  private priceIds;
17
18
  private readonly currency;
@@ -28,6 +29,15 @@ export declare class PriceService implements StoppableServiceInterface, PersistD
28
29
  getPriceIds(): Set<string>;
29
30
  setPriceCurrency(newCurrencyCode: CurrencyType): Promise<boolean>;
30
31
  refreshPriceData(priceIds?: Set<string>): void;
32
+ getHistoryTokenPriceData(priceId: string, timeframe: PriceChartTimeframe): Promise<HistoryTokenPriceJSON>;
33
+ subscribeCurrentTokenPrice(priceId: string, callback: (price: CurrentTokenPrice) => void): {
34
+ unsubscribe: () => void;
35
+ currentPrice: {
36
+ value: number;
37
+ value24h: number;
38
+ time: number;
39
+ };
40
+ };
31
41
  init(): Promise<void>;
32
42
  loadData(): Promise<void>;
33
43
  persistData(): Promise<void>;
@@ -3,13 +3,13 @@
3
3
 
4
4
  import { CRON_REFRESH_PRICE_INTERVAL, CURRENCY } from '@subwallet/extension-base/constants';
5
5
  import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
6
- import { getExchangeRateMap, getPriceMap } from '@subwallet/extension-base/services/price-service/coingecko';
6
+ import { getExchangeRateMap, getHistoryPrice, 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
+ import { getTokenPriceHistoryId, TIME_INTERVAL, wait } from '@subwallet/extension-base/utils';
10
10
  import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
11
11
  import { staticData, StaticKey } from '@subwallet/extension-base/utils/staticData';
12
- import { BehaviorSubject, combineLatest } from 'rxjs';
12
+ import { BehaviorSubject, combineLatest, distinctUntilChanged, map } from 'rxjs';
13
13
  const DEFAULT_CURRENCY = 'USD';
14
14
  const DEFAULT_PRICE_SUBJECT = {
15
15
  currency: DEFAULT_CURRENCY,
@@ -21,7 +21,8 @@ const DEFAULT_PRICE_SUBJECT = {
21
21
  },
22
22
  priceMap: {},
23
23
  price24hMap: {},
24
- exchangeRateMap: {}
24
+ exchangeRateMap: {},
25
+ lastUpdatedMap: {}
25
26
  };
26
27
  const checkFetchSuccess = (obj1, obj2) => {
27
28
  return Object.keys(obj1).length > 0 && Object.keys(obj2).length > 0;
@@ -35,6 +36,7 @@ export class PriceService {
35
36
  });
36
37
  this.rawPriceSubject = new BehaviorSubject({});
37
38
  this.rawExchangeRateMap = new BehaviorSubject({});
39
+ this.historyTokenPriceSubject = new BehaviorSubject({});
38
40
  this.status = ServiceStatus.NOT_INITIALIZED;
39
41
  this.dbService = dbService;
40
42
  this.eventService = eventService;
@@ -92,6 +94,7 @@ export class PriceService {
92
94
  }
93
95
  async calculatePriceMap(currency) {
94
96
  let {
97
+ lastUpdatedMap,
95
98
  price24hMap,
96
99
  priceMap
97
100
  } = this.rawPriceSubject.value;
@@ -122,7 +125,10 @@ export class PriceService {
122
125
  },
123
126
  currency: currencyKey,
124
127
  exchangeRateMap: exchangeRateData,
125
- currencyData: staticData[StaticKey.CURRENCY_SYMBOL][currencyKey || DEFAULT_CURRENCY]
128
+ currencyData: staticData[StaticKey.CURRENCY_SYMBOL][currencyKey || DEFAULT_CURRENCY],
129
+ lastUpdatedMap: {
130
+ ...lastUpdatedMap
131
+ }
126
132
  };
127
133
  if (currencyKey === DEFAULT_CURRENCY) {
128
134
  return finalPriceMap;
@@ -164,6 +170,73 @@ export class PriceService {
164
170
  });
165
171
  this.refreshTimeout = setTimeout(this.refreshPriceData.bind(this), CRON_REFRESH_PRICE_INTERVAL);
166
172
  }
173
+ async getHistoryTokenPriceData(priceId, timeframe) {
174
+ var _this$rawExchangeRate;
175
+ const id = getTokenPriceHistoryId(priceId, timeframe);
176
+ const currentData = this.historyTokenPriceSubject.value[id];
177
+ const now = Date.now();
178
+ const timeInterval = TIME_INTERVAL[timeframe];
179
+ let history = currentData ? structuredClone(currentData) : undefined;
180
+ const needsRefresh = !history || history.length === 0 || now - history[history.length - 1].time > timeInterval;
181
+ if (needsRefresh) {
182
+ const {
183
+ history: newHistory
184
+ } = await getHistoryPrice(priceId, timeframe);
185
+ if (newHistory.length > 0) {
186
+ history = newHistory;
187
+
188
+ // Update internal cache
189
+ this.historyTokenPriceSubject.next({
190
+ ...this.historyTokenPriceSubject.value,
191
+ [id]: structuredClone(history)
192
+ });
193
+ }
194
+ }
195
+ if (!history) {
196
+ return {
197
+ history: []
198
+ };
199
+ }
200
+
201
+ // Resolve current currency
202
+ const {
203
+ promise,
204
+ resolve
205
+ } = createPromiseHandler();
206
+ this.getCurrentCurrency(resolve);
207
+ const currencyKey = await promise;
208
+ const exchangeRate = (_this$rawExchangeRate = this.rawExchangeRateMap.value[currencyKey || DEFAULT_CURRENCY]) === null || _this$rawExchangeRate === void 0 ? void 0 : _this$rawExchangeRate.exchange;
209
+
210
+ // Convert value if needed
211
+ if (exchangeRate && currencyKey !== DEFAULT_CURRENCY) {
212
+ history = history.map(point => ({
213
+ ...point,
214
+ value: point.value * exchangeRate
215
+ }));
216
+ }
217
+ return {
218
+ history
219
+ };
220
+ }
221
+ subscribeCurrentTokenPrice(priceId, callback) {
222
+ const priceData = this.priceSubject.value;
223
+ const currentPrice = {
224
+ value: priceData.priceMap[priceId],
225
+ value24h: priceData.price24hMap[priceId],
226
+ time: priceData.lastUpdatedMap[priceId].getTime()
227
+ };
228
+ const unsubscribe = this.priceSubject.pipe(map(valueSubject => ({
229
+ value: valueSubject.priceMap[priceId],
230
+ value24h: valueSubject.price24hMap[priceId],
231
+ time: valueSubject.lastUpdatedMap[priceId].getTime()
232
+ })), distinctUntilChanged()).subscribe(callback);
233
+ return {
234
+ unsubscribe: () => {
235
+ unsubscribe.unsubscribe();
236
+ },
237
+ currentPrice
238
+ };
239
+ }
167
240
  async init() {
168
241
  this.status = ServiceStatus.INITIALIZING;
169
242
  // Fetch data from storage
package/utils/index.d.ts CHANGED
@@ -6,6 +6,7 @@ import { AccountJson } from '@subwallet/extension-base/types';
6
6
  import { BN } from '@polkadot/util';
7
7
  export * from './mv3';
8
8
  export * from './fetch';
9
+ export * from './price';
9
10
  export { convertCardanoAddressToHex } from './cardano';
10
11
  export declare const notDef: (x: any) => boolean;
11
12
  export declare const isDef: (x: any) => boolean;
package/utils/index.js CHANGED
@@ -11,6 +11,7 @@ import { assert, BN, hexToU8a, isHex } from '@polkadot/util';
11
11
  import { ethereumEncode, isEthereumAddress } from '@polkadot/util-crypto';
12
12
  export * from "./mv3.js";
13
13
  export * from "./fetch.js";
14
+ export * from "./price.js";
14
15
  export { convertCardanoAddressToHex } from "./cardano.js";
15
16
  export const notDef = x => x === null || typeof x === 'undefined';
16
17
  export const isDef = x => !notDef(x);
@@ -0,0 +1,3 @@
1
+ import { PriceChartTimeframe } from '@subwallet/extension-base/background/KoniTypes';
2
+ export declare const TIME_INTERVAL: Record<PriceChartTimeframe, number>;
3
+ export declare const getTokenPriceHistoryId: (tokenId: string, timeframe: PriceChartTimeframe) => string;
package/utils/price.js ADDED
@@ -0,0 +1,20 @@
1
+ // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ // Constants for time multipliers
5
+ const MINUTE = 60 * 1000;
6
+ const HOUR = 60 * MINUTE;
7
+ const DAY = 24 * HOUR;
8
+ const WEEK = 7 * DAY;
9
+ export const TIME_INTERVAL = {
10
+ '1D': 5 * MINUTE,
11
+ '1W': HOUR,
12
+ '1M': 4 * HOUR,
13
+ '3M': 12 * HOUR,
14
+ YTD: DAY,
15
+ '1Y': DAY,
16
+ ALL: WEEK
17
+ };
18
+ export const getTokenPriceHistoryId = (tokenId, timeframe) => {
19
+ return `${tokenId}-${timeframe}`.toLowerCase();
20
+ };