@subwallet/extension-base 1.3.34-0 → 1.3.36-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 +10 -0
- package/cjs/core/logic-validation/request.js +1 -1
- package/cjs/koni/background/handlers/Extension.js +32 -4
- package/cjs/koni/background/utils.js +64 -29
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/helpers/process.js +1 -5
- package/cjs/services/balance-service/index.js +20 -1
- package/cjs/services/balance-service/transfer/xcm/acrossBridge/index.js +91 -175
- package/cjs/services/balance-service/transfer/xcm/index.js +7 -6
- package/cjs/services/price-service/coingecko.js +22 -15
- package/cjs/services/price-service/index.js +12 -0
- package/cjs/services/request-service/handler/EvmRequestHandler.js +4 -1
- package/cjs/services/swap-service/handler/kyber-handler.js +355 -0
- package/cjs/services/swap-service/handler/uniswap-handler.js +223 -41
- package/cjs/services/swap-service/index.js +34 -2
- package/cjs/services/swap-service/utils.js +4 -1
- package/cjs/services/transaction-service/index.js +297 -52
- package/cjs/types/swap/index.js +2 -1
- package/core/logic-validation/request.js +1 -1
- package/koni/background/handlers/Extension.d.ts +1 -0
- package/koni/background/handlers/Extension.js +32 -4
- package/koni/background/utils.d.ts +3 -5
- package/koni/background/utils.js +64 -29
- package/package.json +11 -6
- package/packageInfo.js +1 -1
- package/services/balance-service/helpers/process.d.ts +2 -2
- package/services/balance-service/helpers/process.js +1 -5
- package/services/balance-service/index.js +21 -2
- package/services/balance-service/transfer/xcm/acrossBridge/index.d.ts +9 -8
- package/services/balance-service/transfer/xcm/acrossBridge/index.js +91 -174
- package/services/balance-service/transfer/xcm/index.js +7 -6
- package/services/event-service/types.d.ts +6 -6
- package/services/price-service/coingecko.d.ts +1 -1
- package/services/price-service/coingecko.js +22 -16
- package/services/price-service/index.d.ts +1 -0
- package/services/price-service/index.js +12 -0
- package/services/request-service/handler/EvmRequestHandler.js +4 -1
- package/services/swap-service/handler/kyber-handler.d.ts +28 -0
- package/services/swap-service/handler/kyber-handler.js +346 -0
- package/services/swap-service/handler/uniswap-handler.d.ts +48 -0
- package/services/swap-service/handler/uniswap-handler.js +224 -42
- package/services/swap-service/index.js +34 -2
- package/services/swap-service/utils.js +4 -1
- package/services/transaction-service/helpers/index.d.ts +5 -5
- package/services/transaction-service/index.d.ts +10 -5
- package/services/transaction-service/index.js +279 -36
- package/services/transaction-service/types.d.ts +23 -10
- package/types/swap/index.d.ts +4 -1
- package/types/swap/index.js +2 -1
|
@@ -60,28 +60,33 @@ const fetchDerivativeTokenSlugs = async () => {
|
|
|
60
60
|
};
|
|
61
61
|
const getPriceMap = async function (priceIds) {
|
|
62
62
|
let currency = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'USD';
|
|
63
|
+
let skipDerivativePrice = arguments.length > 2 ? arguments[2] : undefined;
|
|
63
64
|
const idStr = Array.from(priceIds).join(',');
|
|
64
65
|
let response;
|
|
65
66
|
try {
|
|
66
67
|
var _response3, _response5;
|
|
67
68
|
const derivativePriceMap = {};
|
|
69
|
+
const lastUpdatedMap = {};
|
|
68
70
|
let derivativeApiError = false;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
71
|
+
if (!skipDerivativePrice) {
|
|
72
|
+
try {
|
|
73
|
+
const responseDerivativeTokens = await fetch(`${apiCacheDomain}/api/price/derivative-get`);
|
|
74
|
+
const generateDerivativePriceRaw = (await (responseDerivativeTokens === null || responseDerivativeTokens === void 0 ? void 0 : responseDerivativeTokens.json())) || [];
|
|
75
|
+
if (Array.isArray(generateDerivativePriceRaw)) {
|
|
76
|
+
generateDerivativePriceRaw.forEach(token => {
|
|
77
|
+
if (token.id) {
|
|
78
|
+
derivativePriceMap[token.id] = token.derived_price;
|
|
79
|
+
lastUpdatedMap[token.id] = new Date(token.cached_at || Date.now());
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
} else {
|
|
83
|
+
console.warn('Invalid data from derivative API:', generateDerivativePriceRaw);
|
|
84
|
+
derivativeApiError = true;
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error('Error fetching derivative API:', error);
|
|
80
88
|
derivativeApiError = true;
|
|
81
89
|
}
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error('Error fetching derivative API:', error);
|
|
84
|
-
derivativeApiError = true;
|
|
85
90
|
}
|
|
86
91
|
if (!useBackupApi) {
|
|
87
92
|
try {
|
|
@@ -113,10 +118,11 @@ const getPriceMap = async function (priceIds) {
|
|
|
113
118
|
const currencyData = _staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][currency || DEFAULT_CURRENCY];
|
|
114
119
|
const priceMap = {};
|
|
115
120
|
const price24hMap = {};
|
|
116
|
-
const
|
|
121
|
+
const priceCoinGeckoSupported = [];
|
|
117
122
|
responseDataPrice.forEach(val => {
|
|
118
123
|
const currentPrice = val.current_price || 0;
|
|
119
124
|
const price24h = currentPrice - (val.price_change_24h || 0);
|
|
125
|
+
priceCoinGeckoSupported.push(val.id);
|
|
120
126
|
priceMap[val.id] = currentPrice;
|
|
121
127
|
price24hMap[val.id] = price24h;
|
|
122
128
|
lastUpdatedMap[val.id] = new Date(val.last_updated || val.last_updated_at || Date.now());
|
|
@@ -139,6 +145,7 @@ const getPriceMap = async function (priceIds) {
|
|
|
139
145
|
currencyData,
|
|
140
146
|
priceMap,
|
|
141
147
|
price24hMap,
|
|
148
|
+
priceCoinGeckoSupported,
|
|
142
149
|
lastUpdatedMap
|
|
143
150
|
};
|
|
144
151
|
} catch (e) {
|
|
@@ -26,6 +26,7 @@ const DEFAULT_PRICE_SUBJECT = {
|
|
|
26
26
|
isPrefix: true
|
|
27
27
|
},
|
|
28
28
|
priceMap: {},
|
|
29
|
+
priceCoinGeckoSupported: [],
|
|
29
30
|
price24hMap: {},
|
|
30
31
|
exchangeRateMap: {},
|
|
31
32
|
lastUpdatedMap: {}
|
|
@@ -103,6 +104,7 @@ class PriceService {
|
|
|
103
104
|
let {
|
|
104
105
|
lastUpdatedMap,
|
|
105
106
|
price24hMap,
|
|
107
|
+
priceCoinGeckoSupported,
|
|
106
108
|
priceMap
|
|
107
109
|
} = this.rawPriceSubject.value;
|
|
108
110
|
let exchangeRateData = this.rawExchangeRateMap.value;
|
|
@@ -132,6 +134,7 @@ class PriceService {
|
|
|
132
134
|
},
|
|
133
135
|
currency: currencyKey,
|
|
134
136
|
exchangeRateMap: exchangeRateData,
|
|
137
|
+
priceCoinGeckoSupported,
|
|
135
138
|
currencyData: _staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][currencyKey || DEFAULT_CURRENCY],
|
|
136
139
|
lastUpdatedMap: {
|
|
137
140
|
...lastUpdatedMap
|
|
@@ -268,6 +271,15 @@ class PriceService {
|
|
|
268
271
|
this.status = _types.ServiceStatus.INITIALIZED;
|
|
269
272
|
this.eventService.on('asset.updateState', eventHandler);
|
|
270
273
|
}
|
|
274
|
+
checkCoinGeckoPriceSupport(priceId) {
|
|
275
|
+
const {
|
|
276
|
+
priceCoinGeckoSupported
|
|
277
|
+
} = this.priceSubject.value;
|
|
278
|
+
if (!priceCoinGeckoSupported) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
return priceCoinGeckoSupported.includes(priceId);
|
|
282
|
+
}
|
|
271
283
|
async loadData() {
|
|
272
284
|
const data = await this.dbService.getPriceStore(this.priceSubject.value.currency);
|
|
273
285
|
this.priceSubject.next(data || DEFAULT_PRICE_SUBJECT);
|
|
@@ -29,7 +29,8 @@ class EvmRequestHandler {
|
|
|
29
29
|
evmSignatureRequest: {},
|
|
30
30
|
evmSendTransactionRequest: {},
|
|
31
31
|
evmWatchTransactionRequest: {},
|
|
32
|
-
errorConnectNetwork: {}
|
|
32
|
+
errorConnectNetwork: {},
|
|
33
|
+
submitApiRequest: {}
|
|
33
34
|
});
|
|
34
35
|
confirmationsPromiseMap = {};
|
|
35
36
|
constructor(requestService) {
|
|
@@ -225,6 +226,8 @@ class EvmRequestHandler {
|
|
|
225
226
|
result.payload = await this.signMessage(request);
|
|
226
227
|
} else if (t === 'evmSendTransactionRequest') {
|
|
227
228
|
result.payload = await this.signTransaction(request);
|
|
229
|
+
} else if (t === 'submitApiRequest') {
|
|
230
|
+
return;
|
|
228
231
|
}
|
|
229
232
|
if (t === 'evmSignatureRequest' || t === 'evmSendTransactionRequest') {
|
|
230
233
|
const isAlwaysRequired = await this.#requestService.settingService.isAlwaysRequired;
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.KyberHandler = exports.KYBER_CLIENT_ID = void 0;
|
|
8
|
+
var _SwapError = require("@subwallet/extension-base/background/errors/SwapError");
|
|
9
|
+
var _TransactionError = require("@subwallet/extension-base/background/errors/TransactionError");
|
|
10
|
+
var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
|
|
11
|
+
var _web = require("@subwallet/extension-base/koni/api/contract-handler/evm/web3");
|
|
12
|
+
var _types = require("@subwallet/extension-base/types");
|
|
13
|
+
var _utils = require("@subwallet/extension-base/utils");
|
|
14
|
+
var _getId = require("@subwallet/extension-base/utils/getId");
|
|
15
|
+
var _bignumber = _interopRequireDefault(require("bignumber.js"));
|
|
16
|
+
var _utils2 = require("../../chain-service/utils");
|
|
17
|
+
var _utils3 = require("../../fee-service/utils");
|
|
18
|
+
var _baseHandler = require("./base-handler");
|
|
19
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
20
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
21
|
+
|
|
22
|
+
const KYBER_CLIENT_ID = process.env.KYBER_CLIENT_ID || '';
|
|
23
|
+
exports.KYBER_CLIENT_ID = KYBER_CLIENT_ID;
|
|
24
|
+
const kyberUrl = 'https://aggregator-api.kyberswap.com';
|
|
25
|
+
async function buildTxForSwap(params, chain) {
|
|
26
|
+
const {
|
|
27
|
+
recipient,
|
|
28
|
+
sender,
|
|
29
|
+
slippageTolerance
|
|
30
|
+
} = params;
|
|
31
|
+
let routeSummary = params.routeSummary;
|
|
32
|
+
if (!routeSummary || !routeSummary.tokenIn || !routeSummary.tokenOut || !routeSummary.amountIn) {
|
|
33
|
+
const queryParams = new URLSearchParams({
|
|
34
|
+
tokenIn: routeSummary.tokenIn,
|
|
35
|
+
tokenOut: routeSummary.tokenOut,
|
|
36
|
+
amountIn: routeSummary.amountIn,
|
|
37
|
+
gasInclude: 'true'
|
|
38
|
+
});
|
|
39
|
+
const url = `${kyberUrl}/${chain}/api/v1/routes?${queryParams.toString()}`;
|
|
40
|
+
try {
|
|
41
|
+
var _routeData$data;
|
|
42
|
+
const res = await fetch(url, {
|
|
43
|
+
method: 'GET',
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
'x-client-id': KYBER_CLIENT_ID,
|
|
47
|
+
accept: 'application/json'
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
const routeData = await res.json();
|
|
51
|
+
if (!routeData.success || !((_routeData$data = routeData.data) !== null && _routeData$data !== void 0 && _routeData$data.routeSummary)) {
|
|
52
|
+
return {
|
|
53
|
+
error: new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR, routeData.message)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
routeSummary = routeData.data.routeSummary;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error('Error:', error);
|
|
59
|
+
return {
|
|
60
|
+
error: new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const body = {
|
|
65
|
+
routeSummary,
|
|
66
|
+
sender,
|
|
67
|
+
recipient,
|
|
68
|
+
slippageTolerance,
|
|
69
|
+
ignoreCappedSlippage: true,
|
|
70
|
+
enableGasEstimation: true
|
|
71
|
+
};
|
|
72
|
+
try {
|
|
73
|
+
const res = await fetch(`${kyberUrl}/${chain}/api/v1/route/build`, {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
headers: {
|
|
76
|
+
'Content-Type': 'application/json',
|
|
77
|
+
'x-client-id': KYBER_CLIENT_ID,
|
|
78
|
+
accept: 'application/json'
|
|
79
|
+
},
|
|
80
|
+
body: JSON.stringify(body)
|
|
81
|
+
});
|
|
82
|
+
const data = await res.json();
|
|
83
|
+
const requestData = data.data;
|
|
84
|
+
if (!requestData || !requestData.routerAddress || !requestData.data || !requestData.gas) {
|
|
85
|
+
var _data$details$map, _data$details, _data$message$toLower, _data$message;
|
|
86
|
+
const lowerDetails = (_data$details$map = (_data$details = data.details) === null || _data$details === void 0 ? void 0 : _data$details.map(d => d.toLowerCase())) !== null && _data$details$map !== void 0 ? _data$details$map : [];
|
|
87
|
+
const msg = (_data$message$toLower = (_data$message = data.message) === null || _data$message === void 0 ? void 0 : _data$message.toLowerCase()) !== null && _data$message$toLower !== void 0 ? _data$message$toLower : '';
|
|
88
|
+
if (lowerDetails.some(d => d.includes('insufficient liquidity'))) {
|
|
89
|
+
return {
|
|
90
|
+
error: new _SwapError.SwapError(_types.SwapErrorType.NOT_ENOUGH_LIQUIDITY)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (lowerDetails.some(d => d.includes('execution reverted')) || msg.includes('smaller than estimated')) {
|
|
94
|
+
return {
|
|
95
|
+
error: new _SwapError.SwapError(_types.SwapErrorType.NOT_MEET_MIN_EXPECTED)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
error: new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR, data.message)
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
data: {
|
|
104
|
+
from: sender,
|
|
105
|
+
to: requestData.routerAddress,
|
|
106
|
+
value: requestData.transactionValue,
|
|
107
|
+
data: requestData.data,
|
|
108
|
+
gas: requestData.gas
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
} catch (error) {
|
|
112
|
+
console.error('Kyber error:', error);
|
|
113
|
+
return {
|
|
114
|
+
error: new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
class KyberHandler {
|
|
119
|
+
constructor(chainService, balanceService, transactionService, feeService) {
|
|
120
|
+
this.swapBaseHandler = new _baseHandler.SwapBaseHandler({
|
|
121
|
+
chainService,
|
|
122
|
+
balanceService,
|
|
123
|
+
feeService,
|
|
124
|
+
providerName: 'Kyber',
|
|
125
|
+
providerSlug: _types.SwapProviderId.KYBER
|
|
126
|
+
});
|
|
127
|
+
this.transactionService = transactionService;
|
|
128
|
+
this.providerSlug = _types.SwapProviderId.KYBER;
|
|
129
|
+
}
|
|
130
|
+
get chainService() {
|
|
131
|
+
return this.swapBaseHandler.chainService;
|
|
132
|
+
}
|
|
133
|
+
get balanceService() {
|
|
134
|
+
return this.swapBaseHandler.balanceService;
|
|
135
|
+
}
|
|
136
|
+
get feeService() {
|
|
137
|
+
return this.swapBaseHandler.feeService;
|
|
138
|
+
}
|
|
139
|
+
get providerInfo() {
|
|
140
|
+
return this.swapBaseHandler.providerInfo;
|
|
141
|
+
}
|
|
142
|
+
generateOptimalProcessV2(params) {
|
|
143
|
+
return this.swapBaseHandler.generateOptimalProcessV2(params, [this.getApprovalStep.bind(this), this.getSubmitStep.bind(this)]);
|
|
144
|
+
}
|
|
145
|
+
async getApprovalStep(params) {
|
|
146
|
+
const selectedQuote = params.selectedQuote;
|
|
147
|
+
if (selectedQuote) {
|
|
148
|
+
const fromAsset = this.chainService.getAssetBySlug(selectedQuote.pair.from);
|
|
149
|
+
if ((0, _utils2._isNativeToken)(fromAsset)) {
|
|
150
|
+
return Promise.resolve(undefined);
|
|
151
|
+
}
|
|
152
|
+
const metadata = selectedQuote.metadata;
|
|
153
|
+
const routerContract = metadata.routerAddress;
|
|
154
|
+
const evmApi = this.chainService.getEvmApi(fromAsset.originChain);
|
|
155
|
+
const fromContractAddress = (0, _utils2._getContractAddressOfToken)(fromAsset);
|
|
156
|
+
const allowance = await (0, _web.getERC20Allowance)(routerContract, params.request.address, fromContractAddress, evmApi);
|
|
157
|
+
if (allowance && new _bignumber.default(allowance).gt(params.request.fromAmount)) {
|
|
158
|
+
return Promise.resolve(undefined);
|
|
159
|
+
}
|
|
160
|
+
const sendingAmount = selectedQuote.toAmount;
|
|
161
|
+
const senderAddress = params.request.address;
|
|
162
|
+
const fromTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.from);
|
|
163
|
+
const tokenContract = (0, _utils2._getContractAddressOfToken)(fromTokenInfo);
|
|
164
|
+
const spenderAddress = metadata.routerAddress;
|
|
165
|
+
const submitStep = {
|
|
166
|
+
name: 'Approve token',
|
|
167
|
+
type: _types.CommonStepType.TOKEN_APPROVAL,
|
|
168
|
+
metadata: {
|
|
169
|
+
tokenApprove: fromTokenInfo.slug,
|
|
170
|
+
contractAddress: tokenContract,
|
|
171
|
+
spenderAddress: spenderAddress,
|
|
172
|
+
amount: sendingAmount,
|
|
173
|
+
owner: senderAddress
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const tx = await (0, _web.getERC20SpendingApprovalTx)(spenderAddress, senderAddress, tokenContract, evmApi);
|
|
177
|
+
const evmFeeInfo = await this.feeService.subscribeChainFee((0, _getId.getId)(), fromTokenInfo.originChain, 'evm');
|
|
178
|
+
const estimatedFee = await (0, _web.estimateTxFee)(tx, evmApi, evmFeeInfo);
|
|
179
|
+
const fromChainInfo = this.chainService.getChainInfoByKey(fromTokenInfo.originChain);
|
|
180
|
+
const nativeTokenSlug = (0, _utils2._getChainNativeTokenSlug)(fromChainInfo);
|
|
181
|
+
const feeInfo = {
|
|
182
|
+
feeComponent: [{
|
|
183
|
+
feeType: _types.SwapFeeType.NETWORK_FEE,
|
|
184
|
+
amount: estimatedFee,
|
|
185
|
+
tokenSlug: nativeTokenSlug
|
|
186
|
+
}],
|
|
187
|
+
defaultFeeToken: nativeTokenSlug,
|
|
188
|
+
feeOptions: [nativeTokenSlug]
|
|
189
|
+
};
|
|
190
|
+
return Promise.resolve([submitStep, feeInfo]);
|
|
191
|
+
}
|
|
192
|
+
return Promise.resolve(undefined);
|
|
193
|
+
}
|
|
194
|
+
async getSubmitStep(params, stepIndex) {
|
|
195
|
+
const {
|
|
196
|
+
path,
|
|
197
|
+
request,
|
|
198
|
+
selectedQuote
|
|
199
|
+
} = params;
|
|
200
|
+
|
|
201
|
+
// stepIndex is not corresponding index in path, because uniswap include approval and permit step
|
|
202
|
+
const stepData = path.find(action => action.action === _types.DynamicSwapType.SWAP);
|
|
203
|
+
if (!stepData || !stepData.pair) {
|
|
204
|
+
return Promise.resolve(undefined);
|
|
205
|
+
}
|
|
206
|
+
if (!selectedQuote) {
|
|
207
|
+
return Promise.resolve(undefined);
|
|
208
|
+
}
|
|
209
|
+
const originTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.from);
|
|
210
|
+
const destinationTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.to);
|
|
211
|
+
const originChain = this.chainService.getChainInfoByKey(originTokenInfo.originChain);
|
|
212
|
+
const destinationChain = this.chainService.getChainInfoByKey(destinationTokenInfo.originChain);
|
|
213
|
+
const submitStep = {
|
|
214
|
+
name: 'Swap',
|
|
215
|
+
type: _types.SwapStepType.SWAP,
|
|
216
|
+
// @ts-ignore
|
|
217
|
+
metadata: {
|
|
218
|
+
sendingValue: request.fromAmount.toString(),
|
|
219
|
+
expectedReceive: selectedQuote.toAmount,
|
|
220
|
+
originTokenInfo,
|
|
221
|
+
destinationTokenInfo,
|
|
222
|
+
sender: (0, _utils._reformatAddressWithChain)(request.address, originChain),
|
|
223
|
+
receiver: (0, _utils._reformatAddressWithChain)(request.recipient || request.address, destinationChain),
|
|
224
|
+
version: 2
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
return Promise.resolve([submitStep, selectedQuote.feeInfo]);
|
|
228
|
+
}
|
|
229
|
+
async handleSwapProcess(params) {
|
|
230
|
+
const {
|
|
231
|
+
currentStep,
|
|
232
|
+
process
|
|
233
|
+
} = params;
|
|
234
|
+
const type = process.steps[currentStep].type;
|
|
235
|
+
switch (type) {
|
|
236
|
+
case _types.CommonStepType.DEFAULT:
|
|
237
|
+
return Promise.reject(new _TransactionError.TransactionError(_types.BasicTxErrorType.UNSUPPORTED));
|
|
238
|
+
case _types.CommonStepType.TOKEN_APPROVAL:
|
|
239
|
+
return this.tokenApproveSpending(params);
|
|
240
|
+
case _types.SwapStepType.SWAP:
|
|
241
|
+
return this.handleSubmitStep(params);
|
|
242
|
+
default:
|
|
243
|
+
return this.handleSubmitStep(params);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
async tokenApproveSpending(params) {
|
|
247
|
+
const fromAsset = this.chainService.getAssetBySlug(params.quote.pair.from);
|
|
248
|
+
const fromContract = (0, _utils2._getContractAddressOfToken)(fromAsset);
|
|
249
|
+
const evmApi = this.chainService.getEvmApi(fromAsset.originChain);
|
|
250
|
+
const chain = fromAsset.originChain;
|
|
251
|
+
const metadata = params.quote.metadata;
|
|
252
|
+
if (!metadata || !metadata.routerAddress) {
|
|
253
|
+
throw new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS);
|
|
254
|
+
}
|
|
255
|
+
const routerContract = metadata.routerAddress;
|
|
256
|
+
const transactionConfig = await (0, _web.getERC20SpendingApprovalTx)(routerContract, params.address, fromContract, evmApi);
|
|
257
|
+
const _data = {
|
|
258
|
+
spenderAddress: routerContract,
|
|
259
|
+
contractAddress: fromContract,
|
|
260
|
+
amount: params.quote.fromAmount,
|
|
261
|
+
owner: params.address,
|
|
262
|
+
chain: chain
|
|
263
|
+
};
|
|
264
|
+
return Promise.resolve({
|
|
265
|
+
txChain: chain,
|
|
266
|
+
extrinsicType: _KoniTypes.ExtrinsicType.TOKEN_SPENDING_APPROVAL,
|
|
267
|
+
extrinsic: transactionConfig,
|
|
268
|
+
txData: _data,
|
|
269
|
+
transferNativeAmount: '0',
|
|
270
|
+
chainType: _KoniTypes.ChainType.EVM
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
async handleSubmitStep(params) {
|
|
274
|
+
var _params$recipient;
|
|
275
|
+
const fromAsset = this.chainService.getAssetBySlug(params.quote.pair.from);
|
|
276
|
+
const toAsset = this.chainService.getAssetBySlug(params.quote.pair.to);
|
|
277
|
+
const chainInfo = this.chainService.getChainInfoByKey(fromAsset.originChain);
|
|
278
|
+
const toChainInfo = this.chainService.getChainInfoByKey(toAsset.originChain);
|
|
279
|
+
const sender = (0, _utils._reformatAddressWithChain)(params.address, chainInfo);
|
|
280
|
+
const recipient = (0, _utils._reformatAddressWithChain)((_params$recipient = params.recipient) !== null && _params$recipient !== void 0 ? _params$recipient : sender, toChainInfo);
|
|
281
|
+
const metadata = params.quote.metadata;
|
|
282
|
+
const slippageTolerance = params.slippage * 10000;
|
|
283
|
+
const rawTx = await buildTxForSwap({
|
|
284
|
+
routeSummary: metadata.routeSummary,
|
|
285
|
+
sender: params.address,
|
|
286
|
+
recipient,
|
|
287
|
+
slippageTolerance
|
|
288
|
+
}, metadata.network);
|
|
289
|
+
if (rawTx.error) {
|
|
290
|
+
console.error('Kyber error:', rawTx.error);
|
|
291
|
+
throw rawTx.error;
|
|
292
|
+
}
|
|
293
|
+
const evmApi = this.chainService.getEvmApi(fromAsset.originChain);
|
|
294
|
+
const priority = await (0, _utils3.calculateGasFeeParams)(evmApi, evmApi.chainSlug);
|
|
295
|
+
const fee = (0, _utils.combineEthFee)(priority);
|
|
296
|
+
const transactionConfig = {
|
|
297
|
+
...rawTx.data,
|
|
298
|
+
...fee
|
|
299
|
+
};
|
|
300
|
+
const txData = {
|
|
301
|
+
address: params.address,
|
|
302
|
+
provider: this.providerInfo,
|
|
303
|
+
quote: params.quote,
|
|
304
|
+
slippage: params.slippage,
|
|
305
|
+
recipient: params.recipient,
|
|
306
|
+
process: params.process
|
|
307
|
+
};
|
|
308
|
+
return {
|
|
309
|
+
txChain: fromAsset.originChain,
|
|
310
|
+
txData,
|
|
311
|
+
extrinsic: transactionConfig,
|
|
312
|
+
transferNativeAmount: (0, _utils2._isNativeToken)(fromAsset) ? params.quote.fromAmount : '0',
|
|
313
|
+
extrinsicType: _KoniTypes.ExtrinsicType.SWAP,
|
|
314
|
+
chainType: _KoniTypes.ChainType.EVM
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
async validateSwapProcessV2(params) {
|
|
318
|
+
// todo: recheck address and recipient format in params
|
|
319
|
+
const {
|
|
320
|
+
process,
|
|
321
|
+
selectedQuote
|
|
322
|
+
} = params; // todo: review flow, currentStep param.
|
|
323
|
+
|
|
324
|
+
// todo: validate path with optimalProcess
|
|
325
|
+
// todo: review error message in case many step swap
|
|
326
|
+
if ((0, _bignumber.default)(selectedQuote.fromAmount).lte(0)) {
|
|
327
|
+
return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')];
|
|
328
|
+
}
|
|
329
|
+
const actionList = JSON.stringify(process.path.map(step => step.action));
|
|
330
|
+
const swap = actionList === JSON.stringify([_types.DynamicSwapType.SWAP]);
|
|
331
|
+
const swapXcm = actionList === JSON.stringify([_types.DynamicSwapType.SWAP, _types.DynamicSwapType.BRIDGE]);
|
|
332
|
+
const xcmSwap = actionList === JSON.stringify([_types.DynamicSwapType.BRIDGE, _types.DynamicSwapType.SWAP]);
|
|
333
|
+
const xcmSwapXcm = actionList === JSON.stringify([_types.DynamicSwapType.BRIDGE, _types.DynamicSwapType.SWAP, _types.DynamicSwapType.BRIDGE]);
|
|
334
|
+
const swapIndex = params.process.steps.findIndex(step => step.type === _types.SwapStepType.SWAP); // todo
|
|
335
|
+
|
|
336
|
+
if (swapIndex <= -1) {
|
|
337
|
+
return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
|
|
338
|
+
}
|
|
339
|
+
if (swap) {
|
|
340
|
+
return this.swapBaseHandler.validateSwapOnlyProcess(params, swapIndex); // todo: create interface for input request
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (swapXcm) {
|
|
344
|
+
return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
|
|
345
|
+
}
|
|
346
|
+
if (xcmSwap) {
|
|
347
|
+
return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
|
|
348
|
+
}
|
|
349
|
+
if (xcmSwapXcm) {
|
|
350
|
+
return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
|
|
351
|
+
}
|
|
352
|
+
return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
exports.KyberHandler = KyberHandler;
|