@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.
- package/background/KoniTypes.d.ts +9 -0
- package/background/KoniTypes.js +3 -0
- package/cjs/background/KoniTypes.js +3 -0
- package/cjs/koni/api/yield/helper/utils.js +6 -3
- package/cjs/services/chain-service/constants.js +4 -2
- package/cjs/services/chain-service/handler/SubstrateApi.js +10 -5
- package/cjs/services/chain-service/index.js +120 -37
- package/cjs/services/chain-service/utils.js +68 -0
- package/cjs/services/earning-service/handlers/liquid-staking/base.js +2 -1
- package/cjs/services/earning-service/handlers/liquid-staking/bifrost-manta.js +140 -0
- package/cjs/services/earning-service/handlers/liquid-staking/bifrost.js +2 -1
- package/cjs/services/earning-service/handlers/liquid-staking/index.js +7 -0
- package/cjs/services/earning-service/handlers/special.js +7 -3
- package/cjs/services/earning-service/service.js +1 -0
- package/cjs/services/storage-service/DatabaseService.js +29 -1
- package/cjs/services/storage-service/databases/index.js +3 -0
- package/cjs/services/storage-service/db-stores/AssetRef.js +24 -0
- package/cjs/services/transaction-service/index.js +3 -0
- package/cjs/types/yield/actions/join/step.js +1 -0
- package/koni/api/yield/helper/utils.d.ts +1 -1
- package/koni/api/yield/helper/utils.js +5 -3
- package/package.json +12 -2
- package/services/chain-service/constants.d.ts +1 -0
- package/services/chain-service/constants.js +1 -0
- package/services/chain-service/handler/SubstrateApi.js +10 -5
- package/services/chain-service/index.d.ts +11 -1
- package/services/chain-service/index.js +116 -34
- package/services/chain-service/utils.d.ts +10 -1
- package/services/chain-service/utils.js +66 -1
- package/services/earning-service/handlers/liquid-staking/base.d.ts +1 -1
- package/services/earning-service/handlers/liquid-staking/base.js +2 -1
- package/services/earning-service/handlers/liquid-staking/bifrost-manta.d.ts +37 -0
- package/services/earning-service/handlers/liquid-staking/bifrost-manta.js +132 -0
- package/services/earning-service/handlers/liquid-staking/bifrost.d.ts +3 -3
- package/services/earning-service/handlers/liquid-staking/bifrost.js +2 -1
- package/services/earning-service/handlers/liquid-staking/index.d.ts +1 -0
- package/services/earning-service/handlers/liquid-staking/index.js +1 -0
- package/services/earning-service/handlers/special.js +7 -3
- package/services/earning-service/service.js +2 -1
- package/services/storage-service/DatabaseService.d.ts +8 -2
- package/services/storage-service/DatabaseService.js +28 -1
- package/services/storage-service/databases/index.d.ts +5 -1
- package/services/storage-service/databases/index.js +3 -0
- package/services/storage-service/db-stores/AssetRef.d.ts +7 -0
- package/services/storage-service/db-stores/AssetRef.js +16 -0
- package/services/transaction-service/index.js +3 -0
- package/types/yield/actions/join/step.d.ts +1 -0
- 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 {
|
|
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
|
-
|
|
400
|
-
this.
|
|
401
|
-
this.dataMap.assetRefMap =
|
|
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
|
|
566
|
-
return
|
|
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
|
|
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 =
|
|
615
|
-
Object.values(
|
|
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:
|
|
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:
|
|
701
|
+
currentProvider: providerKey
|
|
628
702
|
});
|
|
629
703
|
});
|
|
630
704
|
} else {
|
|
631
|
-
const mergedChainInfoMap =
|
|
705
|
+
const mergedChainInfoMap = defaultChainInfoMap;
|
|
632
706
|
for (const [storedSlug, storedChainInfo] of Object.entries(storedChainSettingMap)) {
|
|
633
|
-
const chainInfo =
|
|
707
|
+
const chainInfo = defaultChainInfoMap[storedSlug];
|
|
634
708
|
|
|
635
|
-
// Network
|
|
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
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
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:
|
|
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:
|
|
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(
|
|
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 =
|
|
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
|
|
1422
|
+
return Promise.resolve(ChainLogoMap);
|
|
1341
1423
|
}
|
|
1342
1424
|
async getAssetLogoMap() {
|
|
1343
|
-
return
|
|
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<
|
|
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
|
|
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
|
|
28
|
-
protected
|
|
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
|
|
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";
|