@subwallet/extension-base 1.3.23-0 → 1.3.24-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/background/KoniTypes.d.ts +2 -2
- package/cjs/constants/environment.js +1 -1
- package/cjs/constants/index.js +21 -4
- package/cjs/core/logic-validation/transfer.js +23 -8
- package/cjs/koni/background/handlers/Extension.js +109 -89
- package/cjs/koni/background/handlers/State.js +2 -2
- package/cjs/koni/background/handlers/Tabs.js +1 -1
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/transfer/smart-contract.js +24 -3
- package/cjs/services/chain-service/index.js +11 -0
- package/cjs/services/fee-service/utils/tokenPayFee.js +151 -0
- package/cjs/services/request-service/handler/MetadataRequestHandler.js +5 -13
- package/cjs/services/request-service/index.js +2 -2
- package/cjs/services/transaction-service/index.js +8 -5
- package/cjs/utils/fee/transfer.js +47 -14
- package/constants/environment.js +1 -1
- package/constants/index.d.ts +6 -1
- package/constants/index.js +14 -1
- package/core/logic-validation/transfer.d.ts +1 -1
- package/core/logic-validation/transfer.js +25 -10
- package/koni/background/handlers/Extension.js +82 -62
- package/koni/background/handlers/State.d.ts +1 -1
- package/koni/background/handlers/State.js +2 -2
- package/koni/background/handlers/Tabs.js +1 -1
- package/package.json +11 -6
- package/packageInfo.js +1 -1
- package/services/balance-service/transfer/smart-contract.d.ts +4 -2
- package/services/balance-service/transfer/smart-contract.js +24 -3
- package/services/chain-service/index.d.ts +1 -0
- package/services/chain-service/index.js +12 -1
- package/services/fee-service/interfaces.d.ts +25 -0
- package/services/fee-service/utils/tokenPayFee.d.ts +8 -0
- package/services/fee-service/utils/tokenPayFee.js +141 -0
- package/services/request-service/handler/MetadataRequestHandler.d.ts +1 -1
- package/services/request-service/handler/MetadataRequestHandler.js +5 -13
- package/services/request-service/index.d.ts +1 -1
- package/services/request-service/index.js +2 -2
- package/services/transaction-service/index.js +10 -7
- package/types/fee/option.d.ts +1 -1
- package/utils/fee/transfer.d.ts +1 -1
- package/utils/fee/transfer.js +46 -13
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { _AssetType } from '@subwallet/chain-list/types';
|
|
5
|
+
import { _getAssetDecimals, _getAssetPriceId, _getTokenOnChainAssetId } from '@subwallet/extension-base/services/chain-service/utils';
|
|
6
|
+
import { checkLiquidityForPool, estimateTokensForPool, getReserveForPool } from '@subwallet/extension-base/services/swap-service/handler/asset-hub/utils';
|
|
7
|
+
import subwalletApiSdk from '@subwallet/subwallet-api-sdk';
|
|
8
|
+
import BigN from 'bignumber.js';
|
|
9
|
+
export async function getAssetHubTokensCanPayFee(request) {
|
|
10
|
+
const {
|
|
11
|
+
chainService,
|
|
12
|
+
feeAmount,
|
|
13
|
+
nativeBalanceInfo,
|
|
14
|
+
nativeTokenInfo,
|
|
15
|
+
substrateApi,
|
|
16
|
+
tokensHasBalanceInfoMap
|
|
17
|
+
} = request;
|
|
18
|
+
const tokensList = [nativeBalanceInfo];
|
|
19
|
+
if (!(nativeTokenInfo.metadata && nativeTokenInfo.metadata.multilocation)) {
|
|
20
|
+
return tokensList;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ensure nativeTokenInfo and localTokenInfo have multi-location metadata beforehand to improve performance.
|
|
24
|
+
const tokensHasBalanceSlug = Object.keys(tokensHasBalanceInfoMap);
|
|
25
|
+
const tokenInfos = tokensHasBalanceSlug.map(tokenSlug => chainService.getAssetBySlug(tokenSlug)).filter(token => token.originChain === substrateApi.chainSlug && token.assetType !== _AssetType.NATIVE && token.metadata && token.metadata.multilocation);
|
|
26
|
+
await Promise.all(tokenInfos.map(async tokenInfo => {
|
|
27
|
+
try {
|
|
28
|
+
const tokenSlug = tokenInfo.slug;
|
|
29
|
+
const reserve = await getReserveForPool(substrateApi.api, nativeTokenInfo, tokenInfo);
|
|
30
|
+
if (!reserve || !reserve[0] || !reserve[1] || reserve[0] === '0' || reserve[1] === '0') {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const rate = new BigN(reserve[1]).div(reserve[0]).toFixed();
|
|
34
|
+
const tokenCanPayFee = {
|
|
35
|
+
slug: tokenSlug,
|
|
36
|
+
free: tokensHasBalanceInfoMap[tokenSlug].free,
|
|
37
|
+
rate
|
|
38
|
+
};
|
|
39
|
+
if (feeAmount === undefined) {
|
|
40
|
+
tokensList.push(tokenCanPayFee);
|
|
41
|
+
} else {
|
|
42
|
+
const amount = estimateTokensForPool(feeAmount, reserve);
|
|
43
|
+
const liquidityError = checkLiquidityForPool(amount, reserve[0], reserve[1]);
|
|
44
|
+
if (!liquidityError) {
|
|
45
|
+
tokensList.push(tokenCanPayFee);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.error('error when fetching pool with token', tokenInfo.slug, e);
|
|
50
|
+
}
|
|
51
|
+
}));
|
|
52
|
+
return tokensList;
|
|
53
|
+
}
|
|
54
|
+
export async function getHydrationTokensCanPayFee(request) {
|
|
55
|
+
const {
|
|
56
|
+
address,
|
|
57
|
+
chainService,
|
|
58
|
+
nativeBalanceInfo,
|
|
59
|
+
nativeTokenInfo,
|
|
60
|
+
substrateApi,
|
|
61
|
+
tokensHasBalanceInfoMap
|
|
62
|
+
} = request;
|
|
63
|
+
const tokensList = [nativeBalanceInfo];
|
|
64
|
+
const _acceptedCurrencies = await substrateApi.api.query.multiTransactionPayment.acceptedCurrencies.entries();
|
|
65
|
+
const supportedAssetIds = _acceptedCurrencies.map(_assetId => {
|
|
66
|
+
const assetId = _assetId[0].toHuman();
|
|
67
|
+
return assetId[0].replaceAll(',', '');
|
|
68
|
+
});
|
|
69
|
+
const nativePriceId = _getAssetPriceId(nativeTokenInfo);
|
|
70
|
+
if (!nativePriceId) {
|
|
71
|
+
return tokensList;
|
|
72
|
+
}
|
|
73
|
+
const tokenInfos = Object.keys(tokensHasBalanceInfoMap).map(tokenSlug => chainService.getAssetBySlug(tokenSlug)).filter(token => token.originChain === substrateApi.chainSlug && token.assetType !== _AssetType.NATIVE && !!token.metadata && !!token.metadata.assetId);
|
|
74
|
+
await Promise.all(tokenInfos.map(async tokenInfo => {
|
|
75
|
+
const priceId = _getAssetPriceId(tokenInfo);
|
|
76
|
+
const rate = await getHydrationRate(address, nativeTokenInfo, tokenInfo);
|
|
77
|
+
if (priceId && rate) {
|
|
78
|
+
if (supportedAssetIds.includes(_getTokenOnChainAssetId(tokenInfo))) {
|
|
79
|
+
tokensList.push({
|
|
80
|
+
slug: tokenInfo.slug,
|
|
81
|
+
free: tokensHasBalanceInfoMap[tokenInfo.slug].free,
|
|
82
|
+
rate: rate.toString()
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}));
|
|
87
|
+
return tokensList;
|
|
88
|
+
}
|
|
89
|
+
export function batchExtrinsicSetFeeHydration(substrateApi, tx, feeSetting, assetId) {
|
|
90
|
+
const api = substrateApi.api;
|
|
91
|
+
const isSettingLocalFee = feeSetting && feeSetting !== 0;
|
|
92
|
+
const isAttendToSetLocalFee = assetId && assetId !== '0';
|
|
93
|
+
if (!tx) {
|
|
94
|
+
return tx;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// current native - set native
|
|
98
|
+
if (!isSettingLocalFee && !isAttendToSetLocalFee) {
|
|
99
|
+
return tx;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// current native - set local
|
|
103
|
+
if (!isSettingLocalFee && isAttendToSetLocalFee) {
|
|
104
|
+
return api.tx.utility.batchAll([api.tx.multiTransactionPayment.setCurrency(assetId), tx, api.tx.multiTransactionPayment.setCurrency('0')]);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// current local - set native
|
|
108
|
+
if (isSettingLocalFee && !isAttendToSetLocalFee) {
|
|
109
|
+
return api.tx.utility.batchAll([api.tx.multiTransactionPayment.setCurrency('0'), tx]);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// current local - set local
|
|
113
|
+
if (isSettingLocalFee && isAttendToSetLocalFee) {
|
|
114
|
+
if (assetId === feeSetting.toString()) {
|
|
115
|
+
// current local = set local
|
|
116
|
+
return api.tx.utility.batchAll([tx, api.tx.multiTransactionPayment.setCurrency('0')]);
|
|
117
|
+
} else {
|
|
118
|
+
// current local != set local
|
|
119
|
+
return api.tx.utility.batchAll([api.tx.multiTransactionPayment.setCurrency(assetId), tx, api.tx.multiTransactionPayment.setCurrency('0')]);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return tx;
|
|
123
|
+
}
|
|
124
|
+
export async function getHydrationRate(address, hdx, desToken) {
|
|
125
|
+
var _subwalletApiSdk$swap;
|
|
126
|
+
const quoteRate = await ((_subwalletApiSdk$swap = subwalletApiSdk.swapApi) === null || _subwalletApiSdk$swap === void 0 ? void 0 : _subwalletApiSdk$swap.getHydrationRate({
|
|
127
|
+
address,
|
|
128
|
+
pair: {
|
|
129
|
+
slug: `${hdx.slug}___${desToken.slug}`,
|
|
130
|
+
from: hdx.slug,
|
|
131
|
+
to: desToken.slug
|
|
132
|
+
}
|
|
133
|
+
}));
|
|
134
|
+
if (!quoteRate) {
|
|
135
|
+
return undefined;
|
|
136
|
+
} else {
|
|
137
|
+
const hdxDecimal = _getAssetDecimals(hdx);
|
|
138
|
+
const desTokenDecimal = _getAssetDecimals(desToken);
|
|
139
|
+
return new BigN(quoteRate).multipliedBy(10 ** (desTokenDecimal - hdxDecimal)).toFixed();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -14,6 +14,6 @@ export default class MetadataRequestHandler {
|
|
|
14
14
|
saveMetadata(meta: MetadataDef): void;
|
|
15
15
|
private updateIconMeta;
|
|
16
16
|
private metaComplete;
|
|
17
|
-
injectMetadata(
|
|
17
|
+
injectMetadata(request: MetadataDef): boolean;
|
|
18
18
|
resetWallet(): void;
|
|
19
19
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
|
|
4
4
|
import { extractMetadata } from '@subwallet/extension-base/services/request-service/helper';
|
|
5
5
|
import { MetadataStore } from '@subwallet/extension-base/stores';
|
|
6
|
-
import { getId } from '@subwallet/extension-base/utils/getId';
|
|
7
6
|
import { addMetadata, knownMetadata } from '@subwallet/extension-chains';
|
|
8
7
|
import { BehaviorSubject } from 'rxjs';
|
|
9
8
|
export default class MetadataRequestHandler {
|
|
@@ -43,6 +42,8 @@ export default class MetadataRequestHandler {
|
|
|
43
42
|
this.metaSubject.next(this.allMetaRequests);
|
|
44
43
|
this.#requestService.updateIconV2(shouldClose);
|
|
45
44
|
}
|
|
45
|
+
|
|
46
|
+
// @ts-ignore
|
|
46
47
|
metaComplete = (id, resolve, reject) => {
|
|
47
48
|
const complete = () => {
|
|
48
49
|
delete this.#metaRequests[id];
|
|
@@ -59,18 +60,9 @@ export default class MetadataRequestHandler {
|
|
|
59
60
|
}
|
|
60
61
|
};
|
|
61
62
|
};
|
|
62
|
-
injectMetadata(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
this.#metaRequests[id] = {
|
|
66
|
-
...this.metaComplete(id, resolve, reject),
|
|
67
|
-
id,
|
|
68
|
-
request,
|
|
69
|
-
url
|
|
70
|
-
};
|
|
71
|
-
this.updateIconMeta();
|
|
72
|
-
this.#requestService.popupOpen();
|
|
73
|
-
});
|
|
63
|
+
injectMetadata(request) {
|
|
64
|
+
this.saveMetadata(request);
|
|
65
|
+
return true;
|
|
74
66
|
}
|
|
75
67
|
resetWallet() {
|
|
76
68
|
for (const request of Object.values(this.#metaRequests)) {
|
|
@@ -22,7 +22,7 @@ export default class RequestService {
|
|
|
22
22
|
get metaSubject(): BehaviorSubject<MetadataRequest[]>;
|
|
23
23
|
get knownMetadata(): MetadataDef[];
|
|
24
24
|
get numMetaRequests(): number;
|
|
25
|
-
injectMetadata(
|
|
25
|
+
injectMetadata(request: MetadataDef): boolean;
|
|
26
26
|
getMetaRequest(id: string): MetaRequest;
|
|
27
27
|
saveMetadata(meta: MetadataDef): void;
|
|
28
28
|
get authSubjectV2(): BehaviorSubject<AuthorizeRequest[]>;
|
|
@@ -79,8 +79,8 @@ export default class RequestService {
|
|
|
79
79
|
get numMetaRequests() {
|
|
80
80
|
return this.#metadataRequestHandler.numMetaRequests;
|
|
81
81
|
}
|
|
82
|
-
injectMetadata(
|
|
83
|
-
return this.#metadataRequestHandler.injectMetadata(
|
|
82
|
+
injectMetadata(request) {
|
|
83
|
+
return this.#metadataRequestHandler.injectMetadata(request);
|
|
84
84
|
}
|
|
85
85
|
getMetaRequest(id) {
|
|
86
86
|
return this.#metadataRequestHandler.getMetaRequest(id);
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
import { EvmProviderError } from '@subwallet/extension-base/background/errors/EvmProviderError';
|
|
5
5
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
6
6
|
import { ChainType, EvmProviderErrorType, ExtrinsicStatus, ExtrinsicType, NotificationType, TransactionDirection } from '@subwallet/extension-base/background/KoniTypes';
|
|
7
|
-
import { ALL_ACCOUNT_KEY, fetchBlockedConfigObjects, fetchLastestBlockedActionsAndFeatures, getPassConfigId } from '@subwallet/extension-base/constants';
|
|
7
|
+
import { _SUPPORT_TOKEN_PAY_FEE_GROUP, ALL_ACCOUNT_KEY, fetchBlockedConfigObjects, fetchLastestBlockedActionsAndFeatures, getPassConfigId } from '@subwallet/extension-base/constants';
|
|
8
8
|
import { checkBalanceWithTransactionFee, checkSigningAccountForTransaction, checkSupportForAction, checkSupportForFeature, checkSupportForTransaction, estimateFeeForTransaction } from '@subwallet/extension-base/core/logic-validation/transfer';
|
|
9
9
|
import { cellToBase64Str, externalMessage, getTransferCellPromise } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/ton/utils';
|
|
10
|
-
import { _getAssetDecimals, _getAssetSymbol, _getChainNativeTokenBasicInfo, _getEvmChainId, _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils';
|
|
10
|
+
import { _getAssetDecimals, _getAssetSymbol, _getChainNativeTokenBasicInfo, _getEvmChainId, _isChainEvmCompatible, _isNativeTokenBySlug } from '@subwallet/extension-base/services/chain-service/utils';
|
|
11
11
|
import { EXTENSION_REQUEST_URL } from '@subwallet/extension-base/services/request-service/constants';
|
|
12
12
|
import { TRANSACTION_TIMEOUT } from '@subwallet/extension-base/services/transaction-service/constants';
|
|
13
13
|
import { parseLiquidStakingEvents, parseLiquidStakingFastUnstakeEvents, parseTransferEventLogs, parseXcmEventLogs } from '@subwallet/extension-base/services/transaction-service/event-parser';
|
|
@@ -90,8 +90,6 @@ export default class TransactionService {
|
|
|
90
90
|
checkSupportForAction(validationResponse, blockedActionsMap);
|
|
91
91
|
}
|
|
92
92
|
const transaction = transactionInput.transaction;
|
|
93
|
-
const nativeTokenInfo = this.state.chainService.getNativeTokenInfo(chain);
|
|
94
|
-
const tokenPayFeeInfo = transactionInput.nonNativeTokenPayFeeSlug ? this.chainService.getAssetBySlug(transactionInput.nonNativeTokenPayFeeSlug) : undefined;
|
|
95
93
|
|
|
96
94
|
// Check duplicated transaction
|
|
97
95
|
validationResponse.errors.push(...this.checkDuplicate(transactionInput));
|
|
@@ -117,7 +115,12 @@ export default class TransactionService {
|
|
|
117
115
|
// Estimate fee for transaction
|
|
118
116
|
const id = getId();
|
|
119
117
|
const feeInfo = await this.state.feeService.subscribeChainFee(id, chain, 'evm');
|
|
120
|
-
|
|
118
|
+
const nativeTokenInfo = this.state.chainService.getNativeTokenInfo(chain);
|
|
119
|
+
const tokenPayFeeSlug = transactionInput.tokenPayFeeSlug;
|
|
120
|
+
const isNonNativeTokenPayFee = tokenPayFeeSlug && !_isNativeTokenBySlug(tokenPayFeeSlug);
|
|
121
|
+
const nonNativeTokenPayFeeInfo = isNonNativeTokenPayFee ? this.chainService.getAssetBySlug(tokenPayFeeSlug) : undefined;
|
|
122
|
+
const priceMap = (await this.state.priceService.getPrice()).priceMap;
|
|
123
|
+
validationResponse.estimateFee = await estimateFeeForTransaction(validationResponse, transaction, chainInfo, evmApi, substrateApi, priceMap, feeInfo, nativeTokenInfo, nonNativeTokenPayFeeInfo, transactionInput.isTransferLocalTokenAndPayThatTokenAsFee);
|
|
121
124
|
const chainInfoMap = this.state.chainService.getChainInfoMap();
|
|
122
125
|
|
|
123
126
|
// Check account signing transaction
|
|
@@ -1347,15 +1350,15 @@ export default class TransactionService {
|
|
|
1347
1350
|
chain,
|
|
1348
1351
|
feeCustom,
|
|
1349
1352
|
id,
|
|
1350
|
-
nonNativeTokenPayFeeSlug,
|
|
1351
1353
|
signAfterCreate,
|
|
1352
1354
|
step,
|
|
1355
|
+
tokenPayFeeSlug,
|
|
1353
1356
|
transaction,
|
|
1354
1357
|
url
|
|
1355
1358
|
}) {
|
|
1356
1359
|
var _this$state$chainServ;
|
|
1357
1360
|
const tip = (feeCustom === null || feeCustom === void 0 ? void 0 : feeCustom.tip) || '0';
|
|
1358
|
-
const feeAssetId =
|
|
1361
|
+
const feeAssetId = tokenPayFeeSlug && !_isNativeTokenBySlug(tokenPayFeeSlug) && _SUPPORT_TOKEN_PAY_FEE_GROUP.assetHub.includes(chain) ? (_this$state$chainServ = this.state.chainService.getAssetBySlug(tokenPayFeeSlug).metadata) === null || _this$state$chainServ === void 0 ? void 0 : _this$state$chainServ.multilocation : undefined;
|
|
1359
1362
|
const emitter = new EventEmitter();
|
|
1360
1363
|
const eventData = {
|
|
1361
1364
|
id,
|
package/types/fee/option.d.ts
CHANGED
package/utils/fee/transfer.d.ts
CHANGED
|
@@ -20,4 +20,4 @@ export interface CalculateMaxTransferable extends TransactionFee {
|
|
|
20
20
|
export declare const detectTransferTxType: (srcToken: _ChainAsset, srcChain: _ChainInfo, destChain: _ChainInfo) => FeeChainType;
|
|
21
21
|
export declare const calculateMaxTransferable: (id: string, request: CalculateMaxTransferable, freeBalance: AmountData, fee: FeeInfo) => Promise<ResponseSubscribeTransfer>;
|
|
22
22
|
export declare const calculateTransferMaxTransferable: (id: string, request: CalculateMaxTransferable, freeBalance: AmountData, fee: FeeInfo) => Promise<ResponseSubscribeTransfer>;
|
|
23
|
-
export declare const
|
|
23
|
+
export declare const calculateXcmMaxTransferable: (id: string, request: CalculateMaxTransferable, freeBalance: AmountData, fee: FeeInfo) => Promise<ResponseSubscribeTransfer>;
|
package/utils/fee/transfer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
-
import { XCM_FEE_RATIO } from '@subwallet/extension-base/constants';
|
|
4
|
+
import { _SUPPORT_TOKEN_PAY_FEE_GROUP, XCM_FEE_RATIO } from '@subwallet/extension-base/constants';
|
|
5
5
|
import { _isSnowBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser';
|
|
6
6
|
import { DEFAULT_CARDANO_TTL_OFFSET } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/cardano/consts';
|
|
7
7
|
import { createCardanoTransaction } from '@subwallet/extension-base/services/balance-service/transfer/cardano-transfer';
|
|
@@ -14,6 +14,7 @@ import { _isPolygonChainBridge } from '@subwallet/extension-base/services/balanc
|
|
|
14
14
|
import { _isPosChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/posBridge';
|
|
15
15
|
import { _getContractAddressOfToken, _isChainCardanoCompatible, _isChainEvmCompatible, _isChainTonCompatible, _isLocalToken, _isNativeToken, _isPureEvmChain, _isTokenEvmSmartContract, _isTokenTransferredByCardano, _isTokenTransferredByEvm, _isTokenTransferredByTon } from '@subwallet/extension-base/services/chain-service/utils';
|
|
16
16
|
import { calculateToAmountByReservePool, FEE_COVERAGE_PERCENTAGE_SPECIAL_CASE } from '@subwallet/extension-base/services/fee-service/utils';
|
|
17
|
+
import { getHydrationRate } from '@subwallet/extension-base/services/fee-service/utils/tokenPayFee';
|
|
17
18
|
import { isCardanoTransaction, isTonTransaction } from '@subwallet/extension-base/services/transaction-service/helpers';
|
|
18
19
|
import { BN_ZERO } from '@subwallet/extension-base/utils';
|
|
19
20
|
import { isCardanoAddress, isTonAddress } from '@subwallet/keyring';
|
|
@@ -49,7 +50,13 @@ export const calculateMaxTransferable = async (id, request, freeBalance, fee) =>
|
|
|
49
50
|
const isXcmTransfer = srcChain.slug !== destChain.slug;
|
|
50
51
|
let maxTransferableAmount;
|
|
51
52
|
if (isXcmTransfer) {
|
|
52
|
-
|
|
53
|
+
const _request = {
|
|
54
|
+
// todo: temp not support pay local fee with xcm
|
|
55
|
+
...request,
|
|
56
|
+
isTransferLocalTokenAndPayThatTokenAsFee: false,
|
|
57
|
+
isTransferNativeTokenAndPayLocalTokenAsFee: false
|
|
58
|
+
};
|
|
59
|
+
maxTransferableAmount = await calculateXcmMaxTransferable(id, _request, freeBalance, fee);
|
|
53
60
|
} else {
|
|
54
61
|
maxTransferableAmount = await calculateTransferMaxTransferable(id, request, freeBalance, fee);
|
|
55
62
|
}
|
|
@@ -88,7 +95,7 @@ export const calculateTransferMaxTransferable = async (id, request, freeBalance,
|
|
|
88
95
|
// todo: refactor: merge getERC20TransactionObject & getEVMTransactionObject
|
|
89
96
|
// Estimate with EVM API
|
|
90
97
|
if (_isTokenEvmSmartContract(srcToken) || _isLocalToken(srcToken)) {
|
|
91
|
-
[transaction] = await getERC20TransactionObject({
|
|
98
|
+
[transaction,, error] = await getERC20TransactionObject({
|
|
92
99
|
assetAddress: _getContractAddressOfToken(srcToken),
|
|
93
100
|
chain: srcChain.slug,
|
|
94
101
|
evmApi,
|
|
@@ -98,10 +105,11 @@ export const calculateTransferMaxTransferable = async (id, request, freeBalance,
|
|
|
98
105
|
from: address,
|
|
99
106
|
to: recipient,
|
|
100
107
|
transferAll: false,
|
|
101
|
-
value: '0'
|
|
108
|
+
value: '0',
|
|
109
|
+
fallbackFee: true
|
|
102
110
|
});
|
|
103
111
|
} else {
|
|
104
|
-
[transaction] = await getEVMTransactionObject({
|
|
112
|
+
[transaction,, error] = await getEVMTransactionObject({
|
|
105
113
|
chain: srcChain.slug,
|
|
106
114
|
evmApi,
|
|
107
115
|
feeCustom,
|
|
@@ -110,7 +118,8 @@ export const calculateTransferMaxTransferable = async (id, request, freeBalance,
|
|
|
110
118
|
from: address,
|
|
111
119
|
to: recipient,
|
|
112
120
|
transferAll: false,
|
|
113
|
-
value: '0'
|
|
121
|
+
value: '0',
|
|
122
|
+
fallbackFee: true
|
|
114
123
|
});
|
|
115
124
|
}
|
|
116
125
|
} else if (isTonAddress(address) && _isTokenTransferredByTon(srcToken)) {
|
|
@@ -231,9 +240,21 @@ export const calculateTransferMaxTransferable = async (id, request, freeBalance,
|
|
|
231
240
|
console.warn('Unable to estimate fee', e);
|
|
232
241
|
}
|
|
233
242
|
if (isTransferLocalTokenAndPayThatTokenAsFee && feeChainType === 'substrate') {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
243
|
+
if (_SUPPORT_TOKEN_PAY_FEE_GROUP.assetHub.includes(srcChain.slug)) {
|
|
244
|
+
const estimatedFeeNative = (BigInt(estimatedFee) * BigInt(FEE_COVERAGE_PERCENTAGE_SPECIAL_CASE) / BigInt(100)).toString();
|
|
245
|
+
const estimatedFeeLocal = await calculateToAmountByReservePool(substrateApi.api, nativeToken, srcToken, estimatedFeeNative);
|
|
246
|
+
maxTransferable = BigN(freeBalance.value).minus(estimatedFeeLocal);
|
|
247
|
+
} else if (_SUPPORT_TOKEN_PAY_FEE_GROUP.hydration.includes(srcChain.slug)) {
|
|
248
|
+
const rate = await getHydrationRate(address, nativeToken, srcToken);
|
|
249
|
+
if (rate) {
|
|
250
|
+
const estimatedFeeLocal = new BigN(estimatedFee).multipliedBy(rate).integerValue(BigN.ROUND_UP).toString();
|
|
251
|
+
maxTransferable = BigN(freeBalance.value).minus(estimatedFeeLocal);
|
|
252
|
+
} else {
|
|
253
|
+
throw new Error(`Unable to estimate fee for ${srcChain.slug}.`);
|
|
254
|
+
}
|
|
255
|
+
} else {
|
|
256
|
+
throw new Error(`Unable to estimate fee for ${srcChain.slug}.`);
|
|
257
|
+
}
|
|
237
258
|
} else if (isTransferNativeTokenAndPayLocalTokenAsFee) {
|
|
238
259
|
maxTransferable = BigN(freeBalance.value);
|
|
239
260
|
} else {
|
|
@@ -251,7 +272,7 @@ export const calculateTransferMaxTransferable = async (id, request, freeBalance,
|
|
|
251
272
|
error
|
|
252
273
|
};
|
|
253
274
|
};
|
|
254
|
-
export const
|
|
275
|
+
export const calculateXcmMaxTransferable = async (id, request, freeBalance, fee) => {
|
|
255
276
|
const {
|
|
256
277
|
address,
|
|
257
278
|
destChain,
|
|
@@ -374,9 +395,21 @@ export const calculateXCMMaxTransferable = async (id, request, freeBalance, fee)
|
|
|
374
395
|
if (!destToken) {
|
|
375
396
|
maxTransferable = BN_ZERO;
|
|
376
397
|
} else if (isTransferLocalTokenAndPayThatTokenAsFee && feeChainType === 'substrate') {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
398
|
+
if (_SUPPORT_TOKEN_PAY_FEE_GROUP.assetHub.includes(srcChain.slug)) {
|
|
399
|
+
const estimatedFeeNative = (BigInt(estimatedFee) * BigInt(FEE_COVERAGE_PERCENTAGE_SPECIAL_CASE) / BigInt(100)).toString();
|
|
400
|
+
const estimatedFeeLocal = await calculateToAmountByReservePool(substrateApi.api, nativeToken, srcToken, estimatedFeeNative);
|
|
401
|
+
maxTransferable = BigN(freeBalance.value).minus(estimatedFeeLocal);
|
|
402
|
+
} else if (_SUPPORT_TOKEN_PAY_FEE_GROUP.hydration.includes(srcChain.slug)) {
|
|
403
|
+
const rate = await getHydrationRate(address, nativeToken, srcToken);
|
|
404
|
+
if (rate) {
|
|
405
|
+
const estimatedFeeLocal = new BigN(estimatedFee).multipliedBy(rate).integerValue(BigN.ROUND_UP).toString();
|
|
406
|
+
maxTransferable = BigN(freeBalance.value).minus(estimatedFeeLocal);
|
|
407
|
+
} else {
|
|
408
|
+
throw new Error(`Unable to estimate fee for ${srcChain.slug}.`);
|
|
409
|
+
}
|
|
410
|
+
} else {
|
|
411
|
+
throw new Error(`Unable to estimate fee for ${srcChain.slug}.`);
|
|
412
|
+
}
|
|
380
413
|
} else if (isTransferNativeTokenAndPayLocalTokenAsFee) {
|
|
381
414
|
maxTransferable = BigN(freeBalance.value);
|
|
382
415
|
} else {
|