@subwallet/extension-base 1.1.33-beta.0 → 1.1.33-beta.2
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/constants/staking.js +1 -1
- 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 +144 -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 +34 -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/constants/staking.js +1 -1
- 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 +12 -1
- package/services/chain-service/index.js +140 -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.js +34 -0
- package/services/storage-service/databases/index.d.ts +4 -1
- 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,11 @@ export class ChainService {
|
|
|
396
396
|
await this.eventService.waitDatabaseReady;
|
|
397
397
|
|
|
398
398
|
// TODO: reconsider the flow of initiation
|
|
399
|
-
|
|
400
|
-
this.
|
|
401
|
-
|
|
399
|
+
this.multiChainAssetMapSubject.next(MultiChainAssetMap);
|
|
400
|
+
// const storedAssetRefMap = await this.dbService.getAssetRefMap();
|
|
401
|
+
//
|
|
402
|
+
// this.dataMap.assetRefMap = storedAssetRefMap && Object.values(storedAssetRefMap).length > 0 ? storedAssetRefMap : AssetRefMap;
|
|
403
|
+
|
|
402
404
|
await this.initChains();
|
|
403
405
|
this.chainInfoMapSubject.next(this.getChainInfoMap());
|
|
404
406
|
this.updateChainStateMapSubscription();
|
|
@@ -406,7 +408,93 @@ export class ChainService {
|
|
|
406
408
|
this.xcmRefMapSubject.next(this.dataMap.assetRefMap);
|
|
407
409
|
await this.initApis();
|
|
408
410
|
await this.initAssetSettings();
|
|
411
|
+
await this.initAssetRefMap();
|
|
412
|
+
this.checkLatestData();
|
|
413
|
+
}
|
|
414
|
+
async initAssetRefMap() {
|
|
415
|
+
try {
|
|
416
|
+
const fetchPromise = this.fetchLatestBlockedAssetRef();
|
|
417
|
+
const timeout = new Promise(resolve => {
|
|
418
|
+
const id = setTimeout(() => {
|
|
419
|
+
clearTimeout(id);
|
|
420
|
+
resolve(null);
|
|
421
|
+
}, 1000);
|
|
422
|
+
});
|
|
423
|
+
const disabledAssetRefs = (await Promise.race([timeout, fetchPromise])) || null;
|
|
424
|
+
if (disabledAssetRefs) {
|
|
425
|
+
this.handleLatestBlockedAssetRef(disabledAssetRefs);
|
|
426
|
+
} else {
|
|
427
|
+
this.dataMap.assetRefMap = AssetRefMap;
|
|
428
|
+
}
|
|
429
|
+
} catch (e) {
|
|
430
|
+
this.dataMap.assetRefMap = AssetRefMap;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
checkLatestData() {
|
|
434
|
+
clearInterval(this.refreshLatestChainDataTimeOut);
|
|
435
|
+
this.handleLatestData();
|
|
436
|
+
this.handleLatestData();
|
|
437
|
+
this.handleLatestData();
|
|
438
|
+
this.refreshLatestChainDataTimeOut = setInterval(this.handleLatestData.bind(this), LATEST_CHAIN_DATA_FETCHING_INTERVAL);
|
|
439
|
+
}
|
|
440
|
+
stopCheckLatestChainData() {
|
|
441
|
+
clearInterval(this.refreshLatestChainDataTimeOut);
|
|
409
442
|
}
|
|
443
|
+
handleLatestProviderData(latestChainInfo) {
|
|
444
|
+
try {
|
|
445
|
+
if (latestChainInfo && latestChainInfo.length > 0) {
|
|
446
|
+
const {
|
|
447
|
+
needUpdateChainApiList,
|
|
448
|
+
storedChainInfoList
|
|
449
|
+
} = updateLatestChainInfo(this.dataMap, latestChainInfo);
|
|
450
|
+
this.dbService.bulkUpdateChainStore(storedChainInfoList).catch(console.error);
|
|
451
|
+
this.updateChainSubscription();
|
|
452
|
+
needUpdateChainApiList.forEach(chainInfo => {
|
|
453
|
+
console.log('Updating chain API for', chainInfo.slug);
|
|
454
|
+
this.initApiForChain(chainInfo).catch(console.error);
|
|
455
|
+
});
|
|
456
|
+
this.logger.log('Finished updating latest RPC providers');
|
|
457
|
+
}
|
|
458
|
+
} catch (e) {
|
|
459
|
+
console.error('Error fetching latest chain data');
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
handleLatestBlockedAssetRef(latestBlockedAssetRefList) {
|
|
463
|
+
const updatedAssetRefMap = {
|
|
464
|
+
...AssetRefMap
|
|
465
|
+
};
|
|
466
|
+
latestBlockedAssetRefList.forEach(blockedAssetRef => {
|
|
467
|
+
delete updatedAssetRefMap[blockedAssetRef];
|
|
468
|
+
});
|
|
469
|
+
this.dataMap.assetRefMap = updatedAssetRefMap;
|
|
470
|
+
|
|
471
|
+
// this.dbService.setAssetRef(this.dataMap.assetRefMap).catch(console.error);
|
|
472
|
+
this.xcmRefMapSubject.next(this.dataMap.assetRefMap);
|
|
473
|
+
this.logger.log('Finished updating latest asset ref');
|
|
474
|
+
}
|
|
475
|
+
handleLatestPriceId(latestPriceIds) {
|
|
476
|
+
Object.entries(latestPriceIds).forEach(([slug, priceId]) => {
|
|
477
|
+
if (this.dataMap.assetRegistry[slug]) {
|
|
478
|
+
this.dataMap.assetRegistry[slug].priceId = priceId;
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
this.assetRegistrySubject.next(this.dataMap.assetRegistry);
|
|
482
|
+
this.eventService.emit('asset.updateState', '');
|
|
483
|
+
this.logger.log('Finished updating latest price IDs');
|
|
484
|
+
}
|
|
485
|
+
handleLatestData() {
|
|
486
|
+
this.fetchLatestChainData().then(latestChainInfo => {
|
|
487
|
+
this.handleLatestProviderData(latestChainInfo);
|
|
488
|
+
}).catch(console.error);
|
|
489
|
+
this.fetchLatestBlockedAssetRef().then(latestAssetRef => {
|
|
490
|
+
this.handleLatestBlockedAssetRef(latestAssetRef);
|
|
491
|
+
}).catch(console.error);
|
|
492
|
+
|
|
493
|
+
// this.fetchLatestPriceIdsData().then((latestPriceIds) => {
|
|
494
|
+
// this.handleLatestPriceId(latestPriceIds);
|
|
495
|
+
// }).catch(console.error);
|
|
496
|
+
}
|
|
497
|
+
|
|
410
498
|
async initApis() {
|
|
411
499
|
const chainInfoMap = this.getChainInfoMap();
|
|
412
500
|
const chainStateMap = this.getChainStateMap();
|
|
@@ -562,8 +650,8 @@ export class ChainService {
|
|
|
562
650
|
}
|
|
563
651
|
return duplicatedSlug;
|
|
564
652
|
}
|
|
565
|
-
async
|
|
566
|
-
return
|
|
653
|
+
async fetchLatestChainData() {
|
|
654
|
+
return await fetchStaticData('chains');
|
|
567
655
|
// try {
|
|
568
656
|
// const timeout = new Promise((resolve) => {
|
|
569
657
|
// const id = setTimeout(() => {
|
|
@@ -600,9 +688,16 @@ export class ChainService {
|
|
|
600
688
|
// }
|
|
601
689
|
}
|
|
602
690
|
|
|
691
|
+
// @ts-ignore
|
|
692
|
+
async fetchLatestPriceIdsData() {
|
|
693
|
+
return await fetchStaticData('chain-assets/price-map');
|
|
694
|
+
}
|
|
695
|
+
async fetchLatestBlockedAssetRef() {
|
|
696
|
+
return await fetchStaticData('chain-assets/disabled-xcm-channels');
|
|
697
|
+
}
|
|
603
698
|
async initChains() {
|
|
604
699
|
const storedChainSettings = await this.dbService.getAllChainStore();
|
|
605
|
-
const
|
|
700
|
+
const defaultChainInfoMap = ChainInfoMap;
|
|
606
701
|
const storedChainSettingMap = {};
|
|
607
702
|
storedChainSettings.forEach(chainStoredSetting => {
|
|
608
703
|
storedChainSettingMap[chainStoredSetting.slug] = chainStoredSetting;
|
|
@@ -611,10 +706,13 @@ export class ChainService {
|
|
|
611
706
|
const deprecatedChains = [];
|
|
612
707
|
const deprecatedChainMap = {};
|
|
613
708
|
if (storedChainSettings.length === 0) {
|
|
614
|
-
this.dataMap.chainInfoMap =
|
|
615
|
-
Object.values(
|
|
709
|
+
this.dataMap.chainInfoMap = defaultChainInfoMap;
|
|
710
|
+
Object.values(defaultChainInfoMap).forEach(chainInfo => {
|
|
711
|
+
const {
|
|
712
|
+
providerKey
|
|
713
|
+
} = randomizeProvider(chainInfo.providers);
|
|
616
714
|
this.dataMap.chainStateMap[chainInfo.slug] = {
|
|
617
|
-
currentProvider:
|
|
715
|
+
currentProvider: providerKey,
|
|
618
716
|
slug: chainInfo.slug,
|
|
619
717
|
connectionStatus: _ChainConnectionStatus.DISCONNECTED,
|
|
620
718
|
active: _DEFAULT_ACTIVE_CHAINS.includes(chainInfo.slug)
|
|
@@ -624,15 +722,15 @@ export class ChainService {
|
|
|
624
722
|
newStorageData.push({
|
|
625
723
|
...chainInfo,
|
|
626
724
|
active: _DEFAULT_ACTIVE_CHAINS.includes(chainInfo.slug),
|
|
627
|
-
currentProvider:
|
|
725
|
+
currentProvider: providerKey
|
|
628
726
|
});
|
|
629
727
|
});
|
|
630
728
|
} else {
|
|
631
|
-
const mergedChainInfoMap =
|
|
729
|
+
const mergedChainInfoMap = defaultChainInfoMap;
|
|
632
730
|
for (const [storedSlug, storedChainInfo] of Object.entries(storedChainSettingMap)) {
|
|
633
|
-
const chainInfo =
|
|
731
|
+
const chainInfo = defaultChainInfoMap[storedSlug];
|
|
634
732
|
|
|
635
|
-
// Network
|
|
733
|
+
// Network existed on change list
|
|
636
734
|
// check predefined chains first, keep setting for providers and currentProvider
|
|
637
735
|
if (chainInfo) {
|
|
638
736
|
// Keep customer provider only
|
|
@@ -647,23 +745,27 @@ export class ChainService {
|
|
|
647
745
|
}
|
|
648
746
|
}
|
|
649
747
|
mergedChainInfoMap[storedSlug].providers = providers;
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
}
|
|
748
|
+
const {
|
|
749
|
+
providerKey
|
|
750
|
+
} = randomizeProvider(providers);
|
|
751
|
+
let selectedProvider = providerKey;
|
|
752
|
+
const storedProviderKey = storedChainInfo.currentProvider;
|
|
753
|
+
const storedProviderValue = storedChainInfo.providers[storedProviderKey] || '';
|
|
754
|
+
if (storedProviderValue !== null && storedProviderValue !== void 0 && storedProviderValue.startsWith('light') || storedProviderKey !== null && storedProviderKey !== void 0 && storedProviderKey.startsWith(_CUSTOM_PREFIX)) {
|
|
755
|
+
const savedProviderKey = Object.keys(providers).find(key => providers[key] === storedProviderValue);
|
|
756
|
+
if (savedProviderKey) {
|
|
757
|
+
selectedProvider = savedProviderKey;
|
|
661
758
|
}
|
|
662
759
|
}
|
|
760
|
+
|
|
761
|
+
// Merge current provider
|
|
762
|
+
// let currentProvider = storedChainInfo.currentProvider;
|
|
763
|
+
// const providerValue = storedChainInfo.providers[selectedProvider] || '';
|
|
764
|
+
|
|
663
765
|
const hasProvider = Object.values(providers).length > 0;
|
|
664
766
|
const canActive = hasProvider && chainInfo.chainStatus === _ChainStatus.ACTIVE;
|
|
665
767
|
this.dataMap.chainStateMap[storedSlug] = {
|
|
666
|
-
currentProvider:
|
|
768
|
+
currentProvider: selectedProvider,
|
|
667
769
|
slug: storedSlug,
|
|
668
770
|
connectionStatus: _ChainConnectionStatus.DISCONNECTED,
|
|
669
771
|
active: canActive && storedChainInfo.active
|
|
@@ -671,13 +773,13 @@ export class ChainService {
|
|
|
671
773
|
newStorageData.push({
|
|
672
774
|
...mergedChainInfoMap[storedSlug],
|
|
673
775
|
active: canActive && storedChainInfo.active,
|
|
674
|
-
currentProvider:
|
|
776
|
+
currentProvider: selectedProvider
|
|
675
777
|
});
|
|
676
778
|
} else if (_isCustomChain(storedSlug)) {
|
|
677
779
|
var _storedChainInfo$subs, _storedChainInfo$evmI;
|
|
678
780
|
// only custom chains are left
|
|
679
781
|
// check custom chain duplicated with predefined chain => merge into predefined chain
|
|
680
|
-
const duplicatedDefaultSlug = this.checkExistedPredefinedChain(
|
|
782
|
+
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
783
|
if (duplicatedDefaultSlug.length > 0) {
|
|
682
784
|
// merge custom chain with existed chain
|
|
683
785
|
mergedChainInfoMap[duplicatedDefaultSlug].providers = {
|
|
@@ -702,6 +804,7 @@ export class ChainService {
|
|
|
702
804
|
slug: storedSlug,
|
|
703
805
|
name: storedChainInfo.name,
|
|
704
806
|
providers: storedChainInfo.providers,
|
|
807
|
+
// TODO: review
|
|
705
808
|
evmInfo: storedChainInfo.evmInfo,
|
|
706
809
|
substrateInfo: storedChainInfo.substrateInfo,
|
|
707
810
|
isTestnet: storedChainInfo.isTestnet,
|
|
@@ -711,6 +814,7 @@ export class ChainService {
|
|
|
711
814
|
};
|
|
712
815
|
this.dataMap.chainStateMap[storedSlug] = {
|
|
713
816
|
currentProvider: storedChainInfo.currentProvider,
|
|
817
|
+
// TODO: review
|
|
714
818
|
slug: storedSlug,
|
|
715
819
|
connectionStatus: _ChainConnectionStatus.DISCONNECTED,
|
|
716
820
|
active: storedChainInfo.active
|
|
@@ -718,7 +822,7 @@ export class ChainService {
|
|
|
718
822
|
newStorageData.push({
|
|
719
823
|
...mergedChainInfoMap[storedSlug],
|
|
720
824
|
active: storedChainInfo.active,
|
|
721
|
-
currentProvider: storedChainInfo.currentProvider
|
|
825
|
+
currentProvider: storedChainInfo.currentProvider // TODO: review
|
|
722
826
|
});
|
|
723
827
|
}
|
|
724
828
|
} else {
|
|
@@ -750,7 +854,7 @@ export class ChainService {
|
|
|
750
854
|
}
|
|
751
855
|
async initAssetRegistry(deprecatedCustomChainMap) {
|
|
752
856
|
const storedAssetRegistry = await this.dbService.getAllAssetStore();
|
|
753
|
-
const latestAssetRegistry =
|
|
857
|
+
const latestAssetRegistry = ChainAssetMap;
|
|
754
858
|
const availableChains = Object.values(this.dataMap.chainInfoMap).filter(info => info.chainStatus === _ChainStatus.ACTIVE).map(chainInfo => chainInfo.slug);
|
|
755
859
|
|
|
756
860
|
// Fill out zk assets from latestAssetRegistry if not supported
|
|
@@ -1200,9 +1304,11 @@ export class ChainService {
|
|
|
1200
1304
|
}
|
|
1201
1305
|
async stopAllChainApis() {
|
|
1202
1306
|
await Promise.all([this.substrateChainHandler.sleep(), this.evmChainHandler.sleep()]);
|
|
1307
|
+
this.stopCheckLatestChainData();
|
|
1203
1308
|
}
|
|
1204
1309
|
async resumeAllChainApis() {
|
|
1205
1310
|
await Promise.all([this.substrateChainHandler.wakeUp(), this.evmChainHandler.wakeUp()]);
|
|
1311
|
+
this.checkLatestData();
|
|
1206
1312
|
}
|
|
1207
1313
|
checkAndUpdateStatusMapForChain(chainSlug) {
|
|
1208
1314
|
const substrateApiMap = this.getSubstrateApiMap();
|
|
@@ -1337,10 +1443,10 @@ export class ChainService {
|
|
|
1337
1443
|
return this.assetSettingSubject;
|
|
1338
1444
|
}
|
|
1339
1445
|
async getChainLogoMap() {
|
|
1340
|
-
return
|
|
1446
|
+
return Promise.resolve(ChainLogoMap);
|
|
1341
1447
|
}
|
|
1342
1448
|
async getAssetLogoMap() {
|
|
1343
|
-
return
|
|
1449
|
+
return Promise.resolve(AssetLogoMap);
|
|
1344
1450
|
}
|
|
1345
1451
|
resetWallet(resetAll) {
|
|
1346
1452
|
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";
|