@subwallet/extension-base 1.3.62-0 → 1.3.64-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/packageInfo.js +1 -1
- package/cjs/services/balance-service/transfer/smart-contract.js +14 -10
- package/cjs/services/balance-service/transfer/xcm/acrossBridge/index.js +0 -6
- package/cjs/services/balance-service/transfer/xcm/utils.js +2 -0
- package/cjs/services/chain-service/constants.js +16 -0
- package/cjs/services/chain-service/utils/index.js +24 -4
- package/cjs/services/chain-service/utils/patch.js +1 -1
- package/cjs/services/earning-service/constants/chains.js +2 -1
- package/cjs/services/earning-service/handlers/native-staking/base-para.js +6 -3
- package/cjs/services/earning-service/handlers/native-staking/energy.js +60 -6
- package/cjs/services/earning-service/handlers/native-staking/tanssi.js +496 -0
- package/cjs/services/earning-service/service.js +4 -0
- package/cjs/services/earning-service/utils/index.js +2 -0
- package/cjs/services/migration-service/scripts/MigrateTransactionHistoryBySymbol20251027.js +51 -0
- package/cjs/services/migration-service/scripts/databases/MigrateAssetSetting20251027.js +37 -0
- package/cjs/services/migration-service/scripts/index.js +5 -1
- package/cjs/services/swap-service/handler/base-handler.js +4 -1
- package/cjs/services/swap-service/handler/chainflip-handler.js +1 -17
- package/cjs/services/swap-service/handler/optimex-handler.js +421 -0
- package/cjs/services/swap-service/handler/simpleswap-handler.js +4 -2
- package/cjs/services/swap-service/index.js +38 -140
- package/cjs/services/swap-service/utils.js +16 -157
- package/cjs/services/transaction-service/helpers/index.js +2 -1
- package/cjs/types/service-base.js +0 -1
- package/cjs/types/swap/index.js +5 -8
- package/cjs/utils/account/common.js +1 -2
- package/koni/api/staking/bonding/utils.d.ts +1 -0
- package/koni/api/staking/bonding/utils.js +5 -0
- package/package.json +26 -6
- package/packageInfo.js +1 -1
- package/services/balance-service/transfer/smart-contract.d.ts +3 -2
- package/services/balance-service/transfer/smart-contract.js +35 -29
- package/services/balance-service/transfer/xcm/acrossBridge/index.d.ts +0 -4
- package/services/balance-service/transfer/xcm/acrossBridge/index.js +0 -4
- package/services/balance-service/transfer/xcm/utils.js +2 -0
- package/services/chain-service/constants.js +16 -0
- package/services/chain-service/utils/index.d.ts +3 -2
- package/services/chain-service/utils/index.js +20 -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.d.ts +1 -0
- package/services/earning-service/constants/chains.js +2 -1
- package/services/earning-service/handlers/native-staking/base-para.js +6 -3
- 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/tanssi.d.ts +16 -0
- package/services/earning-service/handlers/native-staking/tanssi.js +478 -0
- package/services/earning-service/service.js +4 -0
- package/services/earning-service/utils/index.js +2 -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/databases/MigrateAssetSetting20251027.d.ts +4 -0
- package/services/migration-service/scripts/databases/MigrateAssetSetting20251027.js +29 -0
- package/services/migration-service/scripts/index.js +5 -1
- package/services/swap-service/handler/base-handler.js +6 -3
- package/services/swap-service/handler/chainflip-handler.d.ts +0 -2
- package/services/swap-service/handler/chainflip-handler.js +2 -18
- package/services/swap-service/handler/optimex-handler.d.ts +43 -0
- package/services/swap-service/handler/optimex-handler.js +410 -0
- package/services/swap-service/handler/simpleswap-handler.js +5 -3
- package/services/swap-service/index.d.ts +0 -1
- package/services/swap-service/index.js +21 -123
- package/services/swap-service/utils.d.ts +6 -12
- package/services/swap-service/utils.js +8 -138
- package/services/transaction-service/helpers/index.js +2 -1
- package/types/service-base.d.ts +3 -4
- package/types/service-base.js +0 -2
- package/types/swap/index.d.ts +3 -1
- package/types/swap/index.js +7 -6
- package/types/yield/info/account/info.d.ts +5 -0
- package/utils/account/common.js +2 -3
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
-
import { COMMON_ASSETS } from '@subwallet/chain-list';
|
|
5
4
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
6
5
|
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
7
6
|
import { createBitcoinTransaction } from '@subwallet/extension-base/services/balance-service/transfer/bitcoin-transfer';
|
|
8
7
|
import { getERC20TransactionObject, getEVMTransactionObject } from '@subwallet/extension-base/services/balance-service/transfer/smart-contract';
|
|
9
8
|
import { createSubstrateExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/token';
|
|
10
|
-
import {
|
|
9
|
+
import { _chainInfoToChainType, _getContractAddressOfToken, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
|
|
11
10
|
import { SwapBaseHandler } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
|
|
12
11
|
import { BasicTxErrorType, CommonStepType, DynamicSwapType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
|
|
13
12
|
import { ProxyServiceRoute } from '@subwallet/extension-base/types/environment';
|
|
@@ -15,12 +14,7 @@ import { _reformatAddressWithChain, fetchFromProxyService } from '@subwallet/ext
|
|
|
15
14
|
import { getId } from '@subwallet/extension-base/utils/getId';
|
|
16
15
|
import BigNumber from 'bignumber.js';
|
|
17
16
|
import * as bitcoin from 'bitcoinjs-lib';
|
|
18
|
-
const INTERMEDIARY_MAINNET_ASSET_SLUG = COMMON_ASSETS.USDC_ETHEREUM;
|
|
19
|
-
const INTERMEDIARY_TESTNET_ASSET_SLUG = COMMON_ASSETS.USDC_SEPOLIA;
|
|
20
17
|
export class ChainflipSwapHandler {
|
|
21
|
-
// private baseUrl: string;
|
|
22
|
-
// private assetsUrl: string;
|
|
23
|
-
|
|
24
18
|
constructor(chainService, balanceService, feeService, isTestnet = true) {
|
|
25
19
|
this.swapBaseHandler = new SwapBaseHandler({
|
|
26
20
|
chainService,
|
|
@@ -31,10 +25,7 @@ export class ChainflipSwapHandler {
|
|
|
31
25
|
});
|
|
32
26
|
this.isTestnet = isTestnet;
|
|
33
27
|
this.providerSlug = isTestnet ? SwapProviderId.CHAIN_FLIP_TESTNET : SwapProviderId.CHAIN_FLIP_MAINNET;
|
|
34
|
-
// this.baseUrl = getChainflipSwap(isTestnet);
|
|
35
|
-
// this.assetsUrl = getAssetsUrl(isTestnet);
|
|
36
28
|
}
|
|
37
|
-
|
|
38
29
|
get chainService() {
|
|
39
30
|
return this.swapBaseHandler.chainService;
|
|
40
31
|
}
|
|
@@ -50,13 +41,6 @@ export class ChainflipSwapHandler {
|
|
|
50
41
|
get slug() {
|
|
51
42
|
return this.swapBaseHandler.slug;
|
|
52
43
|
}
|
|
53
|
-
get intermediaryAssetSlug() {
|
|
54
|
-
if (this.isTestnet) {
|
|
55
|
-
return INTERMEDIARY_TESTNET_ASSET_SLUG;
|
|
56
|
-
} else {
|
|
57
|
-
return INTERMEDIARY_MAINNET_ASSET_SLUG;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
44
|
async handleSubmitStep(params) {
|
|
61
45
|
const {
|
|
62
46
|
address,
|
|
@@ -70,7 +54,7 @@ export class ChainflipSwapHandler {
|
|
|
70
54
|
const fromAsset = this.chainService.getAssetBySlug(pair.from);
|
|
71
55
|
const chainInfo = this.chainService.getChainInfoByKey(fromAsset.originChain);
|
|
72
56
|
const toChainInfo = this.chainService.getChainInfoByKey(fromAsset.originChain);
|
|
73
|
-
const chainType =
|
|
57
|
+
const chainType = _chainInfoToChainType(chainInfo);
|
|
74
58
|
const receiver = _reformatAddressWithChain(recipient !== null && recipient !== void 0 ? recipient : address, toChainInfo);
|
|
75
59
|
const minReceive = new BigNumber(quote.rate).times(1 - slippage).toString();
|
|
76
60
|
const processMetadata = process.steps[currentStep].metadata;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
2
|
+
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
3
|
+
import { BalanceService } from '@subwallet/extension-base/services/balance-service';
|
|
4
|
+
import { ChainService } from '@subwallet/extension-base/services/chain-service';
|
|
5
|
+
import FeeService from '@subwallet/extension-base/services/fee-service/service';
|
|
6
|
+
import { SwapBaseInterface } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
|
|
7
|
+
import { BaseStepDetail, CommonOptimalSwapPath, CommonStepFeeInfo, OptimalSwapPathParamsV2, SwapProviderId, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types';
|
|
8
|
+
interface OptimexTradeMetadata {
|
|
9
|
+
trade_id: string;
|
|
10
|
+
deposit_address: string;
|
|
11
|
+
payload: string;
|
|
12
|
+
need_approve: boolean;
|
|
13
|
+
approve_address: string;
|
|
14
|
+
approve_payload: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class OptimexHandler implements SwapBaseInterface {
|
|
17
|
+
private readonly baseUrl;
|
|
18
|
+
private currentTradeMetadata;
|
|
19
|
+
private swapBaseHandler;
|
|
20
|
+
private isTestnet;
|
|
21
|
+
providerSlug: SwapProviderId;
|
|
22
|
+
constructor(chainService: ChainService, balanceService: BalanceService, feeService: FeeService, isTestnet?: boolean);
|
|
23
|
+
get chainService(): ChainService;
|
|
24
|
+
get providerInfo(): import("@subwallet/extension-base/types").SwapProvider;
|
|
25
|
+
get name(): string;
|
|
26
|
+
get slug(): string;
|
|
27
|
+
generateOptimalProcessV2(params: OptimalSwapPathParamsV2): Promise<CommonOptimalSwapPath>;
|
|
28
|
+
initTrade(request: OptimalSwapPathParamsV2): Promise<OptimexTradeMetadata | undefined>;
|
|
29
|
+
getApprovalStep(params: OptimalSwapPathParamsV2): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
|
|
30
|
+
getSubmitStep(params: OptimalSwapPathParamsV2, stepIndex: number): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
|
|
31
|
+
validateSwapProcessV2(params: ValidateSwapProcessParams): Promise<TransactionError[]>;
|
|
32
|
+
handleSwapProcess(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
|
|
33
|
+
handleApproveStep(params: SwapSubmitParams): {
|
|
34
|
+
txChain: string;
|
|
35
|
+
txData: string;
|
|
36
|
+
extrinsic: {};
|
|
37
|
+
extrinsicType: ExtrinsicType;
|
|
38
|
+
transferNativeAmount: string;
|
|
39
|
+
chainType: ChainType;
|
|
40
|
+
};
|
|
41
|
+
handleSubmitStep(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
|
|
42
|
+
}
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
5
|
+
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
6
|
+
import { estimateTxFee } from '@subwallet/extension-base/koni/api/contract-handler/evm/web3';
|
|
7
|
+
import { createBitcoinTransaction } from '@subwallet/extension-base/services/balance-service/transfer/bitcoin-transfer';
|
|
8
|
+
import { getERC20TransactionObject, getEVMTransactionObject } from '@subwallet/extension-base/services/balance-service/transfer/smart-contract';
|
|
9
|
+
import { _chainInfoToChainType, _getChainNativeTokenSlug, _getContractAddressOfToken, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
|
|
10
|
+
import { SwapBaseHandler } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
|
|
11
|
+
import { getAmountAfterSlippage } from '@subwallet/extension-base/services/swap-service/utils';
|
|
12
|
+
import { BasicTxErrorType, CommonStepType, DynamicSwapType, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
|
|
13
|
+
import { _reformatAddressWithChain, combineBitcoinFee, getSizeInfo } from '@subwallet/extension-base/utils';
|
|
14
|
+
import { getId } from '@subwallet/extension-base/utils/getId';
|
|
15
|
+
import keyring from '@subwallet/ui-keyring';
|
|
16
|
+
import BigNumber from 'bignumber.js';
|
|
17
|
+
import * as bitcoin from 'bitcoinjs-lib';
|
|
18
|
+
import { hexStripPrefix, u8aToHex } from '@polkadot/util';
|
|
19
|
+
const OptimexBaseUrl = {
|
|
20
|
+
mainnet: 'https://subwallet-provider.optimex.xyz',
|
|
21
|
+
testnet: 'https://provider-stg.bitdex.xyz'
|
|
22
|
+
};
|
|
23
|
+
export class OptimexHandler {
|
|
24
|
+
constructor(chainService, balanceService, feeService, isTestnet = true) {
|
|
25
|
+
this.swapBaseHandler = new SwapBaseHandler({
|
|
26
|
+
chainService,
|
|
27
|
+
balanceService,
|
|
28
|
+
feeService,
|
|
29
|
+
providerName: isTestnet ? 'Optimex Testnet' : 'Optimex',
|
|
30
|
+
providerSlug: isTestnet ? SwapProviderId.OPTIMEX_TESTNET : SwapProviderId.OPTIMEX
|
|
31
|
+
});
|
|
32
|
+
this.providerSlug = isTestnet ? SwapProviderId.OPTIMEX_TESTNET : SwapProviderId.OPTIMEX;
|
|
33
|
+
this.baseUrl = isTestnet ? OptimexBaseUrl.testnet : OptimexBaseUrl.mainnet;
|
|
34
|
+
this.isTestnet = isTestnet;
|
|
35
|
+
}
|
|
36
|
+
get chainService() {
|
|
37
|
+
return this.swapBaseHandler.chainService;
|
|
38
|
+
}
|
|
39
|
+
get providerInfo() {
|
|
40
|
+
return this.swapBaseHandler.providerInfo;
|
|
41
|
+
}
|
|
42
|
+
get name() {
|
|
43
|
+
return this.swapBaseHandler.name;
|
|
44
|
+
}
|
|
45
|
+
get slug() {
|
|
46
|
+
return this.swapBaseHandler.slug;
|
|
47
|
+
}
|
|
48
|
+
async generateOptimalProcessV2(params) {
|
|
49
|
+
const tradeMetadata = await this.initTrade(params);
|
|
50
|
+
if (!tradeMetadata) {
|
|
51
|
+
throw new Error('Error generating optimal process: Cannot init Optimex trade');
|
|
52
|
+
}
|
|
53
|
+
const isNeedApprove = tradeMetadata.need_approve;
|
|
54
|
+
this.currentTradeMetadata = tradeMetadata;
|
|
55
|
+
if (!isNeedApprove) {
|
|
56
|
+
return this.swapBaseHandler.generateOptimalProcessV2(params, [this.getSubmitStep.bind(this)]);
|
|
57
|
+
}
|
|
58
|
+
if (!tradeMetadata.approve_address || !tradeMetadata.approve_payload) {
|
|
59
|
+
throw new Error('Error generating optimal process: Lack of approve info');
|
|
60
|
+
}
|
|
61
|
+
return this.swapBaseHandler.generateOptimalProcessV2(params, [this.getApprovalStep.bind(this), this.getSubmitStep.bind(this)]);
|
|
62
|
+
}
|
|
63
|
+
async initTrade(request) {
|
|
64
|
+
var _request$selectedQuot, _request$selectedQuot2;
|
|
65
|
+
const pair = request.request.pair;
|
|
66
|
+
const fromAsset = this.chainService.getAssetBySlug(pair.from);
|
|
67
|
+
const fromChain = this.chainService.getChainInfoByKey(fromAsset.originChain);
|
|
68
|
+
const fromChainType = _chainInfoToChainType(fromChain);
|
|
69
|
+
const sender = request.request.address;
|
|
70
|
+
const receiver = request.request.recipient;
|
|
71
|
+
const sendingValue = request.request.fromAmount;
|
|
72
|
+
const slippage = request.request.slippage;
|
|
73
|
+
const metadata = (_request$selectedQuot = request.selectedQuote) === null || _request$selectedQuot === void 0 ? void 0 : _request$selectedQuot.metadata;
|
|
74
|
+
const walletFeeInfo = (_request$selectedQuot2 = request.selectedQuote) === null || _request$selectedQuot2 === void 0 ? void 0 : _request$selectedQuot2.feeInfo.feeComponent.find(fee => fee.feeType === SwapFeeType.WALLET_FEE);
|
|
75
|
+
if (!metadata || !walletFeeInfo) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
let initTradeRequest;
|
|
79
|
+
const swAffiliate = walletFeeInfo.metadata;
|
|
80
|
+
if (fromChainType === ChainType.EVM) {
|
|
81
|
+
initTradeRequest = {
|
|
82
|
+
session_id: metadata.session_id,
|
|
83
|
+
amount_in: sendingValue,
|
|
84
|
+
from_user_address: sender,
|
|
85
|
+
// compressPublicKey for BTC and SOLANA, address for EVM
|
|
86
|
+
to_user_address: receiver || '',
|
|
87
|
+
// Receiving address
|
|
88
|
+
user_refund_address: sender,
|
|
89
|
+
// Refund address if trade fails
|
|
90
|
+
user_refund_pubkey: sender,
|
|
91
|
+
// Refund pubkey if trade fails, in btc is pubkey and in evm is address
|
|
92
|
+
creator_public_key: sender,
|
|
93
|
+
// Compressed public key, in btc is pubkey and in evm is address
|
|
94
|
+
from_wallet_address: sender,
|
|
95
|
+
// Creator address
|
|
96
|
+
min_amount_out: getAmountAfterSlippage(metadata.best_quote_after_fees, slippage),
|
|
97
|
+
affiliate_info: [swAffiliate]
|
|
98
|
+
};
|
|
99
|
+
} else if (fromChainType === ChainType.BITCOIN) {
|
|
100
|
+
const fromPublicKey = hexStripPrefix(u8aToHex(keyring.getPair(sender).publicKey));
|
|
101
|
+
initTradeRequest = {
|
|
102
|
+
session_id: metadata.session_id,
|
|
103
|
+
amount_in: sendingValue,
|
|
104
|
+
from_user_address: fromPublicKey,
|
|
105
|
+
to_user_address: receiver || '',
|
|
106
|
+
user_refund_address: sender,
|
|
107
|
+
user_refund_pubkey: fromPublicKey,
|
|
108
|
+
creator_public_key: fromPublicKey,
|
|
109
|
+
from_wallet_address: sender,
|
|
110
|
+
min_amount_out: getAmountAfterSlippage(metadata.best_quote_after_fees, slippage),
|
|
111
|
+
affiliate_info: [swAffiliate]
|
|
112
|
+
};
|
|
113
|
+
} else {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
let tradeInfo;
|
|
117
|
+
try {
|
|
118
|
+
const rawResponse = await fetch(`${this.baseUrl}/v1/trades/initiate`, {
|
|
119
|
+
method: 'POST',
|
|
120
|
+
body: JSON.stringify(initTradeRequest),
|
|
121
|
+
headers: {
|
|
122
|
+
'Content-Type': 'application/json'
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
if (!rawResponse.ok) {
|
|
126
|
+
console.log('Error bad request while init quote');
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
const response = await rawResponse.json();
|
|
130
|
+
tradeInfo = response.data;
|
|
131
|
+
} catch (e) {
|
|
132
|
+
console.log('Error while init quote');
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
return tradeInfo;
|
|
136
|
+
}
|
|
137
|
+
async getApprovalStep(params) {
|
|
138
|
+
// todo: handle this when support route has approve step
|
|
139
|
+
// const selectedQuote = params.selectedQuote;
|
|
140
|
+
//
|
|
141
|
+
// if (selectedQuote) {
|
|
142
|
+
// const metadata = selectedQuote.metadata as OptimexMetadata;
|
|
143
|
+
// }
|
|
144
|
+
|
|
145
|
+
return Promise.resolve(undefined);
|
|
146
|
+
}
|
|
147
|
+
async getSubmitStep(params, stepIndex) {
|
|
148
|
+
var _this$currentTradeMet;
|
|
149
|
+
if (!params.selectedQuote) {
|
|
150
|
+
return Promise.resolve(undefined);
|
|
151
|
+
}
|
|
152
|
+
const originTokenInfo = this.chainService.getAssetBySlug(params.selectedQuote.pair.from);
|
|
153
|
+
const originChain = this.chainService.getChainInfoByKey(originTokenInfo.originChain);
|
|
154
|
+
const destinationTokenInfo = this.chainService.getAssetBySlug(params.selectedQuote.pair.to);
|
|
155
|
+
const destinationChain = this.chainService.getChainInfoByKey(destinationTokenInfo.originChain);
|
|
156
|
+
const originChainType = _chainInfoToChainType(originChain);
|
|
157
|
+
const originChainNativeTokenSlug = _getChainNativeTokenSlug(originChain);
|
|
158
|
+
|
|
159
|
+
// Optimex do not return fee in quote. Need calculate network fee manually from client side
|
|
160
|
+
let networkFeeAmount;
|
|
161
|
+
const depositAddress = (_this$currentTradeMet = this.currentTradeMetadata) === null || _this$currentTradeMet === void 0 ? void 0 : _this$currentTradeMet.deposit_address;
|
|
162
|
+
if (!depositAddress) {
|
|
163
|
+
console.log('Optimex Trade metadata is undefined, request for new quote');
|
|
164
|
+
return Promise.resolve(undefined);
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
if (originChainType === ChainType.EVM) {
|
|
168
|
+
const evmApi = this.chainService.getEvmApi(originChain.slug);
|
|
169
|
+
const feeInfo = await this.swapBaseHandler.feeService.subscribeChainFee(getId(), originChain.slug, 'evm');
|
|
170
|
+
let transactionConfig;
|
|
171
|
+
if (_isNativeToken(originTokenInfo)) {
|
|
172
|
+
var _this$currentTradeMet2;
|
|
173
|
+
[transactionConfig] = await getEVMTransactionObject({
|
|
174
|
+
chain: originChain.slug,
|
|
175
|
+
evmApi,
|
|
176
|
+
from: params.request.address,
|
|
177
|
+
to: depositAddress,
|
|
178
|
+
value: params.request.fromAmount,
|
|
179
|
+
feeInfo,
|
|
180
|
+
transferAll: false,
|
|
181
|
+
fallbackFee: true,
|
|
182
|
+
data: (_this$currentTradeMet2 = this.currentTradeMetadata) === null || _this$currentTradeMet2 === void 0 ? void 0 : _this$currentTradeMet2.payload
|
|
183
|
+
});
|
|
184
|
+
} else {
|
|
185
|
+
[transactionConfig] = await getERC20TransactionObject({
|
|
186
|
+
assetAddress: _getContractAddressOfToken(originTokenInfo),
|
|
187
|
+
chain: originChain.slug,
|
|
188
|
+
evmApi: this.chainService.getEvmApi(originChain.slug),
|
|
189
|
+
from: params.request.address,
|
|
190
|
+
to: depositAddress,
|
|
191
|
+
value: params.request.fromAmount,
|
|
192
|
+
feeInfo,
|
|
193
|
+
transferAll: false
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
networkFeeAmount = await estimateTxFee(transactionConfig, evmApi, feeInfo);
|
|
197
|
+
} else if (originChainType === ChainType.BITCOIN) {
|
|
198
|
+
const bitcoinApi = this.chainService.getBitcoinApi(originChain.slug);
|
|
199
|
+
const feeInfo = await this.swapBaseHandler.feeService.subscribeChainFee(getId(), originChain.slug, 'bitcoin');
|
|
200
|
+
const network = originChain.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin;
|
|
201
|
+
const [transaction] = await createBitcoinTransaction({
|
|
202
|
+
bitcoinApi,
|
|
203
|
+
chain: originChain.slug,
|
|
204
|
+
from: params.request.address,
|
|
205
|
+
feeInfo,
|
|
206
|
+
to: depositAddress,
|
|
207
|
+
transferAll: false,
|
|
208
|
+
value: params.request.fromAmount,
|
|
209
|
+
network
|
|
210
|
+
});
|
|
211
|
+
const feeCombine = combineBitcoinFee(feeInfo, undefined, undefined); // todo: recheck when implement custom fee
|
|
212
|
+
|
|
213
|
+
const recipients = [];
|
|
214
|
+
for (const txOutput of transaction.txOutputs) {
|
|
215
|
+
txOutput.address && recipients.push(txOutput.address);
|
|
216
|
+
}
|
|
217
|
+
const sizeInfo = getSizeInfo({
|
|
218
|
+
inputLength: transaction.inputCount,
|
|
219
|
+
recipients: recipients,
|
|
220
|
+
sender: params.request.address
|
|
221
|
+
});
|
|
222
|
+
networkFeeAmount = Math.ceil(feeCombine.feeRate * sizeInfo.txVBytes).toString();
|
|
223
|
+
} else {
|
|
224
|
+
console.log('Unsupported swap from this chain type', originChainType);
|
|
225
|
+
return Promise.resolve(undefined);
|
|
226
|
+
}
|
|
227
|
+
} catch (e) {
|
|
228
|
+
throw new Error(e.message);
|
|
229
|
+
}
|
|
230
|
+
const networkFee = {
|
|
231
|
+
amount: networkFeeAmount || '0',
|
|
232
|
+
feeType: SwapFeeType.NETWORK_FEE,
|
|
233
|
+
tokenSlug: originChainNativeTokenSlug
|
|
234
|
+
};
|
|
235
|
+
const submitStep = {
|
|
236
|
+
name: 'Swap',
|
|
237
|
+
type: SwapStepType.SWAP,
|
|
238
|
+
// @ts-ignore
|
|
239
|
+
metadata: {
|
|
240
|
+
sendingValue: params.request.fromAmount.toString(),
|
|
241
|
+
expectedReceive: params.selectedQuote.toAmount,
|
|
242
|
+
originTokenInfo,
|
|
243
|
+
destinationTokenInfo,
|
|
244
|
+
sender: _reformatAddressWithChain(params.request.address, originChain),
|
|
245
|
+
receiver: _reformatAddressWithChain(params.request.recipient || params.request.address, destinationChain),
|
|
246
|
+
version: 2
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
const feeInfo = {
|
|
250
|
+
defaultFeeToken: params.selectedQuote.feeInfo.defaultFeeToken,
|
|
251
|
+
feeComponent: [...params.selectedQuote.feeInfo.feeComponent, networkFee],
|
|
252
|
+
feeOptions: params.selectedQuote.feeInfo.feeOptions
|
|
253
|
+
};
|
|
254
|
+
return Promise.resolve([submitStep, feeInfo]);
|
|
255
|
+
}
|
|
256
|
+
async validateSwapProcessV2(params) {
|
|
257
|
+
const {
|
|
258
|
+
process,
|
|
259
|
+
selectedQuote
|
|
260
|
+
} = params;
|
|
261
|
+
if (BigNumber(selectedQuote.fromAmount).lte(0)) {
|
|
262
|
+
return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')];
|
|
263
|
+
}
|
|
264
|
+
const actionList = JSON.stringify(process.path.map(step => step.action));
|
|
265
|
+
const swap = actionList === JSON.stringify([DynamicSwapType.SWAP]);
|
|
266
|
+
const swapXcm = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
|
|
267
|
+
const xcmSwap = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP]);
|
|
268
|
+
const xcmSwapXcm = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
|
|
269
|
+
const swapIndex = params.process.steps.findIndex(step => step.type === SwapStepType.SWAP);
|
|
270
|
+
if (swapIndex <= -1) {
|
|
271
|
+
return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
|
|
272
|
+
}
|
|
273
|
+
if (swap) {
|
|
274
|
+
return this.swapBaseHandler.validateSwapOnlyProcess(params, swapIndex);
|
|
275
|
+
}
|
|
276
|
+
if (swapXcm) {
|
|
277
|
+
return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
|
|
278
|
+
}
|
|
279
|
+
if (xcmSwap) {
|
|
280
|
+
return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
|
|
281
|
+
}
|
|
282
|
+
if (xcmSwapXcm) {
|
|
283
|
+
return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
|
|
284
|
+
}
|
|
285
|
+
return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
|
|
286
|
+
}
|
|
287
|
+
async handleSwapProcess(params) {
|
|
288
|
+
const {
|
|
289
|
+
currentStep,
|
|
290
|
+
process
|
|
291
|
+
} = params;
|
|
292
|
+
const type = process.steps[currentStep].type;
|
|
293
|
+
switch (type) {
|
|
294
|
+
case CommonStepType.DEFAULT:
|
|
295
|
+
return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
|
|
296
|
+
case CommonStepType.TOKEN_APPROVAL:
|
|
297
|
+
return this.handleApproveStep(params);
|
|
298
|
+
case SwapStepType.SWAP:
|
|
299
|
+
return this.handleSubmitStep(params);
|
|
300
|
+
default:
|
|
301
|
+
return this.handleSubmitStep(params);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
handleApproveStep(params) {
|
|
305
|
+
// todo: handle this when support route has approve step
|
|
306
|
+
const fromAsset = this.chainService.getAssetBySlug(params.quote.pair.from);
|
|
307
|
+
return {
|
|
308
|
+
txChain: fromAsset.originChain,
|
|
309
|
+
txData: '',
|
|
310
|
+
extrinsic: {},
|
|
311
|
+
extrinsicType: ExtrinsicType.TOKEN_SPENDING_APPROVAL,
|
|
312
|
+
transferNativeAmount: '0',
|
|
313
|
+
chainType: ChainType.EVM
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
async handleSubmitStep(params) {
|
|
317
|
+
var _this$currentTradeMet3, _this$currentTradeMet4, _this$currentTradeMet5;
|
|
318
|
+
const {
|
|
319
|
+
address,
|
|
320
|
+
process,
|
|
321
|
+
quote,
|
|
322
|
+
recipient,
|
|
323
|
+
slippage
|
|
324
|
+
} = params;
|
|
325
|
+
const pair = quote.pair;
|
|
326
|
+
const fromAsset = this.chainService.getAssetBySlug(pair.from);
|
|
327
|
+
const chainInfo = this.chainService.getChainInfoByKey(fromAsset.originChain);
|
|
328
|
+
const chainType = _chainInfoToChainType(chainInfo);
|
|
329
|
+
const depositAddress = (_this$currentTradeMet3 = this.currentTradeMetadata) === null || _this$currentTradeMet3 === void 0 ? void 0 : _this$currentTradeMet3.deposit_address;
|
|
330
|
+
const tradeId = (_this$currentTradeMet4 = this.currentTradeMetadata) === null || _this$currentTradeMet4 === void 0 ? void 0 : _this$currentTradeMet4.trade_id;
|
|
331
|
+
const payload = (_this$currentTradeMet5 = this.currentTradeMetadata) === null || _this$currentTradeMet5 === void 0 ? void 0 : _this$currentTradeMet5.payload; // undefined in case swap from btc
|
|
332
|
+
|
|
333
|
+
if (!depositAddress || !tradeId) {
|
|
334
|
+
throw new Error('Optimex Trade metadata is undefined, request for new quote');
|
|
335
|
+
}
|
|
336
|
+
const txData = {
|
|
337
|
+
address,
|
|
338
|
+
provider: this.providerInfo,
|
|
339
|
+
quote,
|
|
340
|
+
slippage,
|
|
341
|
+
recipient,
|
|
342
|
+
process
|
|
343
|
+
};
|
|
344
|
+
let extrinsic;
|
|
345
|
+
|
|
346
|
+
// dont remove this log
|
|
347
|
+
console.log('Optimex Trade metadata:', this.currentTradeMetadata);
|
|
348
|
+
console.log('Optimex Trade channel:', this.isTestnet ? `https://provider-api-docs.vercel.app/swap/${tradeId}` : `https://provider-api-docs.vercel.app/swap/${tradeId}?env=sub_wallet`);
|
|
349
|
+
if (chainType === ChainType.BITCOIN) {
|
|
350
|
+
const bitcoinApi = this.chainService.getBitcoinApi(chainInfo.slug);
|
|
351
|
+
const feeInfo = await this.swapBaseHandler.feeService.subscribeChainFee(getId(), chainInfo.slug, 'bitcoin');
|
|
352
|
+
const network = chainInfo.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin;
|
|
353
|
+
const [transaction] = await createBitcoinTransaction({
|
|
354
|
+
bitcoinApi,
|
|
355
|
+
chain: chainInfo.slug,
|
|
356
|
+
from: address,
|
|
357
|
+
feeInfo,
|
|
358
|
+
to: depositAddress,
|
|
359
|
+
transferAll: false,
|
|
360
|
+
value: quote.fromAmount,
|
|
361
|
+
network
|
|
362
|
+
});
|
|
363
|
+
extrinsic = transaction;
|
|
364
|
+
} else if (chainType === ChainType.EVM) {
|
|
365
|
+
const feeInfo = await this.swapBaseHandler.feeService.subscribeChainFee(getId(), chainInfo.slug, 'evm');
|
|
366
|
+
if (_isNativeToken(fromAsset)) {
|
|
367
|
+
const [transactionConfig] = await getEVMTransactionObject({
|
|
368
|
+
chain: chainInfo.slug,
|
|
369
|
+
evmApi: this.chainService.getEvmApi(chainInfo.slug),
|
|
370
|
+
from: address,
|
|
371
|
+
to: depositAddress,
|
|
372
|
+
value: quote.fromAmount,
|
|
373
|
+
feeInfo,
|
|
374
|
+
transferAll: false,
|
|
375
|
+
data: payload
|
|
376
|
+
});
|
|
377
|
+
extrinsic = {
|
|
378
|
+
...transactionConfig,
|
|
379
|
+
data: payload
|
|
380
|
+
};
|
|
381
|
+
} else {
|
|
382
|
+
const [transactionConfig] = await getERC20TransactionObject({
|
|
383
|
+
assetAddress: _getContractAddressOfToken(fromAsset),
|
|
384
|
+
chain: chainInfo.slug,
|
|
385
|
+
evmApi: this.chainService.getEvmApi(chainInfo.slug),
|
|
386
|
+
from: address,
|
|
387
|
+
to: depositAddress,
|
|
388
|
+
value: quote.fromAmount,
|
|
389
|
+
feeInfo,
|
|
390
|
+
transferAll: false
|
|
391
|
+
});
|
|
392
|
+
extrinsic = transactionConfig;
|
|
393
|
+
}
|
|
394
|
+
} else {
|
|
395
|
+
throw new Error('Unknown swap chain type');
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// reset tradeMetadata after use // todo: review to check if need this clear
|
|
399
|
+
// this.currentTradeMetadata = undefined;
|
|
400
|
+
|
|
401
|
+
return {
|
|
402
|
+
txChain: fromAsset.originChain,
|
|
403
|
+
txData,
|
|
404
|
+
extrinsic,
|
|
405
|
+
transferNativeAmount: _isNativeToken(fromAsset) ? quote.fromAmount : '0',
|
|
406
|
+
extrinsicType: ExtrinsicType.SWAP,
|
|
407
|
+
chainType
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
|
|
5
5
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
6
6
|
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
7
|
-
import { _getAssetDecimals, _getAssetSymbol, _getContractAddressOfToken,
|
|
7
|
+
import { _chainInfoToChainType, _getAssetDecimals, _getAssetSymbol, _getContractAddressOfToken, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
|
|
8
8
|
import { BasicTxErrorType, CommonStepType, DynamicSwapType, SwapErrorType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
|
|
9
9
|
import { ProxyServiceRoute } from '@subwallet/extension-base/types/environment';
|
|
10
10
|
import { _reformatAddressWithChain, fetchFromProxyService, formatNumber } from '@subwallet/extension-base/utils';
|
|
@@ -159,7 +159,7 @@ export class SimpleSwapHandler {
|
|
|
159
159
|
const toAsset = this.chainService.getAssetBySlug(pair.to);
|
|
160
160
|
const chainInfo = this.chainService.getChainInfoByKey(fromAsset.originChain);
|
|
161
161
|
const toChainInfo = this.chainService.getChainInfoByKey(toAsset.originChain);
|
|
162
|
-
const chainType =
|
|
162
|
+
const chainType = _chainInfoToChainType(chainInfo);
|
|
163
163
|
const sender = _reformatAddressWithChain(address, chainInfo);
|
|
164
164
|
const receiver = _reformatAddressWithChain(recipient !== null && recipient !== void 0 ? recipient : sender, toChainInfo);
|
|
165
165
|
const fromSymbol = _getAssetSymbol(fromAsset).toLowerCase();
|
|
@@ -222,7 +222,7 @@ export class SimpleSwapHandler {
|
|
|
222
222
|
value: quote.fromAmount
|
|
223
223
|
});
|
|
224
224
|
extrinsic = submittableExtrinsic;
|
|
225
|
-
} else {
|
|
225
|
+
} else if (chainType === ChainType.EVM) {
|
|
226
226
|
const feeInfo = await this.swapBaseHandler.feeService.subscribeChainFee(getId(), chainInfo.slug, 'evm');
|
|
227
227
|
if (_isNativeToken(fromAsset)) {
|
|
228
228
|
const [transactionConfig] = await getEVMTransactionObject({
|
|
@@ -248,6 +248,8 @@ export class SimpleSwapHandler {
|
|
|
248
248
|
});
|
|
249
249
|
extrinsic = transactionConfig;
|
|
250
250
|
}
|
|
251
|
+
} else {
|
|
252
|
+
throw new Error('Unknown swap chain type');
|
|
251
253
|
}
|
|
252
254
|
return {
|
|
253
255
|
txChain: fromAsset.originChain,
|
|
@@ -19,7 +19,6 @@ export declare class SwapService implements StoppableServiceInterface {
|
|
|
19
19
|
private getDefaultProcessV2;
|
|
20
20
|
generateOptimalProcessV2(params: OptimalSwapPathParamsV2): Promise<CommonOptimalSwapPath>;
|
|
21
21
|
handleSwapRequestV2(request: SwapRequestV2): Promise<SwapRequestResult>;
|
|
22
|
-
getAvailablePath(request: SwapRequestV2): [DynamicSwapAction[], SwapRequestV2 | undefined];
|
|
23
22
|
getLatestQuoteFromSwapRequest(request: SwapRequestV2): Promise<{
|
|
24
23
|
path: DynamicSwapAction[];
|
|
25
24
|
swapQuoteResponse: SwapQuoteResponse;
|