@subwallet/extension-base 1.3.63-0 → 1.3.65-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/koni/api/staking/bonding/utils.js +6 -0
- package/cjs/koni/background/handlers/State.js +1 -0
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/index.js +158 -16
- package/cjs/services/balance-service/transfer/xcm/acrossBridge/index.js +50 -4
- package/cjs/services/balance-service/transfer/xcm/index.js +7 -2
- package/cjs/services/chain-online-service/index.js +0 -3
- package/cjs/services/chain-service/index.js +6 -1
- package/cjs/services/chain-service/utils/patch.js +1 -1
- package/cjs/services/earning-service/constants/chains.js +0 -2
- package/cjs/services/earning-service/handlers/lending/interlay.js +1 -0
- package/cjs/services/earning-service/handlers/liquid-staking/acala.js +1 -1
- package/cjs/services/earning-service/handlers/liquid-staking/bifrost.js +1 -1
- package/cjs/services/earning-service/handlers/liquid-staking/parallel.js +1 -0
- package/cjs/services/earning-service/handlers/native-staking/energy.js +60 -6
- package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +1 -4
- package/cjs/services/earning-service/handlers/native-staking/tanssi.js +65 -9
- package/cjs/services/migration-service/scripts/DeleteEarningData20251105.js +21 -0
- package/cjs/services/migration-service/scripts/MigrateTransactionHistoryBySymbol20251027.js +51 -0
- package/cjs/services/migration-service/scripts/OptimizeEnableToken.js +19 -0
- package/cjs/services/migration-service/scripts/databases/MigrateAssetSetting20251027.js +37 -0
- package/cjs/services/migration-service/scripts/index.js +9 -1
- package/cjs/utils/fee/transfer.js +1 -5
- package/koni/api/staking/bonding/utils.d.ts +1 -0
- package/koni/api/staking/bonding/utils.js +5 -0
- package/koni/background/handlers/State.js +1 -0
- package/package.json +27 -7
- package/packageInfo.js +1 -1
- package/services/balance-service/index.d.ts +8 -0
- package/services/balance-service/index.js +158 -17
- package/services/balance-service/transfer/xcm/acrossBridge/index.d.ts +2 -0
- package/services/balance-service/transfer/xcm/acrossBridge/index.js +47 -2
- package/services/balance-service/transfer/xcm/index.js +7 -2
- package/services/chain-online-service/index.js +0 -3
- package/services/chain-service/index.d.ts +1 -0
- package/services/chain-service/index.js +6 -1
- package/services/chain-service/utils/patch.d.ts +1 -1
- package/services/chain-service/utils/patch.js +1 -1
- package/services/earning-service/constants/chains.js +0 -2
- package/services/earning-service/handlers/lending/interlay.js +2 -0
- package/services/earning-service/handlers/liquid-staking/acala.js +1 -1
- package/services/earning-service/handlers/liquid-staking/bifrost.js +1 -1
- package/services/earning-service/handlers/liquid-staking/parallel.js +2 -0
- package/services/earning-service/handlers/native-staking/energy.d.ts +6 -0
- package/services/earning-service/handlers/native-staking/energy.js +60 -8
- package/services/earning-service/handlers/native-staking/relay-chain.js +1 -4
- package/services/earning-service/handlers/native-staking/tanssi.js +62 -6
- package/services/migration-service/scripts/DeleteEarningData20251105.d.ts +4 -0
- package/services/migration-service/scripts/DeleteEarningData20251105.js +13 -0
- package/services/migration-service/scripts/MigrateTransactionHistoryBySymbol20251027.d.ts +4 -0
- package/services/migration-service/scripts/MigrateTransactionHistoryBySymbol20251027.js +42 -0
- package/services/migration-service/scripts/OptimizeEnableToken.d.ts +4 -0
- package/services/migration-service/scripts/OptimizeEnableToken.js +11 -0
- package/services/migration-service/scripts/databases/MigrateAssetSetting20251027.d.ts +4 -0
- package/services/migration-service/scripts/databases/MigrateAssetSetting20251027.js +29 -0
- package/services/migration-service/scripts/index.js +9 -1
- package/utils/fee/transfer.js +2 -6
- package/utils/staticData/buyTokenConfigs.json +0 -46
|
@@ -7,7 +7,7 @@ import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants';
|
|
|
7
7
|
import { _isXcmWithinSameConsensus } from '@subwallet/extension-base/core/substrate/xcm-parser';
|
|
8
8
|
import { getAcrossbridgeTransferProcessFromEvm, getDefaultTransferProcess, getSnowbridgeTransferProcessFromEvm } from '@subwallet/extension-base/services/balance-service/helpers/process';
|
|
9
9
|
import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
|
|
10
|
-
import { _getChainNativeTokenSlug, _isNativeToken, _isPureEvmChain } from '@subwallet/extension-base/services/chain-service/utils';
|
|
10
|
+
import { _getChainNativeTokenSlug, _isCustomAsset, _isNativeToken, _isPureEvmChain } from '@subwallet/extension-base/services/chain-service/utils';
|
|
11
11
|
import DetectAccountBalanceStore from '@subwallet/extension-base/stores/DetectAccountBalance';
|
|
12
12
|
import { addLazy, createPromiseHandler, isAccountAll, waitTimeout } from '@subwallet/extension-base/utils';
|
|
13
13
|
import { getKeypairTypeByAddress } from '@subwallet/keyring';
|
|
@@ -32,13 +32,14 @@ export class BalanceService {
|
|
|
32
32
|
stopPromiseHandler = createPromiseHandler();
|
|
33
33
|
status = ServiceStatus.NOT_INITIALIZED;
|
|
34
34
|
isReload = false;
|
|
35
|
+
requireOptimizeTokenList = false;
|
|
35
36
|
get isStarted() {
|
|
36
37
|
return this.status === ServiceStatus.STARTED;
|
|
37
38
|
}
|
|
38
39
|
detectAccountBalanceStore = new DetectAccountBalanceStore();
|
|
39
40
|
balanceDetectSubject = new BehaviorSubject({});
|
|
40
|
-
intervalTime = 3 * 60 * 1000;
|
|
41
|
-
cacheTime = 15 * 60 * 1000;
|
|
41
|
+
intervalTime = 3 * 60 * 1000; // scan balance every 3 mins
|
|
42
|
+
cacheTime = 15 * 60 * 1000; // cache time 15 mins to run again
|
|
42
43
|
|
|
43
44
|
/**
|
|
44
45
|
* @constructor
|
|
@@ -90,6 +91,10 @@ export class BalanceService {
|
|
|
90
91
|
this.stopPromiseHandler = createPromiseHandler();
|
|
91
92
|
this.status = ServiceStatus.STARTED;
|
|
92
93
|
this.startPromiseHandler.resolve();
|
|
94
|
+
if (this.requireOptimizeTokenList) {
|
|
95
|
+
await this.optimizeEnableTokens();
|
|
96
|
+
this.requireOptimizeTokenList = false;
|
|
97
|
+
}
|
|
93
98
|
}
|
|
94
99
|
|
|
95
100
|
/** Stop service */
|
|
@@ -447,18 +452,12 @@ export class BalanceService {
|
|
|
447
452
|
const type = getKeypairTypeByAddress(address);
|
|
448
453
|
const typeValid = [...EthereumKeypairTypes].includes(type);
|
|
449
454
|
if (typeValid) {
|
|
450
|
-
return
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
});
|
|
454
|
-
const balanceDetectionApi = subwalletApiSdk.balanceDetectionApi || Promise.resolve([]);
|
|
455
|
-
Promise.race([timeOutPromise, balanceDetectionApi.getEvmTokenBalanceSlug(address)]).then(result => resolve(result)).catch(error => {
|
|
456
|
-
console.error(error);
|
|
457
|
-
resolve(null);
|
|
458
|
-
});
|
|
455
|
+
return subwalletApiSdk.balanceDetectionApi.getSubWalletTokenBalance(address).catch(e => {
|
|
456
|
+
console.error(e);
|
|
457
|
+
return null;
|
|
459
458
|
});
|
|
460
459
|
} else {
|
|
461
|
-
return
|
|
460
|
+
return null;
|
|
462
461
|
}
|
|
463
462
|
});
|
|
464
463
|
const needEnableChains = [];
|
|
@@ -516,13 +515,13 @@ export class BalanceService {
|
|
|
516
515
|
}
|
|
517
516
|
for (const balanceData of evmBalanceDataList) {
|
|
518
517
|
if (balanceData) {
|
|
519
|
-
for (const
|
|
518
|
+
for (const tokenSlug of balanceData) {
|
|
520
519
|
var _currentAssetSettings2;
|
|
521
|
-
const chainSlug =
|
|
520
|
+
const chainSlug = tokenSlug.split('-')[0];
|
|
522
521
|
const chainState = this.state.chainService.getChainStateByKey(chainSlug);
|
|
523
|
-
const existedKey = Object.keys(assetMap).find(v => v.toLowerCase() ===
|
|
522
|
+
const existedKey = Object.keys(assetMap).find(v => v.toLowerCase() === tokenSlug.toLowerCase());
|
|
524
523
|
|
|
525
|
-
// Cancel
|
|
524
|
+
// Cancel if chain is turned off by user
|
|
526
525
|
if (chainState && chainState.manualTurnOff) {
|
|
527
526
|
continue;
|
|
528
527
|
}
|
|
@@ -628,4 +627,146 @@ export class BalanceService {
|
|
|
628
627
|
}
|
|
629
628
|
return getDefaultTransferProcess();
|
|
630
629
|
}
|
|
630
|
+
|
|
631
|
+
// only evm addresses
|
|
632
|
+
async evmDetectBalanceToken(addresses) {
|
|
633
|
+
const assetMap = this.state.chainService.getAssetRegistry();
|
|
634
|
+
const evmPromiseList = addresses.map(address => {
|
|
635
|
+
return subwalletApiSdk.balanceDetectionApi.getSubWalletTokenBalance(address).catch(e => {
|
|
636
|
+
console.error(e);
|
|
637
|
+
return null;
|
|
638
|
+
});
|
|
639
|
+
});
|
|
640
|
+
const needActiveTokens = [];
|
|
641
|
+
const evmBalanceDataList = await Promise.all(evmPromiseList);
|
|
642
|
+
for (const balanceData of evmBalanceDataList) {
|
|
643
|
+
if (balanceData) {
|
|
644
|
+
for (const tokenSlug of balanceData) {
|
|
645
|
+
const chainSlug = tokenSlug.split('-')[0];
|
|
646
|
+
const chainState = this.state.chainService.getChainStateByKey(chainSlug);
|
|
647
|
+
const existedKey = Object.keys(assetMap).find(v => v.toLowerCase() === tokenSlug.toLowerCase());
|
|
648
|
+
|
|
649
|
+
// Cancel is chain is turned off by user
|
|
650
|
+
if (chainState && chainState.manualTurnOff) {
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
if (existedKey) {
|
|
654
|
+
needActiveTokens.push(existedKey);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return needActiveTokens;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// only for substrate addresses
|
|
663
|
+
async substrateDetectBalanceToken(addresses) {
|
|
664
|
+
const assetMap = this.state.chainService.getAssetRegistry();
|
|
665
|
+
const promiseList = addresses.map(address => {
|
|
666
|
+
return this.state.subscanService.getMultiChainBalance(address).catch(e => {
|
|
667
|
+
console.error(e);
|
|
668
|
+
return null;
|
|
669
|
+
});
|
|
670
|
+
});
|
|
671
|
+
const needActiveTokens = [];
|
|
672
|
+
const balanceDataList = await Promise.all(promiseList);
|
|
673
|
+
const chainInfoMap = this.state.chainService.getChainInfoMap();
|
|
674
|
+
const detectBalanceChainSlugMap = this.state.chainService.detectBalanceChainSlugMap;
|
|
675
|
+
for (const balanceData of balanceDataList) {
|
|
676
|
+
if (balanceData) {
|
|
677
|
+
for (const balanceDatum of balanceData) {
|
|
678
|
+
const {
|
|
679
|
+
balance,
|
|
680
|
+
bonded,
|
|
681
|
+
category,
|
|
682
|
+
locked,
|
|
683
|
+
network,
|
|
684
|
+
symbol
|
|
685
|
+
} = balanceDatum;
|
|
686
|
+
const chain = detectBalanceChainSlugMap[network];
|
|
687
|
+
const chainState = this.state.chainService.getChainStateByKey(chain);
|
|
688
|
+
const chainInfo = chain ? chainInfoMap[chain] : null;
|
|
689
|
+
const balanceIsEmpty = (!balance || balance === '0') && (!locked || locked === '0') && (!bonded || bonded === '0');
|
|
690
|
+
const tokenKey = `${chain}-${category === 'native' ? 'NATIVE' : 'LOCAL'}-${symbol.toUpperCase()}`;
|
|
691
|
+
const existedKey = Object.keys(assetMap).find(v => v.toLowerCase() === tokenKey.toLowerCase());
|
|
692
|
+
|
|
693
|
+
// Cancel if chain is not supported or is testnet
|
|
694
|
+
if (!chainInfo || chainInfo.isTestnet) {
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
// Cancel is balance is 0
|
|
699
|
+
if (balanceIsEmpty) {
|
|
700
|
+
continue;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Cancel is chain is turned off by user
|
|
704
|
+
if (chainState && chainState.manualTurnOff) {
|
|
705
|
+
continue;
|
|
706
|
+
}
|
|
707
|
+
if (existedKey) {
|
|
708
|
+
needActiveTokens.push(existedKey);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
return needActiveTokens;
|
|
714
|
+
}
|
|
715
|
+
async evmDetectBalanceChain() {
|
|
716
|
+
const blockscoutChain = await subwalletApiSdk.balanceDetectionApi.getBlockscoutChainData();
|
|
717
|
+
const blockscoutChainId = Object.keys(blockscoutChain);
|
|
718
|
+
const evmDetectChain = Object.values(this.state.chainService.getChainInfoMap()).filter(info => {
|
|
719
|
+
var _info$evmInfo, _info$evmInfo2;
|
|
720
|
+
return !!((_info$evmInfo = info.evmInfo) !== null && _info$evmInfo !== void 0 && _info$evmInfo.evmChainId) && blockscoutChainId.includes((_info$evmInfo2 = info.evmInfo) === null || _info$evmInfo2 === void 0 ? void 0 : _info$evmInfo2.evmChainId.toString());
|
|
721
|
+
}).map(chainInfo => chainInfo.slug);
|
|
722
|
+
return evmDetectChain;
|
|
723
|
+
}
|
|
724
|
+
substrateDetectBalanceChain() {
|
|
725
|
+
const substrateDetectChain = Object.values(this.state.chainService.getChainInfoMap()).filter(info => {
|
|
726
|
+
var _info$extraInfo;
|
|
727
|
+
return !!info.substrateInfo && !!((_info$extraInfo = info.extraInfo) !== null && _info$extraInfo !== void 0 && _info$extraInfo.chainBalanceSlug);
|
|
728
|
+
}).map(chainInfo => chainInfo.slug);
|
|
729
|
+
return substrateDetectChain;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/** optimize token area **/
|
|
733
|
+
|
|
734
|
+
enableOptimizeTokenPromise() {
|
|
735
|
+
this.requireOptimizeTokenList = true;
|
|
736
|
+
}
|
|
737
|
+
async optimizeEnableTokens() {
|
|
738
|
+
try {
|
|
739
|
+
const assetSettings = await this.state.chainService.getAssetSettings();
|
|
740
|
+
const assetMap = this.state.chainService.getAssetRegistry();
|
|
741
|
+
const addresses = keyring.getPairs().map(account => account.address);
|
|
742
|
+
const evmAddresses = addresses.filter(address => [...EthereumKeypairTypes].includes(getKeypairTypeByAddress(address)));
|
|
743
|
+
const substrateAddresses = addresses.filter(address => [...SubstrateKeypairTypes].includes(getKeypairTypeByAddress(address)));
|
|
744
|
+
const [nonZeroBalanceEvmToken, nonZeroBalanceSubstrateToken] = await Promise.all([this.evmDetectBalanceToken(evmAddresses), this.substrateDetectBalanceToken(substrateAddresses)]);
|
|
745
|
+
const substrateDetectChain = this.substrateDetectBalanceChain();
|
|
746
|
+
const evmDetectChain = await this.evmDetectBalanceChain();
|
|
747
|
+
const updatedSettings = structuredClone(assetSettings);
|
|
748
|
+
Object.entries(assetSettings).forEach(([tokenSlug, setting]) => {
|
|
749
|
+
const isNonZeroBalanceToken = nonZeroBalanceEvmToken.includes(tokenSlug) || nonZeroBalanceSubstrateToken.includes(tokenSlug);
|
|
750
|
+
const assetInfo = assetMap[tokenSlug];
|
|
751
|
+
const isEvmDetectChain = evmDetectChain.includes(assetInfo.originChain);
|
|
752
|
+
const isSubstrateDetectChain = substrateDetectChain.includes(assetInfo.originChain);
|
|
753
|
+
if (isNonZeroBalanceToken && !setting.visible) {
|
|
754
|
+
// enable non-zero balance tokens
|
|
755
|
+
updatedSettings[tokenSlug] = {
|
|
756
|
+
visible: true
|
|
757
|
+
};
|
|
758
|
+
} else if (!isNonZeroBalanceToken && setting.visible && !_isNativeToken(assetInfo) && !_isCustomAsset(tokenSlug) && (isEvmDetectChain || isSubstrateDetectChain)) {
|
|
759
|
+
// hide tokens with zero balance that aren't native or custom
|
|
760
|
+
updatedSettings[tokenSlug] = {
|
|
761
|
+
visible: false
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
this.state.chainService.setAssetSettings(updatedSettings);
|
|
766
|
+
} catch (e) {
|
|
767
|
+
console.error(e);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/** optimize token area **/
|
|
631
772
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
|
|
1
2
|
import { CreateXcmExtrinsicProps } from '..';
|
|
2
3
|
export declare function _isAcrossChainBridge(srcChain: string, destChain: string): boolean;
|
|
3
4
|
export declare function _isAcrossTestnetBridge(srcChain: string): boolean;
|
|
@@ -13,4 +14,5 @@ interface XcmApiResponse {
|
|
|
13
14
|
metadata?: any;
|
|
14
15
|
}
|
|
15
16
|
export declare const getAcrossQuote: ({ destinationChain, destinationTokenInfo, originChain, originTokenInfo, recipient, sender, sendingValue }: CreateXcmExtrinsicProps) => Promise<XcmApiResponse>;
|
|
17
|
+
export declare const getAcrossSendingValue: (originChain: _ChainInfo, originTokenInfo: _ChainAsset, destinationChain: _ChainInfo, isTestnet: boolean) => Promise<string>;
|
|
16
18
|
export {};
|
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import { COMMON_CHAIN_SLUGS } from '@subwallet/chain-list';
|
|
5
|
+
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
5
6
|
import { _isAcrossBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser';
|
|
7
|
+
import { _getAssetDecimals, _getContractAddressOfToken, _getEvmChainId } from '@subwallet/extension-base/services/chain-service/utils';
|
|
8
|
+
import { BasicTxErrorType } from '@subwallet/extension-base/types';
|
|
6
9
|
import subwalletApiSdk from '@subwallet-monorepos/subwallet-services-sdk';
|
|
10
|
+
import BigN from 'bignumber.js';
|
|
7
11
|
// Across Bridge
|
|
8
12
|
const acrossPairsMap = new Map([[COMMON_CHAIN_SLUGS.ETHEREUM, new Set(['optimism', 'base_mainnet', 'arbitrum_one'])], ['optimism', new Set([COMMON_CHAIN_SLUGS.ETHEREUM, 'base_mainnet', 'arbitrum_one'])], ['base_mainnet', new Set([COMMON_CHAIN_SLUGS.ETHEREUM, 'optimism', 'arbitrum_one'])], ['arbitrum_one', new Set([COMMON_CHAIN_SLUGS.ETHEREUM, 'optimism', 'base_mainnet'])], [COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA, new Set(['base_sepolia', 'arbitrum_sepolia'])],
|
|
9
13
|
// TESTNET START HERE
|
|
10
|
-
['base_sepolia', new Set([COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA])], ['arbitrum_sepolia', new Set([COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA])]]);
|
|
14
|
+
['base_sepolia', new Set([COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA, 'arbitrum_sepolia'])], ['arbitrum_sepolia', new Set([COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA, 'base_sepolia'])]]);
|
|
11
15
|
export function _isAcrossChainBridge(srcChain, destChain) {
|
|
12
16
|
var _acrossPairsMap$get$h, _acrossPairsMap$get;
|
|
13
17
|
return (_acrossPairsMap$get$h = (_acrossPairsMap$get = acrossPairsMap.get(srcChain)) === null || _acrossPairsMap$get === void 0 ? void 0 : _acrossPairsMap$get.has(destChain)) !== null && _acrossPairsMap$get$h !== void 0 ? _acrossPairsMap$get$h : false;
|
|
@@ -33,7 +37,7 @@ export const getAcrossQuote = async ({
|
|
|
33
37
|
throw new Error('Sender is required');
|
|
34
38
|
}
|
|
35
39
|
try {
|
|
36
|
-
const data = await subwalletApiSdk.
|
|
40
|
+
const data = await subwalletApiSdk.bridgeApi.fetchBridgeData({
|
|
37
41
|
address: sender,
|
|
38
42
|
from: originTokenInfo.slug,
|
|
39
43
|
to: destinationTokenInfo.slug,
|
|
@@ -50,4 +54,45 @@ export const getAcrossQuote = async ({
|
|
|
50
54
|
}
|
|
51
55
|
return Promise.reject(new Error((error === null || error === void 0 ? void 0 : error.message) || 'Unable to perform this transaction at the moment. Try again later'));
|
|
52
56
|
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// TODO: update logic after add across metadata for chainlist
|
|
60
|
+
const acrossNativeTokenAddresses = {
|
|
61
|
+
mainnet: {
|
|
62
|
+
arbitrum_one: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',
|
|
63
|
+
base_mainnet: '0x4200000000000000000000000000000000000006',
|
|
64
|
+
ethereum: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
|
|
65
|
+
optimism: '0x4200000000000000000000000000000000000006'
|
|
66
|
+
},
|
|
67
|
+
testnet: {
|
|
68
|
+
arbitrum_sepolia: '0x980B62Da83eFf3D4576C647993b0c1D7faf17c73',
|
|
69
|
+
base_sepolia: '0x4200000000000000000000000000000000000006',
|
|
70
|
+
sepolia_ethereum: '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14'
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
export const getAcrossSendingValue = async (originChain, originTokenInfo, destinationChain, isTestnet) => {
|
|
74
|
+
try {
|
|
75
|
+
const originChainId = _getEvmChainId(originChain);
|
|
76
|
+
const destinationChainId = _getEvmChainId(destinationChain);
|
|
77
|
+
if (!originChainId || !destinationChainId) {
|
|
78
|
+
return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
|
|
79
|
+
}
|
|
80
|
+
const contracts = isTestnet ? acrossNativeTokenAddresses.testnet : acrossNativeTokenAddresses.mainnet;
|
|
81
|
+
const fromContract = _getContractAddressOfToken(originTokenInfo) || contracts[originTokenInfo.originChain];
|
|
82
|
+
const acrossBridgeLimit = await subwalletApiSdk.bridgeApi.getAcrossBridgeLimit(originChainId, destinationChainId, fromContract, isTestnet);
|
|
83
|
+
if (!acrossBridgeLimit.minDeposit || !acrossBridgeLimit.maxDeposit) {
|
|
84
|
+
throw new Error('Invalid Across Bridge response');
|
|
85
|
+
}
|
|
86
|
+
const min = new BigN(acrossBridgeLimit.minDeposit);
|
|
87
|
+
const max = new BigN(acrossBridgeLimit.maxDeposit);
|
|
88
|
+
// Use the midpoint between minDeposit and maxDeposit as a balanced value used for estimating gas fee more accurately
|
|
89
|
+
const sendingValue = min.plus(max).div(2).toFixed(0);
|
|
90
|
+
return sendingValue;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error('Across Bridge error:', error);
|
|
93
|
+
|
|
94
|
+
// fallback in case fetch API fail
|
|
95
|
+
const defaultSendingAmount = isTestnet ? 0.0037 : 1;
|
|
96
|
+
return new BigN(defaultSendingAmount).shiftedBy(_getAssetDecimals(originTokenInfo)).toFixed(0, BigN.ROUND_FLOOR);
|
|
97
|
+
}
|
|
53
98
|
};
|
|
@@ -181,7 +181,7 @@ export const createAcrossBridgeExtrinsic = async ({
|
|
|
181
181
|
throw new Error('Sender is required');
|
|
182
182
|
}
|
|
183
183
|
try {
|
|
184
|
-
const data = await subwalletApiSdk.
|
|
184
|
+
const data = await subwalletApiSdk.bridgeApi.fetchBridgeData({
|
|
185
185
|
address: sender,
|
|
186
186
|
from: originTokenInfo.slug,
|
|
187
187
|
to: destinationTokenInfo.slug,
|
|
@@ -204,9 +204,14 @@ export const createAcrossBridgeExtrinsic = async ({
|
|
|
204
204
|
transactionConfig.gas = gasLimit.toString();
|
|
205
205
|
return transactionConfig;
|
|
206
206
|
} catch (error) {
|
|
207
|
+
var _message, _message$toLowerCase;
|
|
207
208
|
if (error instanceof SyntaxError) {
|
|
208
209
|
return Promise.reject(new Error('Unable to perform this transaction at the moment. Try again later'));
|
|
209
210
|
}
|
|
210
|
-
|
|
211
|
+
const message = (error === null || error === void 0 ? void 0 : (_message = error.message) === null || _message === void 0 ? void 0 : (_message$toLowerCase = _message.toLowerCase) === null || _message$toLowerCase === void 0 ? void 0 : _message$toLowerCase.call(_message)) || '';
|
|
212
|
+
if (!message.includes('amount')) {
|
|
213
|
+
return Promise.reject(new Error('Unable to perform this transaction at the moment. Try again later'));
|
|
214
|
+
}
|
|
215
|
+
return Promise.reject(new Error(error === null || error === void 0 ? void 0 : error.message));
|
|
211
216
|
}
|
|
212
217
|
};
|
|
@@ -268,9 +268,6 @@ export class ChainOnlineService {
|
|
|
268
268
|
this.chainService.subscribeChainInfoMap().next(chainInfoMap);
|
|
269
269
|
this.chainService.setAssetRegistry(assetRegistry);
|
|
270
270
|
this.chainService.subscribeAssetRegistry().next(assetRegistry);
|
|
271
|
-
this.chainService.autoEnableTokens().then(() => {
|
|
272
|
-
this.eventService.emit('asset.updateState', '');
|
|
273
|
-
}).catch(console.error);
|
|
274
271
|
this.chainService.setChainStateMap(currentChainStateMap);
|
|
275
272
|
this.chainService.subscribeChainStateMap().next(currentChainStateMap);
|
|
276
273
|
this.chainService.subscribeChainStatusMap().next(currentChainStatusMap);
|
|
@@ -121,6 +121,7 @@ export declare class ChainService {
|
|
|
121
121
|
stopCheckLatestChainData(): void;
|
|
122
122
|
handleLatestChainData(latestChainInfo: _ChainInfo[]): void;
|
|
123
123
|
autoEnableTokens(): Promise<void>;
|
|
124
|
+
resetPopularTokenList(): void;
|
|
124
125
|
enablePopularTokens(): Promise<void>;
|
|
125
126
|
handleLatestLedgerGenericAllowChains(latestledgerGenericAllowChains: string[]): void;
|
|
126
127
|
handleLatestPriorityTokens(latestPriorityTokens: TokenPriorityDetails): void;
|
|
@@ -583,7 +583,6 @@ export class ChainService {
|
|
|
583
583
|
this.xcmRefMapSubject.next(this.xcmRefMap);
|
|
584
584
|
await this.initApis();
|
|
585
585
|
this.initAssetSettings();
|
|
586
|
-
await this.autoEnableTokens();
|
|
587
586
|
}
|
|
588
587
|
initAssetRefMap() {
|
|
589
588
|
this.dataMap.assetRefMap = AssetRefMap;
|
|
@@ -661,6 +660,12 @@ export class ChainService {
|
|
|
661
660
|
}
|
|
662
661
|
}
|
|
663
662
|
}
|
|
663
|
+
resetPopularTokenList() {
|
|
664
|
+
this.priorityTokensSubject.next({
|
|
665
|
+
token: {},
|
|
666
|
+
tokenGroup: {}
|
|
667
|
+
});
|
|
668
|
+
}
|
|
664
669
|
async enablePopularTokens() {
|
|
665
670
|
const assetSettings = this.assetSettingSubject.value;
|
|
666
671
|
const chainStateMap = this.getChainStateMap();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types';
|
|
2
|
-
export declare const ChainListVersion = "0.2.
|
|
2
|
+
export declare const ChainListVersion = "0.2.120";
|
|
3
3
|
export interface PatchInfo {
|
|
4
4
|
patchVersion: string;
|
|
5
5
|
appliedVersion: string;
|
|
@@ -5,7 +5,7 @@ const PRODUCTION_BRANCHES = ['master', 'webapp', 'webapp-dev'];
|
|
|
5
5
|
const branchName = process.env.BRANCH_NAME || 'subwallet-dev';
|
|
6
6
|
const fetchDomain = process.env.PATCH_CHAIN_LIST_URL || (PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'https://chain-list-assets.subwallet.app' : 'https://dev.sw-chain-list-assets.pages.dev');
|
|
7
7
|
const fetchFile = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'list.json' : 'preview.json';
|
|
8
|
-
export const ChainListVersion = '0.2.
|
|
8
|
+
export const ChainListVersion = '0.2.120'; // update this when build chain-list
|
|
9
9
|
|
|
10
10
|
// todo: move this interface to chainlist
|
|
11
11
|
|
|
@@ -32,8 +32,6 @@ export const MANTA_VALIDATOR_POINTS_PER_BLOCK = 20;
|
|
|
32
32
|
export const MANTA_MIN_DELEGATION = 500;
|
|
33
33
|
export const CHANNEL_ID = 7;
|
|
34
34
|
export const STAKING_IDENTITY_API_SLUG = {
|
|
35
|
-
// @TODO: Remove polkadot then migrate
|
|
36
|
-
polkadot: 'polkadot_people',
|
|
37
35
|
statemine: 'peopleKusama',
|
|
38
36
|
statemint: 'polkadot_people'
|
|
39
37
|
};
|
|
@@ -8,6 +8,8 @@ import { BasicTxErrorType, EarningStatus, YieldStepType } from '@subwallet/exten
|
|
|
8
8
|
import { BN, BN_TEN, BN_ZERO } from '@polkadot/util';
|
|
9
9
|
import { fakeAddress } from "../../constants/index.js";
|
|
10
10
|
import BaseLendingPoolHandler from "./base.js";
|
|
11
|
+
|
|
12
|
+
// TODO: disable earning and stake actions but keep showing existing earning positions (currently handle on UI)
|
|
11
13
|
export default class InterlayLendingPoolHandler extends BaseLendingPoolHandler {
|
|
12
14
|
altInputAsset = 'polkadot-NATIVE-DOT';
|
|
13
15
|
derivativeAssets = ['interlay-LOCAL-qDOT'];
|
|
@@ -14,7 +14,7 @@ function convertDerivativeToken(amount, exchangeRate, decimals) {
|
|
|
14
14
|
return amount.mul(new BN(exchangeRate)).div(BN_TEN.pow(new BN(decimals)));
|
|
15
15
|
}
|
|
16
16
|
export default class AcalaLiquidStakingPoolHandler extends BaseLiquidStakingPoolHandler {
|
|
17
|
-
altInputAsset = '
|
|
17
|
+
altInputAsset = 'statemint-NATIVE-DOT';
|
|
18
18
|
derivativeAssets = ['acala-LOCAL-LDOT'];
|
|
19
19
|
inputAsset = 'acala-LOCAL-DOT';
|
|
20
20
|
rewardAssets = ['acala-LOCAL-DOT'];
|
|
@@ -14,7 +14,7 @@ const STATS_URL = 'https://dapi.bifrost.io/api/site';
|
|
|
14
14
|
const BIFROST_GRAPHQL_ENDPOINT = 'https://bifrost-subsql.liebi.com/v1/graphql';
|
|
15
15
|
const BIFROST_EXCHANGE_RATE_REQUEST = 'query MyQuery{slp_polkadot_ratio(limit:1 where:{key:{_eq:"0"}} order_by:{timestamp:desc_nulls_first}){ratio key timestamp total_issuance token_pool}}';
|
|
16
16
|
export default class BifrostLiquidStakingPoolHandler extends BaseLiquidStakingPoolHandler {
|
|
17
|
-
altInputAsset = '
|
|
17
|
+
altInputAsset = 'statemint-NATIVE-DOT';
|
|
18
18
|
derivativeAssets = ['bifrost_dot-LOCAL-vDOT'];
|
|
19
19
|
inputAsset = 'bifrost_dot-LOCAL-DOT';
|
|
20
20
|
rewardAssets = ['bifrost_dot-LOCAL-DOT'];
|
|
@@ -8,6 +8,8 @@ import { fakeAddress } from '@subwallet/extension-base/services/earning-service/
|
|
|
8
8
|
import { EarningStatus, UnstakingStatus, YieldStepType } from '@subwallet/extension-base/types';
|
|
9
9
|
import { BN, BN_TEN, BN_ZERO } from '@polkadot/util';
|
|
10
10
|
import BaseLiquidStakingPoolHandler from "./base.js";
|
|
11
|
+
|
|
12
|
+
// TODO: disable earning and stake actions but keep showing existing earning positions (currently handle on UI)
|
|
11
13
|
export default class ParallelLiquidStakingPoolHandler extends BaseLiquidStakingPoolHandler {
|
|
12
14
|
altInputAsset = 'polkadot-NATIVE-DOT';
|
|
13
15
|
derivativeAssets = ['parallel-LOCAL-sDOT'];
|
|
@@ -16,6 +16,12 @@ export interface PalletEnergyStakingNominationRequestsScheduledRequest {
|
|
|
16
16
|
whenExecutable: number;
|
|
17
17
|
action: Record<PalletParachainStakingRequestType, number>;
|
|
18
18
|
}
|
|
19
|
+
export interface PalletEnergyStakingTopNominations {
|
|
20
|
+
nominations: Array<{
|
|
21
|
+
owner: string;
|
|
22
|
+
amount: string;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
19
25
|
export default class EnergyNativeStakingPoolHandler extends BaseParaNativeStakingPoolHandler {
|
|
20
26
|
subscribePoolInfo(callback: (data: YieldPoolInfo) => void): Promise<VoidFunction>;
|
|
21
27
|
parseNominatorMetadata(chainInfo: _ChainInfo, address: string, substrateApi: _SubstrateApi, nominatorState: PalletEnergyStakingNominator): Promise<Omit<YieldPositionInfo, keyof BaseYieldPositionInfo>>;
|
|
@@ -3,13 +3,16 @@
|
|
|
3
3
|
|
|
4
4
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
5
5
|
import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
6
|
-
import { getBondedValidators, getEarningStatusByNominations, isUnstakeAll } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
|
|
6
|
+
import { calculateEnergyWebCollatorReturn, getBondedValidators, getEarningStatusByNominations, isUnstakeAll } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
|
|
7
7
|
import { _EXPECTED_BLOCK_TIME, _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
|
|
8
8
|
import { parseIdentity } from '@subwallet/extension-base/services/earning-service/utils';
|
|
9
9
|
import { BasicTxErrorType, EarningStatus, UnstakingStatus } from '@subwallet/extension-base/types';
|
|
10
10
|
import { balanceFormatter, formatNumber, parseRawNumber, reformatAddress } from '@subwallet/extension-base/utils';
|
|
11
|
-
import { BN, BN_ZERO } from '@polkadot/util';
|
|
11
|
+
import { BN, BN_TEN, BN_ZERO } from '@polkadot/util';
|
|
12
12
|
import BaseParaNativeStakingPoolHandler from "./base-para.js";
|
|
13
|
+
const DEFAULT_ANNUAL_REWARD = {
|
|
14
|
+
energy_web_x: 2000000
|
|
15
|
+
};
|
|
13
16
|
export default class EnergyNativeStakingPoolHandler extends BaseParaNativeStakingPoolHandler {
|
|
14
17
|
/* Subscribe pool info */
|
|
15
18
|
|
|
@@ -53,6 +56,13 @@ export default class EnergyNativeStakingPoolHandler extends BaseParaNativeStakin
|
|
|
53
56
|
const unstakingPeriod = parseInt(unstakingDelay.toString()) * eraTime;
|
|
54
57
|
const minStake = '0';
|
|
55
58
|
const minToHuman = formatNumber(minStake.toString(), nativeToken.decimals || 0, balanceFormatter);
|
|
59
|
+
const collators = await this.getPoolTargets();
|
|
60
|
+
let maxApy = 0;
|
|
61
|
+
for (const collator of collators) {
|
|
62
|
+
if (collator.expectedReturn && collator.expectedReturn > maxApy) {
|
|
63
|
+
maxApy = collator.expectedReturn;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
56
66
|
const data = {
|
|
57
67
|
...this.baseInfo,
|
|
58
68
|
type: this.type,
|
|
@@ -76,8 +86,7 @@ export default class EnergyNativeStakingPoolHandler extends BaseParaNativeStakin
|
|
|
76
86
|
// TODO recheck
|
|
77
87
|
era,
|
|
78
88
|
eraTime,
|
|
79
|
-
totalApy:
|
|
80
|
-
// not have
|
|
89
|
+
totalApy: maxApy,
|
|
81
90
|
tvl: totalStake.toString(),
|
|
82
91
|
unstakingPeriod: unstakingPeriod
|
|
83
92
|
},
|
|
@@ -250,12 +259,21 @@ export default class EnergyNativeStakingPoolHandler extends BaseParaNativeStakin
|
|
|
250
259
|
const apiProps = await this.substrateApi.isReady;
|
|
251
260
|
const substrateIdentityApi = this.substrateIdentityApi;
|
|
252
261
|
const allCollators = [];
|
|
253
|
-
const [_allCollators, _selectedCandidates] = await Promise.all([apiProps.api.query.parachainStaking.candidateInfo.entries(),
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
262
|
+
const [_allCollators, _selectedCandidates, _eraInfo, unstakingDelay] = await Promise.all([apiProps.api.query.parachainStaking.candidateInfo.entries(), apiProps.api.query.parachainStaking.selectedCandidates(), apiProps.api.query.parachainStaking.era(), apiProps.api.query.parachainStaking.delay()]);
|
|
263
|
+
const delay = parseInt(unstakingDelay.toString()); // in era unit
|
|
264
|
+
const roundInfo = _eraInfo.toPrimitive();
|
|
265
|
+
const currentRound = roundInfo.current;
|
|
266
|
+
let defaultCommission = 0;
|
|
267
|
+
if (apiProps.api.query.parachainStaking.defaultCollatorCommission) {
|
|
268
|
+
const _defaultCommission = await apiProps.api.query.parachainStaking.defaultCollatorCommission();
|
|
269
|
+
const {
|
|
270
|
+
current
|
|
271
|
+
} = _defaultCommission.toPrimitive();
|
|
272
|
+
defaultCommission = current / 1000000000;
|
|
273
|
+
}
|
|
257
274
|
const maxNominationPerCollator = apiProps.api.consts.parachainStaking.maxTopNominationsPerCandidate.toString();
|
|
258
275
|
const selectedCollators = _selectedCandidates.toPrimitive();
|
|
276
|
+
const selectedCollatorsCount = selectedCollators.length;
|
|
259
277
|
for (const collator of _allCollators) {
|
|
260
278
|
const _collatorAddress = collator[0].toHuman();
|
|
261
279
|
const collatorAddress = _collatorAddress[0];
|
|
@@ -282,6 +300,39 @@ export default class EnergyNativeStakingPoolHandler extends BaseParaNativeStakin
|
|
|
282
300
|
});
|
|
283
301
|
}
|
|
284
302
|
}
|
|
303
|
+
const annualReward = DEFAULT_ANNUAL_REWARD[this.chain] ? new BN(DEFAULT_ANNUAL_REWARD[this.chain]).mul(BN_TEN.pow(new BN(this.nativeToken.decimals || 18))) : BN_ZERO;
|
|
304
|
+
|
|
305
|
+
// calculate expected return
|
|
306
|
+
await Promise.all(allCollators.map(async collator => {
|
|
307
|
+
if (!selectedCollators.includes(collator.address) || annualReward.lte(BN_ZERO)) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const [_topNominations, _nominationScheduledRequests] = await Promise.all([apiProps.api.query.parachainStaking.topNominations(collator.address), apiProps.api.query.parachainStaking.nominationScheduledRequests(collator.address)]);
|
|
311
|
+
const nominationScheduledRequests = _nominationScheduledRequests.toPrimitive();
|
|
312
|
+
const topNominations = _topNominations.toPrimitive();
|
|
313
|
+
const topNominationsRecord = topNominations.nominations.reduce((record, {
|
|
314
|
+
amount,
|
|
315
|
+
owner
|
|
316
|
+
}) => {
|
|
317
|
+
record[owner] = amount || '0';
|
|
318
|
+
return record;
|
|
319
|
+
}, {});
|
|
320
|
+
let bnTotalActiveStake = new BN(collator.totalStake);
|
|
321
|
+
if (nominationScheduledRequests !== null && nominationScheduledRequests !== void 0 && nominationScheduledRequests.length) {
|
|
322
|
+
const bnTotalInactiveStake = nominationScheduledRequests.reduce((partialSum, {
|
|
323
|
+
action,
|
|
324
|
+
nominator,
|
|
325
|
+
whenExecutable
|
|
326
|
+
}) => {
|
|
327
|
+
if (whenExecutable + delay - parseInt(currentRound) < 0 && action) {
|
|
328
|
+
return partialSum.add(new BN(topNominationsRecord[nominator] || Object.values(action)[0] || BN_ZERO));
|
|
329
|
+
}
|
|
330
|
+
return partialSum;
|
|
331
|
+
}, BN_ZERO);
|
|
332
|
+
bnTotalActiveStake = bnTotalActiveStake.sub(bnTotalInactiveStake);
|
|
333
|
+
}
|
|
334
|
+
collator.expectedReturn = calculateEnergyWebCollatorReturn(annualReward.toString(), defaultCommission, selectedCollatorsCount, bnTotalActiveStake.toString());
|
|
335
|
+
}));
|
|
285
336
|
const extraInfoMap = {};
|
|
286
337
|
await Promise.all(allCollators.map(async collator => {
|
|
287
338
|
const [_info, [identity, isReasonable]] = await Promise.all([apiProps.api.query.parachainStaking.candidateInfo(collator.address), parseIdentity(substrateIdentityApi, collator.address)]);
|
|
@@ -297,6 +348,7 @@ export default class EnergyNativeStakingPoolHandler extends BaseParaNativeStakin
|
|
|
297
348
|
validator.blocked = !extraInfoMap[validator.address].active;
|
|
298
349
|
validator.identity = extraInfoMap[validator.address].identity;
|
|
299
350
|
validator.isVerified = extraInfoMap[validator.address].isVerified;
|
|
351
|
+
validator.commission = defaultCommission * 100;
|
|
300
352
|
}
|
|
301
353
|
return allCollators;
|
|
302
354
|
}
|
|
@@ -60,10 +60,7 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
|
|
|
60
60
|
}
|
|
61
61
|
const unlimitedNominatorRewarded = substrateApi.api.consts.staking.maxExposurePageSize !== undefined;
|
|
62
62
|
const maxNominatorRewarded = (_substrateApi$api$con = substrateApi.api.consts.staking.maxNominatorRewardedPerValidator) === null || _substrateApi$api$con === void 0 ? void 0 : _substrateApi$api$con.toString();
|
|
63
|
-
|
|
64
|
-
// hotfix for kusama asset hub migration
|
|
65
|
-
const kahMaxNominations = '24';
|
|
66
|
-
const maxNominations = chainInfo.slug === 'statemine' ? kahMaxNominations : await getRelayMaxNominations(substrateApi, this.chain);
|
|
63
|
+
const maxNominations = await getRelayMaxNominations(substrateApi, this.chain);
|
|
67
64
|
const currentEra = _currentEra.toString();
|
|
68
65
|
const maxUnlockingChunks = substrateApi.api.consts.staking.maxUnlockingChunks.toString();
|
|
69
66
|
const unlockingEras = substrateApi.api.consts.staking.bondingDuration.toString();
|