@subwallet/extension-base 1.3.35-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 +8 -0
- package/cjs/koni/background/handlers/Extension.js +21 -0
- package/cjs/packageInfo.js +1 -1
- 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 +209 -40
- package/cjs/services/swap-service/index.js +28 -2
- package/cjs/services/swap-service/utils.js +4 -1
- package/cjs/services/transaction-service/index.js +252 -28
- package/cjs/types/swap/index.js +2 -1
- package/koni/background/handlers/Extension.js +21 -0
- package/package.json +11 -6
- package/packageInfo.js +1 -1
- package/services/event-service/types.d.ts +6 -6
- 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 +209 -40
- package/services/swap-service/index.js +28 -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 +234 -12
- package/services/transaction-service/types.d.ts +23 -10
- package/types/swap/index.d.ts +4 -1
- package/types/swap/index.js +2 -1
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
|
|
5
|
+
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
6
|
+
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
7
|
+
import { estimateTxFee, getERC20Allowance, getERC20SpendingApprovalTx } from '@subwallet/extension-base/koni/api/contract-handler/evm/web3';
|
|
8
|
+
import { BasicTxErrorType, CommonStepType, DynamicSwapType, SwapErrorType, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
|
|
9
|
+
import { _reformatAddressWithChain, combineEthFee } from '@subwallet/extension-base/utils';
|
|
10
|
+
import { getId } from '@subwallet/extension-base/utils/getId';
|
|
11
|
+
import BigNumber from 'bignumber.js';
|
|
12
|
+
import { _getChainNativeTokenSlug, _getContractAddressOfToken, _isNativeToken } from "../../chain-service/utils/index.js";
|
|
13
|
+
import { calculateGasFeeParams } from "../../fee-service/utils/index.js";
|
|
14
|
+
import { SwapBaseHandler } from "./base-handler.js";
|
|
15
|
+
export const KYBER_CLIENT_ID = process.env.KYBER_CLIENT_ID || '';
|
|
16
|
+
const kyberUrl = 'https://aggregator-api.kyberswap.com';
|
|
17
|
+
async function buildTxForSwap(params, chain) {
|
|
18
|
+
const {
|
|
19
|
+
recipient,
|
|
20
|
+
sender,
|
|
21
|
+
slippageTolerance
|
|
22
|
+
} = params;
|
|
23
|
+
let routeSummary = params.routeSummary;
|
|
24
|
+
if (!routeSummary || !routeSummary.tokenIn || !routeSummary.tokenOut || !routeSummary.amountIn) {
|
|
25
|
+
const queryParams = new URLSearchParams({
|
|
26
|
+
tokenIn: routeSummary.tokenIn,
|
|
27
|
+
tokenOut: routeSummary.tokenOut,
|
|
28
|
+
amountIn: routeSummary.amountIn,
|
|
29
|
+
gasInclude: 'true'
|
|
30
|
+
});
|
|
31
|
+
const url = `${kyberUrl}/${chain}/api/v1/routes?${queryParams.toString()}`;
|
|
32
|
+
try {
|
|
33
|
+
var _routeData$data;
|
|
34
|
+
const res = await fetch(url, {
|
|
35
|
+
method: 'GET',
|
|
36
|
+
headers: {
|
|
37
|
+
'Content-Type': 'application/json',
|
|
38
|
+
'x-client-id': KYBER_CLIENT_ID,
|
|
39
|
+
accept: 'application/json'
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
const routeData = await res.json();
|
|
43
|
+
if (!routeData.success || !((_routeData$data = routeData.data) !== null && _routeData$data !== void 0 && _routeData$data.routeSummary)) {
|
|
44
|
+
return {
|
|
45
|
+
error: new TransactionError(BasicTxErrorType.INTERNAL_ERROR, routeData.message)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
routeSummary = routeData.data.routeSummary;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('Error:', error);
|
|
51
|
+
return {
|
|
52
|
+
error: new TransactionError(BasicTxErrorType.INTERNAL_ERROR)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const body = {
|
|
57
|
+
routeSummary,
|
|
58
|
+
sender,
|
|
59
|
+
recipient,
|
|
60
|
+
slippageTolerance,
|
|
61
|
+
ignoreCappedSlippage: true,
|
|
62
|
+
enableGasEstimation: true
|
|
63
|
+
};
|
|
64
|
+
try {
|
|
65
|
+
const res = await fetch(`${kyberUrl}/${chain}/api/v1/route/build`, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: {
|
|
68
|
+
'Content-Type': 'application/json',
|
|
69
|
+
'x-client-id': KYBER_CLIENT_ID,
|
|
70
|
+
accept: 'application/json'
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify(body)
|
|
73
|
+
});
|
|
74
|
+
const data = await res.json();
|
|
75
|
+
const requestData = data.data;
|
|
76
|
+
if (!requestData || !requestData.routerAddress || !requestData.data || !requestData.gas) {
|
|
77
|
+
var _data$details$map, _data$details, _data$message$toLower, _data$message;
|
|
78
|
+
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 : [];
|
|
79
|
+
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 : '';
|
|
80
|
+
if (lowerDetails.some(d => d.includes('insufficient liquidity'))) {
|
|
81
|
+
return {
|
|
82
|
+
error: new SwapError(SwapErrorType.NOT_ENOUGH_LIQUIDITY)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (lowerDetails.some(d => d.includes('execution reverted')) || msg.includes('smaller than estimated')) {
|
|
86
|
+
return {
|
|
87
|
+
error: new SwapError(SwapErrorType.NOT_MEET_MIN_EXPECTED)
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
error: new TransactionError(BasicTxErrorType.INTERNAL_ERROR, data.message)
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
data: {
|
|
96
|
+
from: sender,
|
|
97
|
+
to: requestData.routerAddress,
|
|
98
|
+
value: requestData.transactionValue,
|
|
99
|
+
data: requestData.data,
|
|
100
|
+
gas: requestData.gas
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error('Kyber error:', error);
|
|
105
|
+
return {
|
|
106
|
+
error: new TransactionError(BasicTxErrorType.INTERNAL_ERROR)
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export class KyberHandler {
|
|
111
|
+
constructor(chainService, balanceService, transactionService, feeService) {
|
|
112
|
+
this.swapBaseHandler = new SwapBaseHandler({
|
|
113
|
+
chainService,
|
|
114
|
+
balanceService,
|
|
115
|
+
feeService,
|
|
116
|
+
providerName: 'Kyber',
|
|
117
|
+
providerSlug: SwapProviderId.KYBER
|
|
118
|
+
});
|
|
119
|
+
this.transactionService = transactionService;
|
|
120
|
+
this.providerSlug = SwapProviderId.KYBER;
|
|
121
|
+
}
|
|
122
|
+
get chainService() {
|
|
123
|
+
return this.swapBaseHandler.chainService;
|
|
124
|
+
}
|
|
125
|
+
get balanceService() {
|
|
126
|
+
return this.swapBaseHandler.balanceService;
|
|
127
|
+
}
|
|
128
|
+
get feeService() {
|
|
129
|
+
return this.swapBaseHandler.feeService;
|
|
130
|
+
}
|
|
131
|
+
get providerInfo() {
|
|
132
|
+
return this.swapBaseHandler.providerInfo;
|
|
133
|
+
}
|
|
134
|
+
generateOptimalProcessV2(params) {
|
|
135
|
+
return this.swapBaseHandler.generateOptimalProcessV2(params, [this.getApprovalStep.bind(this), this.getSubmitStep.bind(this)]);
|
|
136
|
+
}
|
|
137
|
+
async getApprovalStep(params) {
|
|
138
|
+
const selectedQuote = params.selectedQuote;
|
|
139
|
+
if (selectedQuote) {
|
|
140
|
+
const fromAsset = this.chainService.getAssetBySlug(selectedQuote.pair.from);
|
|
141
|
+
if (_isNativeToken(fromAsset)) {
|
|
142
|
+
return Promise.resolve(undefined);
|
|
143
|
+
}
|
|
144
|
+
const metadata = selectedQuote.metadata;
|
|
145
|
+
const routerContract = metadata.routerAddress;
|
|
146
|
+
const evmApi = this.chainService.getEvmApi(fromAsset.originChain);
|
|
147
|
+
const fromContractAddress = _getContractAddressOfToken(fromAsset);
|
|
148
|
+
const allowance = await getERC20Allowance(routerContract, params.request.address, fromContractAddress, evmApi);
|
|
149
|
+
if (allowance && new BigNumber(allowance).gt(params.request.fromAmount)) {
|
|
150
|
+
return Promise.resolve(undefined);
|
|
151
|
+
}
|
|
152
|
+
const sendingAmount = selectedQuote.toAmount;
|
|
153
|
+
const senderAddress = params.request.address;
|
|
154
|
+
const fromTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.from);
|
|
155
|
+
const tokenContract = _getContractAddressOfToken(fromTokenInfo);
|
|
156
|
+
const spenderAddress = metadata.routerAddress;
|
|
157
|
+
const submitStep = {
|
|
158
|
+
name: 'Approve token',
|
|
159
|
+
type: CommonStepType.TOKEN_APPROVAL,
|
|
160
|
+
metadata: {
|
|
161
|
+
tokenApprove: fromTokenInfo.slug,
|
|
162
|
+
contractAddress: tokenContract,
|
|
163
|
+
spenderAddress: spenderAddress,
|
|
164
|
+
amount: sendingAmount,
|
|
165
|
+
owner: senderAddress
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const tx = await getERC20SpendingApprovalTx(spenderAddress, senderAddress, tokenContract, evmApi);
|
|
169
|
+
const evmFeeInfo = await this.feeService.subscribeChainFee(getId(), fromTokenInfo.originChain, 'evm');
|
|
170
|
+
const estimatedFee = await estimateTxFee(tx, evmApi, evmFeeInfo);
|
|
171
|
+
const fromChainInfo = this.chainService.getChainInfoByKey(fromTokenInfo.originChain);
|
|
172
|
+
const nativeTokenSlug = _getChainNativeTokenSlug(fromChainInfo);
|
|
173
|
+
const feeInfo = {
|
|
174
|
+
feeComponent: [{
|
|
175
|
+
feeType: SwapFeeType.NETWORK_FEE,
|
|
176
|
+
amount: estimatedFee,
|
|
177
|
+
tokenSlug: nativeTokenSlug
|
|
178
|
+
}],
|
|
179
|
+
defaultFeeToken: nativeTokenSlug,
|
|
180
|
+
feeOptions: [nativeTokenSlug]
|
|
181
|
+
};
|
|
182
|
+
return Promise.resolve([submitStep, feeInfo]);
|
|
183
|
+
}
|
|
184
|
+
return Promise.resolve(undefined);
|
|
185
|
+
}
|
|
186
|
+
async getSubmitStep(params, stepIndex) {
|
|
187
|
+
const {
|
|
188
|
+
path,
|
|
189
|
+
request,
|
|
190
|
+
selectedQuote
|
|
191
|
+
} = params;
|
|
192
|
+
|
|
193
|
+
// stepIndex is not corresponding index in path, because uniswap include approval and permit step
|
|
194
|
+
const stepData = path.find(action => action.action === DynamicSwapType.SWAP);
|
|
195
|
+
if (!stepData || !stepData.pair) {
|
|
196
|
+
return Promise.resolve(undefined);
|
|
197
|
+
}
|
|
198
|
+
if (!selectedQuote) {
|
|
199
|
+
return Promise.resolve(undefined);
|
|
200
|
+
}
|
|
201
|
+
const originTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.from);
|
|
202
|
+
const destinationTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.to);
|
|
203
|
+
const originChain = this.chainService.getChainInfoByKey(originTokenInfo.originChain);
|
|
204
|
+
const destinationChain = this.chainService.getChainInfoByKey(destinationTokenInfo.originChain);
|
|
205
|
+
const submitStep = {
|
|
206
|
+
name: 'Swap',
|
|
207
|
+
type: SwapStepType.SWAP,
|
|
208
|
+
// @ts-ignore
|
|
209
|
+
metadata: {
|
|
210
|
+
sendingValue: request.fromAmount.toString(),
|
|
211
|
+
expectedReceive: selectedQuote.toAmount,
|
|
212
|
+
originTokenInfo,
|
|
213
|
+
destinationTokenInfo,
|
|
214
|
+
sender: _reformatAddressWithChain(request.address, originChain),
|
|
215
|
+
receiver: _reformatAddressWithChain(request.recipient || request.address, destinationChain),
|
|
216
|
+
version: 2
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
return Promise.resolve([submitStep, selectedQuote.feeInfo]);
|
|
220
|
+
}
|
|
221
|
+
async handleSwapProcess(params) {
|
|
222
|
+
const {
|
|
223
|
+
currentStep,
|
|
224
|
+
process
|
|
225
|
+
} = params;
|
|
226
|
+
const type = process.steps[currentStep].type;
|
|
227
|
+
switch (type) {
|
|
228
|
+
case CommonStepType.DEFAULT:
|
|
229
|
+
return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
|
|
230
|
+
case CommonStepType.TOKEN_APPROVAL:
|
|
231
|
+
return this.tokenApproveSpending(params);
|
|
232
|
+
case SwapStepType.SWAP:
|
|
233
|
+
return this.handleSubmitStep(params);
|
|
234
|
+
default:
|
|
235
|
+
return this.handleSubmitStep(params);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
async tokenApproveSpending(params) {
|
|
239
|
+
const fromAsset = this.chainService.getAssetBySlug(params.quote.pair.from);
|
|
240
|
+
const fromContract = _getContractAddressOfToken(fromAsset);
|
|
241
|
+
const evmApi = this.chainService.getEvmApi(fromAsset.originChain);
|
|
242
|
+
const chain = fromAsset.originChain;
|
|
243
|
+
const metadata = params.quote.metadata;
|
|
244
|
+
if (!metadata || !metadata.routerAddress) {
|
|
245
|
+
throw new TransactionError(BasicTxErrorType.INVALID_PARAMS);
|
|
246
|
+
}
|
|
247
|
+
const routerContract = metadata.routerAddress;
|
|
248
|
+
const transactionConfig = await getERC20SpendingApprovalTx(routerContract, params.address, fromContract, evmApi);
|
|
249
|
+
const _data = {
|
|
250
|
+
spenderAddress: routerContract,
|
|
251
|
+
contractAddress: fromContract,
|
|
252
|
+
amount: params.quote.fromAmount,
|
|
253
|
+
owner: params.address,
|
|
254
|
+
chain: chain
|
|
255
|
+
};
|
|
256
|
+
return Promise.resolve({
|
|
257
|
+
txChain: chain,
|
|
258
|
+
extrinsicType: ExtrinsicType.TOKEN_SPENDING_APPROVAL,
|
|
259
|
+
extrinsic: transactionConfig,
|
|
260
|
+
txData: _data,
|
|
261
|
+
transferNativeAmount: '0',
|
|
262
|
+
chainType: ChainType.EVM
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
async handleSubmitStep(params) {
|
|
266
|
+
var _params$recipient;
|
|
267
|
+
const fromAsset = this.chainService.getAssetBySlug(params.quote.pair.from);
|
|
268
|
+
const toAsset = this.chainService.getAssetBySlug(params.quote.pair.to);
|
|
269
|
+
const chainInfo = this.chainService.getChainInfoByKey(fromAsset.originChain);
|
|
270
|
+
const toChainInfo = this.chainService.getChainInfoByKey(toAsset.originChain);
|
|
271
|
+
const sender = _reformatAddressWithChain(params.address, chainInfo);
|
|
272
|
+
const recipient = _reformatAddressWithChain((_params$recipient = params.recipient) !== null && _params$recipient !== void 0 ? _params$recipient : sender, toChainInfo);
|
|
273
|
+
const metadata = params.quote.metadata;
|
|
274
|
+
const slippageTolerance = params.slippage * 10000;
|
|
275
|
+
const rawTx = await buildTxForSwap({
|
|
276
|
+
routeSummary: metadata.routeSummary,
|
|
277
|
+
sender: params.address,
|
|
278
|
+
recipient,
|
|
279
|
+
slippageTolerance
|
|
280
|
+
}, metadata.network);
|
|
281
|
+
if (rawTx.error) {
|
|
282
|
+
console.error('Kyber error:', rawTx.error);
|
|
283
|
+
throw rawTx.error;
|
|
284
|
+
}
|
|
285
|
+
const evmApi = this.chainService.getEvmApi(fromAsset.originChain);
|
|
286
|
+
const priority = await calculateGasFeeParams(evmApi, evmApi.chainSlug);
|
|
287
|
+
const fee = combineEthFee(priority);
|
|
288
|
+
const transactionConfig = {
|
|
289
|
+
...rawTx.data,
|
|
290
|
+
...fee
|
|
291
|
+
};
|
|
292
|
+
const txData = {
|
|
293
|
+
address: params.address,
|
|
294
|
+
provider: this.providerInfo,
|
|
295
|
+
quote: params.quote,
|
|
296
|
+
slippage: params.slippage,
|
|
297
|
+
recipient: params.recipient,
|
|
298
|
+
process: params.process
|
|
299
|
+
};
|
|
300
|
+
return {
|
|
301
|
+
txChain: fromAsset.originChain,
|
|
302
|
+
txData,
|
|
303
|
+
extrinsic: transactionConfig,
|
|
304
|
+
transferNativeAmount: _isNativeToken(fromAsset) ? params.quote.fromAmount : '0',
|
|
305
|
+
extrinsicType: ExtrinsicType.SWAP,
|
|
306
|
+
chainType: ChainType.EVM
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
async validateSwapProcessV2(params) {
|
|
310
|
+
// todo: recheck address and recipient format in params
|
|
311
|
+
const {
|
|
312
|
+
process,
|
|
313
|
+
selectedQuote
|
|
314
|
+
} = params; // todo: review flow, currentStep param.
|
|
315
|
+
|
|
316
|
+
// todo: validate path with optimalProcess
|
|
317
|
+
// todo: review error message in case many step swap
|
|
318
|
+
if (BigNumber(selectedQuote.fromAmount).lte(0)) {
|
|
319
|
+
return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')];
|
|
320
|
+
}
|
|
321
|
+
const actionList = JSON.stringify(process.path.map(step => step.action));
|
|
322
|
+
const swap = actionList === JSON.stringify([DynamicSwapType.SWAP]);
|
|
323
|
+
const swapXcm = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
|
|
324
|
+
const xcmSwap = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP]);
|
|
325
|
+
const xcmSwapXcm = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
|
|
326
|
+
const swapIndex = params.process.steps.findIndex(step => step.type === SwapStepType.SWAP); // todo
|
|
327
|
+
|
|
328
|
+
if (swapIndex <= -1) {
|
|
329
|
+
return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
|
|
330
|
+
}
|
|
331
|
+
if (swap) {
|
|
332
|
+
return this.swapBaseHandler.validateSwapOnlyProcess(params, swapIndex); // todo: create interface for input request
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (swapXcm) {
|
|
336
|
+
return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
|
|
337
|
+
}
|
|
338
|
+
if (xcmSwap) {
|
|
339
|
+
return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
|
|
340
|
+
}
|
|
341
|
+
if (xcmSwapXcm) {
|
|
342
|
+
return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
|
|
343
|
+
}
|
|
344
|
+
return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
|
|
345
|
+
}
|
|
346
|
+
}
|
|
@@ -12,6 +12,53 @@ export declare type PermitData = {
|
|
|
12
12
|
types: Record<string, unknown>;
|
|
13
13
|
values: unknown;
|
|
14
14
|
};
|
|
15
|
+
export interface UniswapMetadata {
|
|
16
|
+
permitData: PermitData;
|
|
17
|
+
quote: UniswapQuote;
|
|
18
|
+
routing: string;
|
|
19
|
+
}
|
|
20
|
+
declare type UniswapQuote = UniswapClassicQuote | UniswapDutchQuote;
|
|
21
|
+
interface UniswapClassicQuote {
|
|
22
|
+
swapper: string;
|
|
23
|
+
chainId: number;
|
|
24
|
+
input: {
|
|
25
|
+
amount: string;
|
|
26
|
+
token: string;
|
|
27
|
+
};
|
|
28
|
+
output: {
|
|
29
|
+
amount: string;
|
|
30
|
+
token: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
interface UniswapDutchQuote {
|
|
34
|
+
orderInfo: {
|
|
35
|
+
swapper: string;
|
|
36
|
+
chainId: number;
|
|
37
|
+
input: UniswapDutchInput;
|
|
38
|
+
outputs: UniswapDutchOutput[];
|
|
39
|
+
};
|
|
40
|
+
orderId: string;
|
|
41
|
+
}
|
|
42
|
+
interface UniswapDutchInput {
|
|
43
|
+
startAmount: string;
|
|
44
|
+
endAmount: string;
|
|
45
|
+
token: string;
|
|
46
|
+
}
|
|
47
|
+
interface UniswapDutchOutput {
|
|
48
|
+
startAmount: string;
|
|
49
|
+
endAmount: string;
|
|
50
|
+
token: string;
|
|
51
|
+
recipient: string;
|
|
52
|
+
}
|
|
53
|
+
export interface UniswapOrders {
|
|
54
|
+
orders: UniswapOrderInfo[];
|
|
55
|
+
}
|
|
56
|
+
export interface UniswapOrderInfo {
|
|
57
|
+
orderStatus: 'open' | 'expired' | 'error' | 'cancelled' | 'filled' | 'unverified' | 'insufficient-funds';
|
|
58
|
+
orderId: string;
|
|
59
|
+
swapper: string;
|
|
60
|
+
txHash: string;
|
|
61
|
+
}
|
|
15
62
|
export declare class UniswapHandler implements SwapBaseInterface {
|
|
16
63
|
private swapBaseHandler;
|
|
17
64
|
transactionService: TransactionService;
|
|
@@ -44,3 +91,4 @@ export declare class UniswapHandler implements SwapBaseInterface {
|
|
|
44
91
|
};
|
|
45
92
|
validateSwapProcessV2(params: ValidateSwapProcessParams): Promise<TransactionError[]>;
|
|
46
93
|
}
|
|
94
|
+
export {};
|