@subwallet/extension-base 1.1.33-beta.0 → 1.1.33-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/background/KoniTypes.d.ts +9 -0
  2. package/background/KoniTypes.js +3 -0
  3. package/cjs/background/KoniTypes.js +3 -0
  4. package/cjs/koni/api/yield/helper/utils.js +6 -3
  5. package/cjs/services/chain-service/constants.js +4 -2
  6. package/cjs/services/chain-service/handler/SubstrateApi.js +10 -5
  7. package/cjs/services/chain-service/index.js +120 -37
  8. package/cjs/services/chain-service/utils.js +68 -0
  9. package/cjs/services/earning-service/handlers/liquid-staking/base.js +2 -1
  10. package/cjs/services/earning-service/handlers/liquid-staking/bifrost-manta.js +140 -0
  11. package/cjs/services/earning-service/handlers/liquid-staking/bifrost.js +2 -1
  12. package/cjs/services/earning-service/handlers/liquid-staking/index.js +7 -0
  13. package/cjs/services/earning-service/handlers/special.js +7 -3
  14. package/cjs/services/earning-service/service.js +1 -0
  15. package/cjs/services/storage-service/DatabaseService.js +29 -1
  16. package/cjs/services/storage-service/databases/index.js +3 -0
  17. package/cjs/services/storage-service/db-stores/AssetRef.js +24 -0
  18. package/cjs/services/transaction-service/index.js +3 -0
  19. package/cjs/types/yield/actions/join/step.js +1 -0
  20. package/koni/api/yield/helper/utils.d.ts +1 -1
  21. package/koni/api/yield/helper/utils.js +5 -3
  22. package/package.json +12 -2
  23. package/services/chain-service/constants.d.ts +1 -0
  24. package/services/chain-service/constants.js +1 -0
  25. package/services/chain-service/handler/SubstrateApi.js +10 -5
  26. package/services/chain-service/index.d.ts +11 -1
  27. package/services/chain-service/index.js +116 -34
  28. package/services/chain-service/utils.d.ts +10 -1
  29. package/services/chain-service/utils.js +66 -1
  30. package/services/earning-service/handlers/liquid-staking/base.d.ts +1 -1
  31. package/services/earning-service/handlers/liquid-staking/base.js +2 -1
  32. package/services/earning-service/handlers/liquid-staking/bifrost-manta.d.ts +37 -0
  33. package/services/earning-service/handlers/liquid-staking/bifrost-manta.js +132 -0
  34. package/services/earning-service/handlers/liquid-staking/bifrost.d.ts +3 -3
  35. package/services/earning-service/handlers/liquid-staking/bifrost.js +2 -1
  36. package/services/earning-service/handlers/liquid-staking/index.d.ts +1 -0
  37. package/services/earning-service/handlers/liquid-staking/index.js +1 -0
  38. package/services/earning-service/handlers/special.js +7 -3
  39. package/services/earning-service/service.js +2 -1
  40. package/services/storage-service/DatabaseService.d.ts +8 -2
  41. package/services/storage-service/DatabaseService.js +28 -1
  42. package/services/storage-service/databases/index.d.ts +5 -1
  43. package/services/storage-service/databases/index.js +3 -0
  44. package/services/storage-service/db-stores/AssetRef.d.ts +7 -0
  45. package/services/storage-service/db-stores/AssetRef.js +16 -0
  46. package/services/transaction-service/index.js +3 -0
  47. package/types/yield/actions/join/step.d.ts +1 -0
  48. package/types/yield/actions/join/step.js +1 -0
@@ -3,15 +3,15 @@
3
3
 
4
4
  import { AssetLogoMap, AssetRefMap, ChainAssetMap, ChainInfoMap, ChainLogoMap, MultiChainAssetMap } from '@subwallet/chain-list';
5
5
  import { _AssetRefPath, _AssetType, _ChainStatus, _SubstrateChainType } from '@subwallet/chain-list/types';
6
- import { _ASSET_LOGO_MAP_SRC, _ASSET_REF_SRC, _CHAIN_ASSET_SRC, _CHAIN_INFO_SRC, _CHAIN_LOGO_MAP_SRC, _DEFAULT_ACTIVE_CHAINS, _MANTA_ZK_CHAIN_GROUP, _MULTI_CHAIN_ASSET_SRC, _ZK_ASSET_PREFIX } from '@subwallet/extension-base/services/chain-service/constants';
6
+ import { _DEFAULT_ACTIVE_CHAINS, _MANTA_ZK_CHAIN_GROUP, _ZK_ASSET_PREFIX, LATEST_CHAIN_DATA_FETCHING_INTERVAL } from '@subwallet/extension-base/services/chain-service/constants';
7
7
  import { EvmChainHandler } from '@subwallet/extension-base/services/chain-service/handler/EvmChainHandler';
8
8
  import { MantaPrivateHandler } from '@subwallet/extension-base/services/chain-service/handler/manta/MantaPrivateHandler';
9
9
  import { SubstrateChainHandler } from '@subwallet/extension-base/services/chain-service/handler/SubstrateChainHandler';
10
10
  import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chain-service/handler/types';
11
11
  import { _ChainConnectionStatus, _CUSTOM_PREFIX, _NFT_CONTRACT_STANDARDS, _SMART_CONTRACT_STANDARDS } from '@subwallet/extension-base/services/chain-service/types';
