@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
|
@@ -6,7 +6,7 @@ import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/K
|
|
|
6
6
|
import { validateTypedSignMessageDataV3V4 } from '@subwallet/extension-base/core/logic-validation';
|
|
7
7
|
import { estimateTxFee, getERC20Allowance, getERC20SpendingApprovalTx } from '@subwallet/extension-base/koni/api/contract-handler/evm/web3';
|
|
8
8
|
import { createAcrossBridgeExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
|
|
9
|
-
import {
|
|
9
|
+
import { getAcrossQuote } from '@subwallet/extension-base/services/balance-service/transfer/xcm/acrossBridge';
|
|
10
10
|
import { BasicTxErrorType, CommonStepType, DynamicSwapType, FeeOptionKey, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
|
|
11
11
|
import { _reformatAddressWithChain } from '@subwallet/extension-base/utils';
|
|
12
12
|
import { getId } from '@subwallet/extension-base/utils/getId';
|
|
@@ -18,8 +18,36 @@ const API_URL = 'https://trade-api.gateway.uniswap.org/v1';
|
|
|
18
18
|
const headers = {
|
|
19
19
|
'x-api-key': process.env.UNISWAP_API_KEY || ''
|
|
20
20
|
};
|
|
21
|
-
async function fetchCheckApproval(
|
|
22
|
-
const
|
|
21
|
+
async function fetchCheckApproval(request) {
|
|
22
|
+
const {
|
|
23
|
+
address,
|
|
24
|
+
amount,
|
|
25
|
+
classicQuote,
|
|
26
|
+
dutchQuote
|
|
27
|
+
} = request;
|
|
28
|
+
let chainId;
|
|
29
|
+
let tokenIn;
|
|
30
|
+
let tokenOut;
|
|
31
|
+
if (classicQuote) {
|
|
32
|
+
chainId = classicQuote.chainId;
|
|
33
|
+
tokenIn = classicQuote.input.token;
|
|
34
|
+
tokenOut = classicQuote.output.token;
|
|
35
|
+
} else if (dutchQuote) {
|
|
36
|
+
/**
|
|
37
|
+
* In Dutch order swap, the outputs field is an array instead of a single output since it might contain filler's output to pay fee.
|
|
38
|
+
* Need to filter exactly output that come to recipient address.
|
|
39
|
+
*/
|
|
40
|
+
const output = dutchQuote.orderInfo.outputs.find(output => output.recipient.toLowerCase() === address.toLowerCase());
|
|
41
|
+
if (!output) {
|
|
42
|
+
return undefined; // todo: recheck
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
chainId = dutchQuote.orderInfo.chainId;
|
|
46
|
+
tokenIn = dutchQuote.orderInfo.input.token;
|
|
47
|
+
tokenOut = output.token;
|
|
48
|
+
} else {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
23
51
|
const response = await fetch(`${API_URL}/check_approval`, {
|
|
24
52
|
method: 'POST',
|
|
25
53
|
headers: {
|
|
@@ -27,16 +55,16 @@ async function fetchCheckApproval(walletAddress, fromAmount, quote) {
|
|
|
27
55
|
'Content-Type': 'application/json'
|
|
28
56
|
},
|
|
29
57
|
body: JSON.stringify({
|
|
30
|
-
walletAddress,
|
|
31
|
-
amount: BigNumber(
|
|
32
|
-
token:
|
|
58
|
+
walletAddress: address,
|
|
59
|
+
amount: BigNumber(amount).multipliedBy(2).toFixed(0),
|
|
60
|
+
token: tokenIn,
|
|
33
61
|
chainId: chainId,
|
|
34
|
-
tokenOut:
|
|
35
|
-
tokenOutChainId: chainId
|
|
62
|
+
tokenOut: tokenOut,
|
|
63
|
+
tokenOutChainId: chainId // swap in-chain
|
|
36
64
|
})
|
|
37
65
|
});
|
|
38
|
-
|
|
39
|
-
return
|
|
66
|
+
|
|
67
|
+
return await response.json();
|
|
40
68
|
}
|
|
41
69
|
export class UniswapHandler {
|
|
42
70
|
constructor(chainService, balanceService, transactionService, feeService) {
|
|
@@ -96,11 +124,38 @@ export class UniswapHandler {
|
|
|
96
124
|
if (!selectedQuote) {
|
|
97
125
|
return Promise.resolve(undefined);
|
|
98
126
|
}
|
|
99
|
-
const quoteMetadata = selectedQuote.metadata
|
|
100
|
-
|
|
101
|
-
|
|
127
|
+
const quoteMetadata = selectedQuote.metadata;
|
|
128
|
+
let sender;
|
|
129
|
+
let sendingValue;
|
|
130
|
+
let checkApprovalResponse;
|
|
131
|
+
if (quoteMetadata.routing === 'CLASSIC') {
|
|
132
|
+
const quote = quoteMetadata.quote;
|
|
133
|
+
sender = quote.swapper;
|
|
134
|
+
sendingValue = quote.input.amount;
|
|
135
|
+
checkApprovalResponse = await fetchCheckApproval({
|
|
136
|
+
address: sender,
|
|
137
|
+
amount: sendingValue,
|
|
138
|
+
classicQuote: quote
|
|
139
|
+
});
|
|
140
|
+
} else if (quoteMetadata.routing === 'DUTCH_LIMIT' || quoteMetadata.routing === 'DUTCH_V2') {
|
|
141
|
+
const quote = quoteMetadata.quote;
|
|
142
|
+
sender = quote.orderInfo.swapper;
|
|
143
|
+
sendingValue = quote.orderInfo.input.startAmount;
|
|
144
|
+
checkApprovalResponse = await fetchCheckApproval({
|
|
145
|
+
address: sender,
|
|
146
|
+
amount: sendingValue,
|
|
147
|
+
dutchQuote: quote
|
|
148
|
+
});
|
|
149
|
+
} else {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
if (!checkApprovalResponse) {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
102
155
|
const fromTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.from);
|
|
103
|
-
const
|
|
156
|
+
const fromChainInfo = this.chainService.getChainInfoByKey(_getAssetOriginChain(fromTokenInfo));
|
|
157
|
+
const evmApi = this.chainService.getEvmApi(fromChainInfo.slug);
|
|
158
|
+
const tokenContract = _getContractAddressOfToken(fromTokenInfo);
|
|
104
159
|
const approval = checkApprovalResponse.approval;
|
|
105
160
|
if (!approval) {
|
|
106
161
|
return Promise.resolve(undefined);
|
|
@@ -112,27 +167,41 @@ export class UniswapHandler {
|
|
|
112
167
|
} catch (e) {
|
|
113
168
|
// Empty
|
|
114
169
|
}
|
|
170
|
+
const tx = await getERC20SpendingApprovalTx(spender, sender, tokenContract, evmApi);
|
|
171
|
+
const evmFeeInfo = await this.feeService.subscribeChainFee(getId(), fromTokenInfo.originChain, 'evm');
|
|
172
|
+
const estimatedFee = await estimateTxFee(tx, evmApi, evmFeeInfo);
|
|
173
|
+
const nativeTokenSlug = _getChainNativeTokenSlug(fromChainInfo);
|
|
174
|
+
const feeInfo = {
|
|
175
|
+
feeComponent: [{
|
|
176
|
+
feeType: SwapFeeType.NETWORK_FEE,
|
|
177
|
+
amount: estimatedFee,
|
|
178
|
+
tokenSlug: nativeTokenSlug
|
|
179
|
+
}],
|
|
180
|
+
defaultFeeToken: nativeTokenSlug,
|
|
181
|
+
feeOptions: [nativeTokenSlug]
|
|
182
|
+
};
|
|
115
183
|
const submitStep = {
|
|
116
184
|
name: 'Approve token for swap',
|
|
117
185
|
type: CommonStepType.TOKEN_APPROVAL,
|
|
118
186
|
// @ts-ignore
|
|
119
187
|
metadata: {
|
|
120
188
|
tokenApprove: fromTokenInfo.slug,
|
|
121
|
-
contractAddress: _getContractAddressOfToken(fromTokenInfo),
|
|
189
|
+
contractAddress: _getContractAddressOfToken(fromTokenInfo) || approval.to,
|
|
122
190
|
spenderAddress: spender,
|
|
123
191
|
owner: sender,
|
|
192
|
+
// todo: use approval.from?
|
|
124
193
|
amount: sendingValue,
|
|
125
194
|
isUniswapApprove: true
|
|
126
195
|
}
|
|
127
196
|
};
|
|
128
|
-
return Promise.resolve([submitStep,
|
|
197
|
+
return Promise.resolve([submitStep, feeInfo]);
|
|
129
198
|
}
|
|
130
|
-
|
|
131
199
|
async getApproveBridge(params) {
|
|
132
200
|
const quote = params.selectedQuote;
|
|
133
201
|
if (!quote) {
|
|
134
202
|
return Promise.resolve(undefined);
|
|
135
203
|
}
|
|
204
|
+
console.log('params', params);
|
|
136
205
|
const sendingAmount = quote.toAmount;
|
|
137
206
|
const senderAddress = params.request.address;
|
|
138
207
|
const fromTokenInfo = this.chainService.getAssetBySlug(quote.pair.to);
|
|
@@ -140,13 +209,25 @@ export class UniswapHandler {
|
|
|
140
209
|
const fromChainId = _getEvmChainId(fromChainInfo);
|
|
141
210
|
const evmApi = this.chainService.getEvmApi(fromChainInfo.slug);
|
|
142
211
|
const tokenContract = _getContractAddressOfToken(fromTokenInfo);
|
|
212
|
+
const toTokenInfo = this.chainService.getAssetBySlug(params.request.pair.to);
|
|
213
|
+
const toChainInfo = this.chainService.getChainInfoByKey(_getAssetOriginChain(toTokenInfo));
|
|
143
214
|
if (_isNativeToken(fromTokenInfo)) {
|
|
144
215
|
return Promise.resolve(undefined);
|
|
145
216
|
}
|
|
146
217
|
if (!fromChainId) {
|
|
147
218
|
throw Error('Error getting Evm chain Id');
|
|
148
219
|
}
|
|
149
|
-
const
|
|
220
|
+
const inputData = {
|
|
221
|
+
destinationTokenInfo: toTokenInfo,
|
|
222
|
+
originTokenInfo: fromTokenInfo,
|
|
223
|
+
sendingValue: sendingAmount,
|
|
224
|
+
sender: senderAddress,
|
|
225
|
+
recipient: senderAddress,
|
|
226
|
+
destinationChain: toChainInfo,
|
|
227
|
+
originChain: fromChainInfo
|
|
228
|
+
};
|
|
229
|
+
const acrossQuote = await getAcrossQuote(inputData);
|
|
230
|
+
const spokePoolAddress = acrossQuote.to;
|
|
150
231
|
const allowance = await getERC20Allowance(spokePoolAddress, senderAddress, tokenContract, evmApi);
|
|
151
232
|
if (allowance && BigNumber(allowance).gt(sendingAmount)) {
|
|
152
233
|
return Promise.resolve(undefined);
|
|
@@ -355,14 +436,38 @@ export class UniswapHandler {
|
|
|
355
436
|
if (!sender || !sendingValue) {
|
|
356
437
|
throw new Error('Sender or value is not found');
|
|
357
438
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
439
|
+
const quoteMetadata = params.quote.metadata;
|
|
440
|
+
let spenderAddress;
|
|
441
|
+
let contractAddress;
|
|
442
|
+
let chainId;
|
|
443
|
+
let checkApprovalResponse;
|
|
444
|
+
if (quoteMetadata.routing === 'CLASSIC') {
|
|
445
|
+
const quote = quoteMetadata.quote;
|
|
446
|
+
spenderAddress = quote.output.token;
|
|
447
|
+
contractAddress = quote.input.token;
|
|
448
|
+
chainId = quote.chainId.toString();
|
|
449
|
+
checkApprovalResponse = await fetchCheckApproval({
|
|
450
|
+
address: sender,
|
|
451
|
+
amount: sendingValue,
|
|
452
|
+
classicQuote: quote
|
|
453
|
+
});
|
|
454
|
+
} else if (quoteMetadata.routing === 'DUTCH_LIMIT' || quoteMetadata.routing === 'DUTCH_V2') {
|
|
455
|
+
const quote = quoteMetadata.quote;
|
|
456
|
+
spenderAddress = quote.orderInfo.outputs[0].token;
|
|
457
|
+
contractAddress = quote.orderInfo.input.token;
|
|
458
|
+
chainId = quote.orderInfo.chainId.toString();
|
|
459
|
+
checkApprovalResponse = await fetchCheckApproval({
|
|
460
|
+
address: sender,
|
|
461
|
+
amount: sendingValue,
|
|
462
|
+
dutchQuote: quote
|
|
463
|
+
});
|
|
464
|
+
} else {
|
|
465
|
+
throw Error('Unsupported quote route');
|
|
466
|
+
}
|
|
365
467
|
let transactionConfig = {};
|
|
468
|
+
if (!checkApprovalResponse) {
|
|
469
|
+
throw new Error('Check approval fail');
|
|
470
|
+
}
|
|
366
471
|
const approval = checkApprovalResponse.approval;
|
|
367
472
|
if (approval) {
|
|
368
473
|
var _priority$options, _priority$options$Fee, _priority$options2;
|
|
@@ -382,11 +487,11 @@ export class UniswapHandler {
|
|
|
382
487
|
}
|
|
383
488
|
const chain = fromAsset.originChain;
|
|
384
489
|
const _data = {
|
|
385
|
-
spenderAddress
|
|
386
|
-
contractAddress
|
|
490
|
+
spenderAddress,
|
|
491
|
+
contractAddress,
|
|
387
492
|
amount: params.quote.fromAmount,
|
|
388
493
|
owner: params.address,
|
|
389
|
-
chain:
|
|
494
|
+
chain: chainId
|
|
390
495
|
};
|
|
391
496
|
return Promise.resolve({
|
|
392
497
|
txChain: chain,
|
|
@@ -458,19 +563,93 @@ export class UniswapHandler {
|
|
|
458
563
|
const transactionResponse = await postTransactionResponse.json();
|
|
459
564
|
extrinsic = transactionResponse.swap;
|
|
460
565
|
} else if (routing === 'DUTCH_LIMIT' || routing === 'DUTCH_V2') {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
566
|
+
const dutchQuote = quote;
|
|
567
|
+
const submitSwapOrder = async () => {
|
|
568
|
+
try {
|
|
569
|
+
const res = await fetch(`${API_URL}/order`, {
|
|
570
|
+
method: 'POST',
|
|
571
|
+
headers: {
|
|
572
|
+
...headers,
|
|
573
|
+
'Content-Type': 'application/json'
|
|
574
|
+
},
|
|
575
|
+
body: JSON.stringify({
|
|
576
|
+
signature: signature,
|
|
577
|
+
quote: dutchQuote
|
|
578
|
+
})
|
|
579
|
+
});
|
|
580
|
+
return res.ok;
|
|
581
|
+
} catch (e) {
|
|
582
|
+
console.log(e);
|
|
583
|
+
return false;
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
const retryGetUniswapTx = async (fn, options) => {
|
|
587
|
+
let lastError;
|
|
588
|
+
for (let i = 0; i < options.retries; i++) {
|
|
589
|
+
try {
|
|
590
|
+
const orderInfo = await fn();
|
|
591
|
+
if (orderInfo && orderInfo.orderStatus === 'filled') {
|
|
592
|
+
return orderInfo;
|
|
593
|
+
}
|
|
594
|
+
await new Promise(resolve => setTimeout(resolve, options.delay));
|
|
595
|
+
} catch (e) {
|
|
596
|
+
if (e instanceof Error) {
|
|
597
|
+
lastError = e;
|
|
598
|
+
}
|
|
599
|
+
await new Promise(resolve => setTimeout(resolve, options.delay));
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
console.error('UniswapX order timeout', lastError); // throw only last error, in case no successful result from fn()
|
|
603
|
+
|
|
604
|
+
return undefined;
|
|
605
|
+
};
|
|
606
|
+
const cronCheckTxSuccess = async () => {
|
|
607
|
+
const delay = 10000;
|
|
608
|
+
const retries = 50;
|
|
609
|
+
const orderId = dutchQuote.orderId;
|
|
610
|
+
const swapper = dutchQuote.orderInfo.swapper;
|
|
611
|
+
return retryGetUniswapTx(async () => {
|
|
612
|
+
try {
|
|
613
|
+
const response = await fetch(`${API_URL}/orders?orderId=${orderId}&swapper=${swapper}`, {
|
|
614
|
+
method: 'GET',
|
|
615
|
+
headers: {
|
|
616
|
+
...headers,
|
|
617
|
+
'Content-Type': 'application/json'
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
if (response.ok) {
|
|
621
|
+
const res = await response.json();
|
|
622
|
+
return res.orders.find(e => e.orderId === orderId && e.swapper === swapper.toLowerCase());
|
|
623
|
+
}
|
|
624
|
+
return undefined;
|
|
625
|
+
} catch (e) {
|
|
626
|
+
return undefined;
|
|
627
|
+
}
|
|
628
|
+
}, {
|
|
629
|
+
retries,
|
|
630
|
+
delay
|
|
631
|
+
});
|
|
632
|
+
};
|
|
633
|
+
const txData = {
|
|
634
|
+
address: params.address,
|
|
635
|
+
provider: this.providerInfo,
|
|
636
|
+
quote: params.quote,
|
|
637
|
+
slippage: params.slippage,
|
|
638
|
+
recipient: params.recipient,
|
|
639
|
+
process: params.process
|
|
640
|
+
};
|
|
641
|
+
return {
|
|
642
|
+
txChain: fromAsset.originChain,
|
|
643
|
+
txData,
|
|
644
|
+
extrinsic: {
|
|
645
|
+
submitSwapOrder,
|
|
646
|
+
cronCheckTxSuccess
|
|
468
647
|
},
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
}
|
|
648
|
+
transferNativeAmount: _isNativeToken(fromAsset) ? params.quote.fromAmount : '0',
|
|
649
|
+
extrinsicType: ExtrinsicType.SWAP,
|
|
650
|
+
chainType: ChainType.EVM,
|
|
651
|
+
isDutch: true
|
|
652
|
+
};
|
|
474
653
|
}
|
|
475
654
|
const txData = {
|
|
476
655
|
address: params.address,
|
|
@@ -492,9 +671,12 @@ export class UniswapHandler {
|
|
|
492
671
|
handlePermitStep(params) {
|
|
493
672
|
const fromAsset = this.chainService.getAssetBySlug(params.quote.pair.from);
|
|
494
673
|
const {
|
|
495
|
-
permitData
|
|
674
|
+
permitData,
|
|
675
|
+
routing
|
|
496
676
|
} = params.quote.metadata;
|
|
497
677
|
const processId = params.cacheProcessId;
|
|
678
|
+
const primaryType = routing === 'CLASSIC' ? 'PermitSingle' : routing === 'DUTCH_LIMIT' || routing === 'DUTCH_V2' ? 'PermitWitnessTransferFrom' : ''; // todo
|
|
679
|
+
|
|
498
680
|
let validatePayload;
|
|
499
681
|
if (permitData) {
|
|
500
682
|
const payload = {
|
|
@@ -512,7 +694,7 @@ export class UniswapHandler {
|
|
|
512
694
|
...permitData.types
|
|
513
695
|
},
|
|
514
696
|
domain: permitData.domain,
|
|
515
|
-
primaryType
|
|
697
|
+
primaryType,
|
|
516
698
|
message: permitData.values
|
|
517
699
|
};
|
|
518
700
|
validatePayload = validateTypedSignMessageDataV3V4({
|
|
@@ -21,6 +21,7 @@ import subwalletApiSdk from '@subwallet/subwallet-api-sdk';
|
|
|
21
21
|
import BigN from 'bignumber.js';
|
|
22
22
|
import { t } from 'i18next';
|
|
23
23
|
import { BehaviorSubject } from 'rxjs';
|
|
24
|
+
import { KyberHandler } from "./handler/kyber-handler.js";
|
|
24
25
|
import { SimpleSwapHandler } from "./handler/simpleswap-handler.js";
|
|
25
26
|
import { UniswapHandler } from "./handler/uniswap-handler.js";
|
|
26
27
|
export class SwapService {
|
|
@@ -34,12 +35,21 @@ export class SwapService {
|
|
|
34
35
|
this.eventService = state.eventService;
|
|
35
36
|
this.chainService = state.chainService;
|
|
36
37
|
}
|
|
37
|
-
async askProvidersForQuote(
|
|
38
|
+
async askProvidersForQuote(_request) {
|
|
38
39
|
var _subwalletApiSdk$swap;
|
|
39
40
|
const availableQuotes = [];
|
|
41
|
+
|
|
42
|
+
// hotfix
|
|
43
|
+
const request = {
|
|
44
|
+
..._request,
|
|
45
|
+
isSupportKyberVersion: true
|
|
46
|
+
};
|
|
40
47
|
const quotes = await ((_subwalletApiSdk$swap = subwalletApiSdk.swapApi) === null || _subwalletApiSdk$swap === void 0 ? void 0 : _subwalletApiSdk$swap.fetchSwapQuoteData(request));
|
|
41
48
|
if (Array.isArray(quotes)) {
|
|
42
49
|
quotes.forEach(quoteData => {
|
|
50
|
+
if (!_SUPPORTED_SWAP_PROVIDERS.includes(quoteData.provider)) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
43
53
|
if (!quoteData.quote || Object.keys(quoteData.quote).length === 0) {
|
|
44
54
|
return;
|
|
45
55
|
}
|
|
@@ -113,6 +123,12 @@ export class SwapService {
|
|
|
113
123
|
console.group('Swap Logger');
|
|
114
124
|
console.log('path', path);
|
|
115
125
|
console.log('swapQuoteResponse', swapQuoteResponse);
|
|
126
|
+
if (swapQuoteResponse.optimalQuote && swapQuoteResponse.optimalQuote.metadata) {
|
|
127
|
+
const routing = swapQuoteResponse.optimalQuote.metadata.routing;
|
|
128
|
+
if (routing) {
|
|
129
|
+
console.log('Uniswap routing', routing);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
116
132
|
let optimalProcess;
|
|
117
133
|
try {
|
|
118
134
|
optimalProcess = await this.generateOptimalProcessV2({
|
|
@@ -123,6 +139,12 @@ export class SwapService {
|
|
|
123
139
|
} catch (e) {
|
|
124
140
|
throw new Error(e.message);
|
|
125
141
|
}
|
|
142
|
+
if (swapQuoteResponse.error) {
|
|
143
|
+
return {
|
|
144
|
+
process: optimalProcess,
|
|
145
|
+
quote: swapQuoteResponse
|
|
146
|
+
};
|
|
147
|
+
}
|
|
126
148
|
console.log('optimalProcess', optimalProcess);
|
|
127
149
|
console.groupEnd();
|
|
128
150
|
if (JSON.stringify(processStepsToPathActions(optimalProcess.steps)) !== JSON.stringify(optimalProcess.path.map(e => e.action))) {
|
|
@@ -246,7 +268,14 @@ export class SwapService {
|
|
|
246
268
|
var _subwalletApiSdk$swap2;
|
|
247
269
|
const availablePath = await ((_subwalletApiSdk$swap2 = subwalletApiSdk.swapApi) === null || _subwalletApiSdk$swap2 === void 0 ? void 0 : _subwalletApiSdk$swap2.findAvailablePath(request));
|
|
248
270
|
if (!availablePath) {
|
|
249
|
-
|
|
271
|
+
return {
|
|
272
|
+
path: [],
|
|
273
|
+
swapQuoteResponse: {
|
|
274
|
+
quotes: [],
|
|
275
|
+
aliveUntil: Date.now() + SWAP_QUOTE_TIMEOUT_MAP.error,
|
|
276
|
+
error: new SwapError(SwapErrorType.ERROR_FETCHING_QUOTE)
|
|
277
|
+
}
|
|
278
|
+
};
|
|
250
279
|
}
|
|
251
280
|
const {
|
|
252
281
|
path
|
|
@@ -354,6 +383,9 @@ export class SwapService {
|
|
|
354
383
|
case SwapProviderId.UNISWAP:
|
|
355
384
|
this.handlers[providerId] = new UniswapHandler(this.chainService, this.state.balanceService, this.state.transactionService, this.state.feeService);
|
|
356
385
|
break;
|
|
386
|
+
case SwapProviderId.KYBER:
|
|
387
|
+
this.handlers[providerId] = new KyberHandler(this.chainService, this.state.balanceService, this.state.transactionService, this.state.feeService);
|
|
388
|
+
break;
|
|
357
389
|
default:
|
|
358
390
|
throw new Error('Unsupported provider');
|
|
359
391
|
}
|
|
@@ -22,8 +22,11 @@ export const SWAP_QUOTE_TIMEOUT_MAP = {
|
|
|
22
22
|
// in milliseconds
|
|
23
23
|
default: 90000,
|
|
24
24
|
[SwapProviderId.CHAIN_FLIP_TESTNET]: 30000,
|
|
25
|
-
[SwapProviderId.CHAIN_FLIP_MAINNET]: 30000
|
|
25
|
+
[SwapProviderId.CHAIN_FLIP_MAINNET]: 30000,
|
|
26
|
+
error: 10000
|
|
26
27
|
};
|
|
28
|
+
|
|
29
|
+
// deprecated
|
|
27
30
|
export const _PROVIDER_TO_SUPPORTED_PAIR_MAP = {
|
|
28
31
|
[SwapProviderId.HYDRADX_MAINNET]: [COMMON_CHAIN_SLUGS.HYDRADX],
|
|
29
32
|
[SwapProviderId.CHAIN_FLIP_MAINNET]: [COMMON_CHAIN_SLUGS.POLKADOT, COMMON_CHAIN_SLUGS.ETHEREUM, COMMON_CHAIN_SLUGS.ARBITRUM],
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { _ChainInfo } from '@subwallet/chain-list/types';
|
|
2
2
|
import { CardanoTransactionConfig } from '@subwallet/extension-base/services/balance-service/transfer/cardano-transfer';
|
|
3
3
|
import { TonTransactionConfig } from '@subwallet/extension-base/services/balance-service/transfer/ton-transfer';
|
|
4
|
-
import {
|
|
4
|
+
import { SWTransactionBase } from '@subwallet/extension-base/services/transaction-service/types';
|
|
5
5
|
import { SubmittableExtrinsic } from '@polkadot/api/promise/types';
|
|
6
6
|
export declare const getTransactionId: (chainType: string, chain: string, isInternal: boolean, isWalletConnect?: boolean) => string;
|
|
7
7
|
export declare const getValidationId: (chainType: string, chain: string) => string;
|
|
8
|
-
export declare const isSubstrateTransaction: (tx:
|
|
9
|
-
export declare const isTonTransaction: (tx:
|
|
10
|
-
export declare const isCardanoTransaction: (tx:
|
|
11
|
-
export declare const getBaseTransactionInfo: (transaction:
|
|
8
|
+
export declare const isSubstrateTransaction: (tx: SWTransactionBase['transaction']) => tx is SubmittableExtrinsic;
|
|
9
|
+
export declare const isTonTransaction: (tx: SWTransactionBase['transaction']) => tx is TonTransactionConfig;
|
|
10
|
+
export declare const isCardanoTransaction: (tx: SWTransactionBase['transaction']) => tx is CardanoTransactionConfig;
|
|
11
|
+
export declare const getBaseTransactionInfo: (transaction: SWTransactionBase, chainInfoMap: Record<string, _ChainInfo>) => string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
2
2
|
import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
|
|
3
|
-
import { SWPermitTransactionInput,
|
|
3
|
+
import { SWDutchTransactionInput, SWPermitTransactionInput, SWTransactionBase, SWTransactionInput, SWTransactionResponse, TransactionEmitter } from '@subwallet/extension-base/services/transaction-service/types';
|
|
4
4
|
import { BaseStepType, BriefProcessStep, ProcessStep, ProcessTransactionData } from '@subwallet/extension-base/types';
|
|
5
5
|
import { BehaviorSubject } from 'rxjs';
|
|
6
6
|
import { TransactionConfig } from 'web3-core';
|
|
@@ -20,27 +20,31 @@ export default class TransactionService {
|
|
|
20
20
|
constructor(state: KoniState);
|
|
21
21
|
private get allTransactions();
|
|
22
22
|
private get processingTransactions();
|
|
23
|
-
getTransaction(id: string):
|
|
23
|
+
getTransaction(id: string): SWTransactionBase;
|
|
24
24
|
private checkDuplicate;
|
|
25
25
|
validateTransaction(transactionInput: SWTransactionInput): Promise<SWTransactionResponse>;
|
|
26
|
-
getTransactionSubject(): BehaviorSubject<Record<string,
|
|
26
|
+
getTransactionSubject(): BehaviorSubject<Record<string, SWTransactionBase>>;
|
|
27
27
|
get observables(): {
|
|
28
|
-
readonly transaction: import("rxjs").Observable<Record<string,
|
|
28
|
+
readonly transaction: import("rxjs").Observable<Record<string, SWTransactionBase>>;
|
|
29
29
|
readonly aliveProcess: import("rxjs").Observable<Record<string, ProcessTransactionData>>;
|
|
30
30
|
};
|
|
31
31
|
get values(): {
|
|
32
|
-
readonly transaction: Record<string,
|
|
32
|
+
readonly transaction: Record<string, SWTransactionBase>;
|
|
33
33
|
readonly aliveProcess: Record<string, ProcessTransactionData>;
|
|
34
34
|
};
|
|
35
35
|
getCacheInfo(processId: string, step: BaseStepType): string;
|
|
36
36
|
private updateAliveProcess;
|
|
37
37
|
private fillTransactionDefaultInfo;
|
|
38
|
+
private fillDutchTransactionDefaultInfo;
|
|
38
39
|
addTransaction(inputTransaction: SWTransactionInput): Promise<TransactionEmitter>;
|
|
40
|
+
addDutchTransaction(inputTransaction: SWDutchTransactionInput): TransactionEmitter;
|
|
39
41
|
generateBeforeHandleResponseErrors(errors: TransactionError[]): SWTransactionResponse;
|
|
40
42
|
handleTransaction(transaction: SWTransactionInput): Promise<SWTransactionResponse>;
|
|
41
43
|
handlePermitTransaction(transaction: SWPermitTransactionInput): Promise<SWTransactionResponse>;
|
|
44
|
+
handleDutchTransaction(transaction: SWDutchTransactionInput): Promise<SWTransactionResponse>;
|
|
42
45
|
private sendTransaction;
|
|
43
46
|
private sendPermitTransaction;
|
|
47
|
+
private sendDutchTransaction;
|
|
44
48
|
private removeTransaction;
|
|
45
49
|
private updateTransaction;
|
|
46
50
|
private getTransactionLink;
|
|
@@ -55,6 +59,7 @@ export default class TransactionService {
|
|
|
55
59
|
generateHashPayload(chain: string, transaction: TransactionConfig): HexString;
|
|
56
60
|
private signAndSendEvmTransaction;
|
|
57
61
|
private signAndSendEvmPermitTransaction;
|
|
62
|
+
private signAndSendEvmDutchTransaction;
|
|
58
63
|
private signAndSendSubstrateTransaction;
|
|
59
64
|
private signAndSendTonTransaction;
|
|
60
65
|
private signAndSendCardanoTransaction;
|