12
- import { _isAssetFungibleToken, _isChainEnabled, _isCustomAsset, _isCustomChain, _isCustomProvider, _isEqualContractAddress, _isEqualSmartContractAsset, _isMantaZkAsset, _isPureEvmChain, _isPureSubstrateChain, _parseAssetRefKey } from '@subwallet/extension-base/services/chain-service/utils';
12
+ import { _isAssetFungibleToken, _isChainEnabled, _isCustomAsset, _isCustomChain, _isCustomProvider, _isEqualContractAddress, _isEqualSmartContractAsset, _isMantaZkAsset, _isPureEvmChain, _isPureSubstrateChain, _parseAssetRefKey, randomizeProvider, updateLatestChainInfo } from '@subwallet/extension-base/services/chain-service/utils';
13
13
  import AssetSettingStore from '@subwallet/extension-base/stores/AssetSetting';
14
- import { MODULE_SUPPORT } from '@subwallet/extension-base/utils';
14
+ import { fetchStaticData, 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';
@@ -396,9 +396,9 @@ export class ChainService {
396
396
  await this.eventService.waitDatabaseReady;
397
397
 
398
398
  // TODO: reconsider the flow of initiation
399
- const [latestAssetRefMap, latestMultiChainAssetMap] = await Promise.all([this.fetchLatestData(_ASSET_REF_SRC, AssetRefMap), this.fetchLatestData(_MULTI_CHAIN_ASSET_SRC, MultiChainAssetMap)]);
400
- this.multiChainAssetMapSubject.next(latestMultiChainAssetMap);
401
- this.dataMap.assetRefMap = latestAssetRefMap;
399
+ this.multiChainAssetMapSubject.next(MultiChainAssetMap);
400
+ const storedAssetRefMap = await this.dbService.getAssetRefMap();
401
+ this.dataMap.assetRefMap = storedAssetRefMap && Object.values(storedAssetRefMap).length > 0 ? storedAssetRefMap : AssetRefMap;
402
402
  await this.initChains();
403
403
  this.chainInfoMapSubject.next(this.getChainInfoMap());
404
404
  this.updateChainStateMapSubscription();
@@ -406,7 +406,71 @@ export class ChainService {
406
406
  this.xcmRefMapSubject.next(this.dataMap.assetRefMap);
407
407
  await this.initApis();
408
408
  await this.initAssetSettings();
409
+ this.checkLatestData();
409
410
  }
411
+ checkLatestData() {
412
+ clearInterval(this.refreshLatestChainDataTimeOut);
413
+ this.handleLatestData();
414
+ this.handleLatestData();
415
+ this.refreshLatestChainDataTimeOut = setInterval(this.handleLatestData.bind(this), LATEST_CHAIN_DATA_FETCHING_INTERVAL);
416
+ }
417
+ stopCheckLatestChainData() {
418
+ clearInterval(this.refreshLatestChainDataTimeOut);
419
+ }
420
+ handleLatestProviderData(latestChainInfo) {
421
+ try {
422
+ if (latestChainInfo && latestChainInfo.length > 0) {
423
+ const {
424
+ needUpdateChainApiList,
425
+ storedChainInfoList
426
+ } = updateLatestChainInfo(this.dataMap, latestChainInfo);
427
+ this.dbService.bulkUpdateChainStore(storedChainInfoList).catch(console.error);
428
+ this.updateChainSubscription();
429
+ needUpdateChainApiList.forEach(chainInfo => {
430
+ console.log('Updating chain API for', chainInfo.slug);
431
+ this.initApiForChain(chainInfo).catch(console.error);
432
+ });
433
+ this.logger.log('Finished updating latest RPC providers');
434
+ }
435
+ } catch (e) {
436
+ console.error('Error fetching latest chain data');
437
+ }
438
+ }
439
+ handleLatestBlockedAssetRef(latestBlockedAssetRefList) {
440
+ if (latestBlockedAssetRefList.length > 0) {
441
+ latestBlockedAssetRefList.forEach(blockedAssetRef => {
442
+ delete this.dataMap.assetRefMap[blockedAssetRef];
443
+ });
444
+ } else {
445
+ this.dataMap.assetRefMap = AssetRefMap;
446
+ }
447
+ this.dbService.setAssetRef(this.dataMap.assetRefMap).catch(console.error);
448
+ this.xcmRefMapSubject.next(this.dataMap.assetRefMap);
449
+ this.logger.log('Finished updating latest asset ref');
450
+ }
451
+ handleLatestPriceId(latestPriceIds) {
452
+ Object.entries(latestPriceIds).forEach(([slug, priceId]) => {
453
+ if (this.dataMap.assetRegistry[slug]) {
454
+ this.dataMap.assetRegistry[slug].priceId = priceId;
455
+ }
456
+ });
457
+ this.assetRegistrySubject.next(this.dataMap.assetRegistry);
458
+ this.eventService.emit('asset.updateState', '');
459
+ this.logger.log('Finished updating latest price IDs');
460
+ }
461
+ handleLatestData() {
462
+ this.fetchLatestChainData().then(latestChainInfo => {
463
+ this.handleLatestProviderData(latestChainInfo);
464
+ }).catch(console.error);
465
+ this.fetchLatestBlockedAssetRef().then(latestAssetRef => {
466
+ this.handleLatestBlockedAssetRef(latestAssetRef);
467
+ }).catch(console.error);
468
+
469
+ // this.fetchLatestPriceIdsData().then((latestPriceIds) => {
470
+ // this.handleLatestPriceId(latestPriceIds);
471
+ // }).catch(console.error);
472
+ }
473
+
410
474
  async initApis() {
411
475
  const chainInfoMap = this.getChainInfoMap();
412
476
  const chainStateMap = this.getChainStateMap();
@@ -562,8 +626,8 @@ export class ChainService {
562
626
  }
563
627
  return duplicatedSlug;
564
628
  }
565
- async fetchLatestData(src, defaultValue) {
566
- return Promise.resolve(defaultValue);
629
+ async fetchLatestChainData() {
630
+ return await fetchStaticData('chains');
567
631
  // try {
568
632
  // const timeout = new Promise((resolve) => {
569
633
  // const id = setTimeout(() => {
@@ -600,9 +664,16 @@ export class ChainService {
600
664
  // }
601
665
  }
602
666
 
667
+ // @ts-ignore
668
+ async fetchLatestPriceIdsData() {
669
+ return await fetchStaticData('chain-assets/price-map');
670
+ }
671
+ async fetchLatestBlockedAssetRef() {
672
+ return await fetchStaticData('chain-assets/disabled-xcm-channels');
673
+ }
603
674
  async initChains() {
604
675
  const storedChainSettings = await this.dbService.getAllChainStore();
605
- const latestChainInfoMap = await this.fetchLatestData(_CHAIN_INFO_SRC, ChainInfoMap);
676
+ const defaultChainInfoMap = ChainInfoMap;
606
677
  const storedChainSettingMap = {};
607
678
  storedChainSettings.forEach(chainStoredSetting => {
608
679
  storedChainSettingMap[chainStoredSetting.slug] = chainStoredSetting;
@@ -611,10 +682,13 @@ export class ChainService {
611
682
  const deprecatedChains = [];
612
683
  const deprecatedChainMap = {};
613
684
  if (storedChainSettings.length === 0) {
614
- this.dataMap.chainInfoMap = latestChainInfoMap;
615
- Object.values(latestChainInfoMap).forEach(chainInfo => {
685
+ this.dataMap.chainInfoMap = defaultChainInfoMap;
686
+ Object.values(defaultChainInfoMap).forEach(chainInfo => {
687
+ const {
688
+ providerKey
689
+ } = randomizeProvider(chainInfo.providers);
616
690
  this.dataMap.chainStateMap[chainInfo.slug] = {
617
- currentProvider: Object.keys(chainInfo.providers)[0],
691
+ currentProvider: providerKey,
618
692
  slug: chainInfo.slug,
619
693
  connectionStatus: _ChainConnectionStatus.DISCONNECTED,
620
694
  active: _DEFAULT_ACTIVE_CHAINS.includes(chainInfo.slug)
@@ -624,15 +698,15 @@ export class ChainService {
624
698
  newStorageData.push({
625
699
  ...chainInfo,
626
700
  active: _DEFAULT_ACTIVE_CHAINS.includes(chainInfo.slug),
627
- currentProvider: Object.keys(chainInfo.providers)[0]
701
+ currentProvider: providerKey
628
702
  });
629
703
  });
630
704
  } else {
631
- const mergedChainInfoMap = latestChainInfoMap;
705
+ const mergedChainInfoMap = defaultChainInfoMap;
632
706
  for (const [storedSlug, storedChainInfo] of Object.entries(storedChainSettingMap)) {
633
- const chainInfo = latestChainInfoMap[storedSlug];
707
+ const chainInfo = defaultChainInfoMap[storedSlug];
634
708
 
635
- // Network is existed on change list
709
+ // Network existed on change list
636
710
  // check predefined chains first, keep setting for providers and currentProvider
637
711
  if (chainInfo) {
638
712
  // Keep customer provider only
@@ -647,23 +721,27 @@ export class ChainService {
647
721
  }
648
722
  }
649
723
  mergedChainInfoMap[storedSlug].providers = providers;
650
-
651
- // Merge current provider
652
- let currentProvider = storedChainInfo.currentProvider;
653
- const providerValue = storedChainInfo.providers[currentProvider] || '';
654
- if (!providers[currentProvider]) {
655
- currentProvider = Object.keys(providers)[0];
656
- for (const [key, value] of Object.entries(providers)) {
657
- if (providerValue === value) {
658
- currentProvider = key;
659
- break;
660
- }
724
+ const {
725
+ providerKey
726
+ } = randomizeProvider(providers);
727
+ let selectedProvider = providerKey;
728
+ const storedProviderKey = storedChainInfo.currentProvider;
729
+ const storedProviderValue = storedChainInfo.providers[storedProviderKey] || '';
730
+ if (storedProviderValue !== null && storedProviderValue !== void 0 && storedProviderValue.startsWith('light') || storedProviderKey !== null && storedProviderKey !== void 0 && storedProviderKey.startsWith(_CUSTOM_PREFIX)) {
731
+ const savedProviderKey = Object.keys(providers).find(key => providers[key] === storedProviderValue);
732
+ if (savedProviderKey) {
733
+ selectedProvider = savedProviderKey;
661
734
  }
662
735
  }
736
+
737
+ // Merge current provider
738
+ // let currentProvider = storedChainInfo.currentProvider;
739
+ // const providerValue = storedChainInfo.providers[selectedProvider] || '';
740
+
663
741
  const hasProvider = Object.values(providers).length > 0;
664
742
  const canActive = hasProvider && chainInfo.chainStatus === _ChainStatus.ACTIVE;
665
743
  this.dataMap.chainStateMap[storedSlug] = {
666
- currentProvider: currentProvider,
744
+ currentProvider: selectedProvider,
667
745
  slug: storedSlug,
668
746
  connectionStatus: _ChainConnectionStatus.DISCONNECTED,
669
747
  active: canActive && storedChainInfo.active
@@ -671,13 +749,13 @@ export class ChainService {
671
749
  newStorageData.push({
672
750
  ...mergedChainInfoMap[storedSlug],
673
751
  active: canActive && storedChainInfo.active,
674
- currentProvider: currentProvider
752
+ currentProvider: selectedProvider
675
753
  });
676
754
  } else if (_isCustomChain(storedSlug)) {
677
755
  var _storedChainInfo$subs, _storedChainInfo$evmI;
678
756
  // only custom chains are left
679
757
  // check custom chain duplicated with predefined chain => merge into predefined chain
680
- const duplicatedDefaultSlug = this.checkExistedPredefinedChain(latestChainInfoMap, (_storedChainInfo$subs = storedChainInfo.substrateInfo) === null || _storedChainInfo$subs === void 0 ? void 0 : _storedChainInfo$subs.genesisHash, (_storedChainInfo$evmI = storedChainInfo.evmInfo) === null || _storedChainInfo$evmI === void 0 ? void 0 : _storedChainInfo$evmI.evmChainId);
758
+ const duplicatedDefaultSlug = this.checkExistedPredefinedChain(defaultChainInfoMap, (_storedChainInfo$subs = storedChainInfo.substrateInfo) === null || _storedChainInfo$subs === void 0 ? void 0 : _storedChainInfo$subs.genesisHash, (_storedChainInfo$evmI = storedChainInfo.evmInfo) === null || _storedChainInfo$evmI === void 0 ? void 0 : _storedChainInfo$evmI.evmChainId);
681
759
  if (duplicatedDefaultSlug.length > 0) {
682
760
  // merge custom chain with existed chain
683
761
  mergedChainInfoMap[duplicatedDefaultSlug].providers = {
@@ -702,6 +780,7 @@ export class ChainService {
702
780
  slug: storedSlug,
703
781
  name: storedChainInfo.name,
704
782
  providers: storedChainInfo.providers,
783
+ // TODO: review
705
784
  evmInfo: storedChainInfo.evmInfo,
706
785
  substrateInfo: storedChainInfo.substrateInfo,
707
786
  isTestnet: storedChainInfo.isTestnet,
@@ -711,6 +790,7 @@ export class ChainService {
711
790
  };
712
791
  this.dataMap.chainStateMap[storedSlug] = {
713
792
  currentProvider: storedChainInfo.currentProvider,
793
+ // TODO: review
714
794
  slug: storedSlug,
715
795
  connectionStatus: _ChainConnectionStatus.DISCONNECTED,
716
796
  active: storedChainInfo.active
@@ -718,7 +798,7 @@ export class ChainService {
718
798
  newStorageData.push({
719
799
  ...mergedChainInfoMap[storedSlug],
720
800
  active: storedChainInfo.active,
721
- currentProvider: storedChainInfo.currentProvider
801
+ currentProvider: storedChainInfo.currentProvider // TODO: review
722
802
  });
723
803
  }
724
804
  } else {
@@ -750,7 +830,7 @@ export class ChainService {
750
830
  }
751
831
  async initAssetRegistry(deprecatedCustomChainMap) {
752
832
  const storedAssetRegistry = await this.dbService.getAllAssetStore();
753
- const latestAssetRegistry = await this.fetchLatestData(_CHAIN_ASSET_SRC, ChainAssetMap);
833
+ const latestAssetRegistry = ChainAssetMap;
754
834
  const availableChains = Object.values(this.dataMap.chainInfoMap).filter(info => info.chainStatus === _ChainStatus.ACTIVE).map(chainInfo => chainInfo.slug);
755
835
 
756
836
  // Fill out zk assets from latestAssetRegistry if not supported
@@ -1200,9 +1280,11 @@ export class ChainService {
1200
1280
  }
1201
1281
  async stopAllChainApis() {
1202
1282
  await Promise.all([this.substrateChainHandler.sleep(), this.evmChainHandler.sleep()]);
1283
+ this.stopCheckLatestChainData();
1203
1284
  }
1204
1285
  async resumeAllChainApis() {
1205
1286
  await Promise.all([this.substrateChainHandler.wakeUp(), this.evmChainHandler.wakeUp()]);
1287
+ this.checkLatestData();
1206
1288
  }
1207
1289
  checkAndUpdateStatusMapForChain(chainSlug) {
1208
1290
  const substrateApiMap = this.getSubstrateApiMap();
@@ -1337,10 +1419,10 @@ export class ChainService {
1337
1419
  return this.assetSettingSubject;
1338
1420
  }
1339
1421
  async getChainLogoMap() {
1340
- return await this.fetchLatestData(_CHAIN_LOGO_MAP_SRC, ChainLogoMap);
1422
+ return Promise.resolve(ChainLogoMap);
1341
1423
  }
1342
1424
  async getAssetLogoMap() {
1343
- return await this.fetchLatestData(_ASSET_LOGO_MAP_SRC, AssetLogoMap);
1425
+ return Promise.resolve(AssetLogoMap);
1344
1426
  }
1345
1427
  resetWallet(resetAll) {
1346
1428
  if (resetAll) {
@@ -1,6 +1,7 @@
1
1
  import { _AssetRef, _AssetType, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types';
2
2
  import { BasicTokenInfo } from '@subwallet/extension-base/background/KoniTypes';
3
- import { _ChainState } from '@subwallet/extension-base/services/chain-service/types';
3
+ import { _ChainState, _DataMap } from '@subwallet/extension-base/services/chain-service/types';
4
+ import { IChain } from '@subwallet/extension-base/services/storage-service/databases';
4
5
  export declare function _isCustomChain(slug: string): boolean;
5
6
  export declare function _isCustomAsset(slug: string): boolean;
6
7
  export declare function _getCustomAssets(assetRegistry: Record<string, _ChainAsset>): Record<string, _ChainAsset>;
@@ -67,3 +68,11 @@ export declare function _generateCustomProviderKey(index: number): string;
67
68
  export declare const findChainInfoByHalfGenesisHash: (chainMap: Record<string, _ChainInfo>, halfGenesisHash?: string) => _ChainInfo | null;
68
69
  export declare const findChainInfoByChainId: (chainMap: Record<string, _ChainInfo>, chainId?: number) => _ChainInfo | null;
69
70
  export declare function _isMantaZkAsset(chainAsset: _ChainAsset): boolean;
71
+ export declare function randomizeProvider(providers: Record<string, string>, excludedKeys?: string[]): {
72
+ providerKey: string;
73
+ providerValue: string;
74
+ };
75
+ export declare function updateLatestChainInfo(currentDataMap: _DataMap, latestChainInfoList: _ChainInfo[]): {
76
+ storedChainInfoList: IChain[];
77
+ needUpdateChainApiList: _ChainInfo[];
78
+ };
@@ -1,7 +1,7 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-base
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import { _AssetRefPath, _AssetType, _SubstrateChainType } from '@subwallet/chain-list/types';
4
+ import { _AssetRefPath, _AssetType, _ChainStatus, _SubstrateChainType } from '@subwallet/chain-list/types';
5
5
  import { _MANTA_ZK_CHAIN_GROUP, _ZK_ASSET_PREFIX } from '@subwallet/extension-base/services/chain-service/constants';
6
6
  import { _CUSTOM_PREFIX, _SMART_CONTRACT_STANDARDS } from '@subwallet/extension-base/services/chain-service/types';
7
7
  import { isEthereumAddress } from '@polkadot/util-crypto';
@@ -362,4 +362,69 @@ export const findChainInfoByChainId = (chainMap, chainId) => {
362
362
  };
363
363
  export function _isMantaZkAsset(chainAsset) {
364
364
  return _MANTA_ZK_CHAIN_GROUP.includes(chainAsset.originChain) && chainAsset.symbol.startsWith(_ZK_ASSET_PREFIX);
365
+ }
366
+ export function randomizeProvider(providers, excludedKeys) {
367
+ if (Object.keys(providers).length === 0) {
368
+ return {
369
+ providerKey: '',
370
+ providerValue: ''
371
+ };
372
+ }
373
+ let isValid = false;
374
+ let selectedProviderKey = '';
375
+ let selectedProviderValue = '';
376
+ while (!isValid) {
377
+ var _selectedProviderValu, _selectedProviderKey;
378
+ const randomProvider = Math.floor(Math.random() * Object.keys(providers).length);
379
+ selectedProviderKey = Object.keys(providers)[randomProvider];
380
+ selectedProviderValue = providers[selectedProviderKey];
381
+ if (!((_selectedProviderValu = selectedProviderValue) !== null && _selectedProviderValu !== void 0 && _selectedProviderValu.startsWith('light')) && !((_selectedProviderKey = selectedProviderKey) !== null && _selectedProviderKey !== void 0 && _selectedProviderKey.startsWith(_CUSTOM_PREFIX)) && !(excludedKeys !== null && excludedKeys !== void 0 && excludedKeys.includes(selectedProviderKey))) {
382
+ // if it's light client, then re-randomize
383
+ isValid = true;
384
+ }
385
+ }
386
+ return {
387
+ providerKey: selectedProviderKey,
388
+ providerValue: selectedProviderValue
389
+ };
390
+ }
391
+ export function updateLatestChainInfo(currentDataMap, latestChainInfoList) {
392
+ const currentChainInfoMap = currentDataMap.chainInfoMap;
393
+ const currentChainStateMap = currentDataMap.chainStateMap;
394
+ const storedChainInfoList = [];
395
+ const needUpdateChainApiList = [];
396
+ latestChainInfoList.forEach(latestChainInfo => {
397
+ const currentChainInfo = currentChainInfoMap[latestChainInfo.slug];
398
+ const currentChainState = currentChainStateMap[latestChainInfo.slug];
399
+ const currentChainProviderValue = currentChainInfo === null || currentChainInfo === void 0 ? void 0 : currentChainInfo.providers[currentChainState === null || currentChainState === void 0 ? void 0 : currentChainState.currentProvider];
400
+ if (currentChainInfo && currentChainState) {
401
+ const preservedProvider = {};
402
+ Object.entries(currentChainInfo.providers).forEach(([providerKey, providerValue]) => {
403
+ if (providerValue !== null && providerValue !== void 0 && providerValue.startsWith('light') || providerKey !== null && providerKey !== void 0 && providerKey.startsWith(_CUSTOM_PREFIX)) {
404
+ preservedProvider[providerKey] = providerValue;
405
+ }
406
+ });
407
+ currentChainInfo.providers = {
408
+ ...latestChainInfo.providers,
409
+ ...preservedProvider
410
+ };
411
+ const currentProviderNotFound = !Object.keys(currentChainInfo.providers).includes(currentChainState.currentProvider);
412
+ const currentProviderUpdated = Object.keys(currentChainInfo.providers).includes(currentChainState.currentProvider) && !Object.values(currentChainInfo.providers).includes(currentChainProviderValue);
413
+ if (currentChainInfo.chainStatus === _ChainStatus.ACTIVE && (currentProviderNotFound || currentProviderUpdated)) {
414
+ const {
415
+ providerKey
416
+ } = randomizeProvider(currentChainInfo.providers);
417
+ currentChainState.currentProvider = providerKey;
418
+ needUpdateChainApiList.push(currentChainInfo);
419
+ }
420
+ storedChainInfoList.push({
421
+ ...currentChainInfo,
422
+ ...currentChainState
423
+ });
424
+ }
425
+ });
426
+ return {
427
+ storedChainInfoList,
428
+ needUpdateChainApiList
429
+ };
365
430
  }
@@ -6,6 +6,6 @@ export default abstract class BaseLiquidStakingPoolHandler extends BaseSpecialSt
6
6
  /** Rate convert token when redeem */
7
7
  readonly minAmountPercent: number;
8
8
  static get defaultMinAmountPercent(): number;
9
- createParamToRedeem(amount: string, address: string): Promise<number>;
9
+ createParamToRedeem(amount: string, address: string): Promise<string>;
10
10
  validateYieldLeave(amount: string, address: string, fastLeave: boolean, selectedTarget?: string): Promise<TransactionError[]>;
11
11
  }
@@ -6,6 +6,7 @@ import { BasicTxErrorType, StakingTxErrorType } from '@subwallet/extension-base/
6
6
  import { convertDerivativeToOriginToken } from '@subwallet/extension-base/koni/api/yield/helper/utils';
7
7
  import { YieldPoolType } from '@subwallet/extension-base/types';
8
8
  import { formatNumber } from '@subwallet/extension-base/utils';
9
+ import BigN from 'bignumber.js';
9
10
  import { t } from 'i18next';
10
11
  import { BN, BN_ZERO } from '@polkadot/util';
11
12
  import BaseSpecialStakingPoolHandler from "../special.js";
@@ -31,7 +32,7 @@ export default class BaseLiquidStakingPoolHandler extends BaseSpecialStakingPool
31
32
  return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
32
33
  }
33
34
  const formattedMinAmount = convertDerivativeToOriginToken(amount, poolInfo, derivativeTokenInfo, originTokenInfo);
34
- return Math.floor(this.minAmountPercent * formattedMinAmount);
35
+ return new BigN(formattedMinAmount).multipliedBy(this.minAmountPercent).toFixed(0);
35
36
  }
36
37
  async validateYieldLeave(amount, address, fastLeave, selectedTarget) {
37
38
  const poolInfo = await this.getPoolInfo();
@@ -0,0 +1,37 @@
1
+ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
2
+ import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
3
+ import { BaseYieldStepDetail, HandleYieldStepData, LiquidYieldPoolInfo, OptimalYieldPath, SubmitYieldJoinData, TransactionData } from '@subwallet/extension-base/types';
4
+ import BifrostLiquidStakingPoolHandler from './bifrost';
5
+ export interface BifrostLiquidStakingMeta {
6
+ apy: string;
7
+ apyBase: string;
8
+ apyReward: string;
9
+ tvl: number;
10
+ tvm: number;
11
+ holders: number;
12
+ }
13
+ export interface BifrostVtokenExchangeRateResp {
14
+ ratio: BifrostVtokenExchangeRate[];
15
+ }
16
+ export interface BifrostVtokenExchangeRate {
17
+ ratio: string;
18
+ key: string;
19
+ timestamp: string;
20
+ total_issuance: number;
21
+ token_pool: number;
22
+ }
23
+ export default class BifrostMantaLiquidStakingPoolHandler extends BifrostLiquidStakingPoolHandler {
24
+ protected readonly altInputAsset: string;
25
+ protected readonly derivativeAssets: string[];
26
+ protected readonly inputAsset: string;
27
+ protected readonly rewardAssets: string[];
28
+ protected readonly feeAssets: string[];
29
+ readonly minAmountPercent: number;
30
+ constructor(state: KoniState, chain: string);
31
+ protected getDescription(): string;
32
+ getPoolStat(): Promise<LiquidYieldPoolInfo>;
33
+ get submitJoinStepInfo(): BaseYieldStepDetail;
34
+ handleSubmitStep(data: SubmitYieldJoinData, path: OptimalYieldPath): Promise<HandleYieldStepData>;
35
+ handleYieldRedeem(amount: string, address: string, selectedTarget?: string): Promise<[ExtrinsicType, TransactionData]>;
36
+ handleYieldUnstake(amount: string, address: string, selectedTarget?: string): Promise<[ExtrinsicType, TransactionData]>;
37
+ }
@@ -0,0 +1,132 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
5
+ import { _getAssetDecimals, _getTokenOnChainInfo } from '@subwallet/extension-base/services/chain-service/utils';
6
+ import { YieldStepType } from '@subwallet/extension-base/types';
7
+ import fetch from 'cross-fetch';
8
+ import BifrostLiquidStakingPoolHandler from "./bifrost.js";
9
+ const STATS_URL = 'https://api.bifrost.app/api/site';
10
+ const RATIO_URL = 'https://api.bifrost.app/api/omni/MANTA';
11
+ export default class BifrostMantaLiquidStakingPoolHandler extends BifrostLiquidStakingPoolHandler {
12
+ altInputAsset = 'manta_network-NATIVE-MANTA';
13
+ derivativeAssets = ['bifrost_dot-LOCAL-vMANTA'];
14
+ inputAsset = 'bifrost_dot-LOCAL-MANTA';
15
+ rewardAssets = ['bifrost_dot-LOCAL-MANTA'];
16
+ feeAssets = ['bifrost_dot-NATIVE-BNC', 'bifrost_dot-LOCAL-MANTA'];
17
+ minAmountPercent = 0.985;
18
+ constructor(state, chain) {
19
+ super(state, chain);
20
+ const chainInfo = this.chainInfo;
21
+ this.slug = `MANTA___liquid_staking___${chain}`;
22
+ this.name = `${chainInfo.name} Liquid Staking Manta`;
23
+ this.shortName = chainInfo.name.replaceAll(' Relay Chain', '');
24
+ }
25
+ getDescription() {
26
+ return 'Stake MANTA to earn yield on vMANTA';
27
+ }
28
+
29
+ /* Subscribe pool info */
30
+
31
+ async getPoolStat() {
32
+ const substrateApi = await this.substrateApi.isReady;
33
+ const stakingMetaPromise = new Promise(function (resolve) {
34
+ fetch(STATS_URL, {
35
+ method: 'GET'
36
+ }).then(res => {
37
+ resolve(res.json());
38
+ }).catch(console.error);
39
+ });
40
+ const exchangeRatePromise = new Promise(function (resolve) {
41
+ fetch(RATIO_URL, {
42
+ method: 'GET'
43
+ }).then(resp => {
44
+ resolve(resp.json());
45
+ }).catch(console.error);
46
+ });
47
+ const derivativeTokenInfo = this.state.getAssetBySlug(this.derivativeAssets[0]);
48
+ const inputTokenInfo = this.state.getAssetBySlug(this.inputAsset);
49
+ const [_stakingMeta, _exchangeRate, _minimumRedeem, _minimumMint] = await Promise.all([stakingMetaPromise, exchangeRatePromise, substrateApi.api.query.vtokenMinting.minimumRedeem(_getTokenOnChainInfo(derivativeTokenInfo)), substrateApi.api.query.vtokenMinting.minimumMint(_getTokenOnChainInfo(inputTokenInfo))]);
50
+ const minimumRedeem = _minimumRedeem.toString();
51
+ const minimumMint = _minimumMint.toString();
52
+ const stakingMeta = _stakingMeta;
53
+ const exchangeRate = _exchangeRate;
54
+ const vMANTAStats = stakingMeta.vMANTA;
55
+ const assetInfo = this.state.getAssetBySlug(this.inputAsset);
56
+ const assetDecimals = 10 ** _getAssetDecimals(assetInfo);
57
+ const rate = parseFloat(exchangeRate.ratio[exchangeRate.ratio.length - 1].ratio); // TODO
58
+
59
+ this.updateExchangeRate(rate);
60
+ return {
61
+ ...this.baseInfo,
62
+ type: this.type,
63
+ metadata: {
64
+ ...this.metadataInfo,
65
+ description: this.getDescription()
66
+ },
67
+ statistic: {
68
+ assetEarning: [{
69
+ slug: this.rewardAssets[0],
70
+ apy: parseFloat(vMANTAStats.apyBase),
71
+ exchangeRate: rate
72
+ }],
73
+ farmerCount: vMANTAStats.holders,
74
+ unstakingPeriod: 24 * 7,
75
+ maxCandidatePerFarmer: 1,
76
+ maxWithdrawalRequestPerFarmer: 1,
77
+ earningThreshold: {
78
+ join: minimumMint,
79
+ defaultUnstake: minimumRedeem,
80
+ fastUnstake: '0'
81
+ },
82
+ totalApy: parseFloat(vMANTAStats.apyBase),
83
+ tvl: (vMANTAStats.tvm * assetDecimals).toString()
84
+ }
85
+ };
86
+ }
87
+
88
+ /* Subscribe pool info */
89
+
90
+ /* Join pool action */
91
+
92
+ get submitJoinStepInfo() {
93
+ return {
94
+ name: 'Mint vMANTA',
95
+ type: YieldStepType.MINT_VMANTA
96
+ };
97
+ }
98
+ async handleSubmitStep(data, path) {
99
+ const substrateApi = await this.substrateApi.isReady;
100
+ const inputTokenSlug = this.inputAsset;
101
+ const inputTokenInfo = this.state.getAssetBySlug(inputTokenSlug);
102
+ const extrinsic = substrateApi.api.tx.vtokenMinting.mint(_getTokenOnChainInfo(inputTokenInfo), data.amount, undefined, undefined);
103
+ return {
104
+ txChain: this.chain,
105
+ extrinsicType: ExtrinsicType.MINT_VMANTA,
106
+ extrinsic,
107
+ txData: data,
108
+ transferNativeAmount: '0',
109
+ chainType: ChainType.SUBSTRATE
110
+ };
111
+ }
112
+
113
+ /* Join pool action */
114
+
115
+ /* Leave pool action */
116
+
117
+ async handleYieldRedeem(amount, address, selectedTarget) {
118
+ const substrateApi = await this.substrateApi.isReady;
119
+ const weightedMinAmount = await this.createParamToRedeem(amount, address);
120
+ const extrinsic = substrateApi.api.tx.stablePool.swap(5, 1, 0, amount, weightedMinAmount);
121
+ return [ExtrinsicType.REDEEM_VMANTA, extrinsic];
122
+ }
123
+ async handleYieldUnstake(amount, address, selectedTarget) {
124
+ const chainApi = await this.substrateApi.isReady;
125
+ const derivativeTokenSlug = this.derivativeAssets[0];
126
+ const derivativeTokenInfo = this.state.getAssetBySlug(derivativeTokenSlug);
127
+ const extrinsic = chainApi.api.tx.vtokenMinting.redeem(_getTokenOnChainInfo(derivativeTokenInfo), amount);
128
+ return [ExtrinsicType.UNSTAKE_VMANTA, extrinsic];
129
+ }
130
+
131
+ /* Leave pool action */
132
+ }
@@ -24,14 +24,14 @@ export interface BifrostVtokenExchangeRate {
24
24
  }
25
25
  export default class BifrostLiquidStakingPoolHandler extends BaseLiquidStakingPoolHandler {
26
26
  slug: string;
27
- protected readonly name: string;
28
- protected readonly shortName: string;
27
+ protected name: string;
28
+ protected shortName: string;
29
29
  protected readonly altInputAsset: string;
30
30
  protected readonly derivativeAssets: string[];
31
31
  protected readonly inputAsset: string;
32
32
  protected readonly rewardAssets: string[];
33
33
  protected readonly feeAssets: string[];
34
- readonly minAmountPercent = 0.99;
34
+ readonly minAmountPercent: number;
35
35
  protected readonly availableMethod: YieldPoolMethodInfo;
36
36
  protected readonly rateDecimals = 0;
37
37
  constructor(state: KoniState, chain: string);
@@ -34,7 +34,7 @@ export default class BifrostLiquidStakingPoolHandler extends BaseLiquidStakingPo
34
34
  super(state, chain);
35
35
  const chainInfo = this.chainInfo;
36
36
  this.slug = `DOT___liquid_staking___${chain}`;
37
- this.name = `${chainInfo.name} Liquid Staking`;
37
+ this.name = `${chainInfo.name} Liquid Staking DOT`;
38
38
  this.shortName = chainInfo.name.replaceAll(' Relay Chain', '');
39
39
  }
40
40
  getDescription() {
@@ -93,6 +93,7 @@ export default class BifrostLiquidStakingPoolHandler extends BaseLiquidStakingPo
93
93
  unstakingPeriod: 24 * 28,
94
94
  maxCandidatePerFarmer: 1,
95
95
  maxWithdrawalRequestPerFarmer: 1,
96
+ farmerCount: vDOTStats.holders,
96
97
  earningThreshold: {
97
98
  join: minimumMint,
98
99
  defaultUnstake: minimumRedeem,
@@ -1,4 +1,5 @@
1
1
  export { default as AcalaLiquidStakingPoolHandler } from './acala';
2
2
  export { default as BifrostLiquidStakingPoolHandler } from './bifrost';
3
+ export { default as BifrostMantaLiquidStakingPoolHandler } from './bifrost-manta';
3
4
  export { default as ParallelLiquidStakingPoolHandler } from './parallel';
4
5
  export { default as StellaSwapLiquidStakingPoolHandler } from './stella-swap';
@@ -3,5 +3,6 @@
3
3
 
4
4
  export { default as AcalaLiquidStakingPoolHandler } from "./acala.js";
5
5
  export { default as BifrostLiquidStakingPoolHandler } from "./bifrost.js";
6
+ export { default as BifrostMantaLiquidStakingPoolHandler } from "./bifrost-manta.js";
6
7
  export { default as ParallelLiquidStakingPoolHandler } from "./parallel.js";
7
8
  export { default as StellaSwapLiquidStakingPoolHandler } from "./stella-swap.js";