@subwallet/extension-base 1.3.26-0 → 1.3.27-1

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.
Files changed (54) hide show
  1. package/background/KoniTypes.d.ts +4 -3
  2. package/background/warnings/TransactionWarning.d.ts +2 -0
  3. package/background/warnings/TransactionWarning.js +16 -1
  4. package/cjs/background/warnings/TransactionWarning.js +15 -0
  5. package/cjs/core/logic-validation/index.js +32 -1
  6. package/cjs/core/utils.js +25 -3
  7. package/cjs/koni/background/handlers/Extension.js +86 -94
  8. package/cjs/packageInfo.js +1 -1
  9. package/cjs/services/chain-service/utils/patch.js +1 -1
  10. package/cjs/services/swap-service/handler/asset-hub/handler.js +182 -40
  11. package/cjs/services/swap-service/handler/asset-hub/utils.js +3 -0
  12. package/cjs/services/swap-service/handler/base-handler.js +326 -12
  13. package/cjs/services/swap-service/handler/chainflip-handler.js +80 -16
  14. package/cjs/services/swap-service/handler/hydradx-handler.js +174 -30
  15. package/cjs/services/swap-service/handler/simpleswap-handler.js +50 -1
  16. package/cjs/services/swap-service/handler/uniswap-handler.js +47 -1
  17. package/cjs/services/swap-service/index.js +191 -27
  18. package/cjs/services/swap-service/interface.js +14 -0
  19. package/cjs/services/swap-service/utils.js +81 -5
  20. package/cjs/services/transaction-service/utils.js +4 -1
  21. package/core/logic-validation/index.d.ts +4 -0
  22. package/core/logic-validation/index.js +22 -1
  23. package/core/utils.d.ts +3 -0
  24. package/core/utils.js +22 -2
  25. package/koni/background/handlers/Extension.d.ts +2 -2
  26. package/koni/background/handlers/Extension.js +20 -28
  27. package/package.json +12 -7
  28. package/packageInfo.js +1 -1
  29. package/services/balance-service/helpers/process.d.ts +3 -3
  30. package/services/balance-service/index.d.ts +2 -3
  31. package/services/chain-service/utils/patch.js +1 -1
  32. package/services/swap-service/handler/asset-hub/handler.d.ts +6 -3
  33. package/services/swap-service/handler/asset-hub/handler.js +170 -28
  34. package/services/swap-service/handler/asset-hub/utils.js +3 -0
  35. package/services/swap-service/handler/base-handler.d.ts +12 -3
  36. package/services/swap-service/handler/base-handler.js +329 -15
  37. package/services/swap-service/handler/chainflip-handler.d.ts +4 -3
  38. package/services/swap-service/handler/chainflip-handler.js +74 -10
  39. package/services/swap-service/handler/hydradx-handler.d.ts +8 -3
  40. package/services/swap-service/handler/hydradx-handler.js +176 -32
  41. package/services/swap-service/handler/simpleswap-handler.d.ts +4 -2
  42. package/services/swap-service/handler/simpleswap-handler.js +50 -1
  43. package/services/swap-service/handler/uniswap-handler.d.ts +4 -2
  44. package/services/swap-service/handler/uniswap-handler.js +47 -1
  45. package/services/swap-service/index.d.ts +15 -5
  46. package/services/swap-service/index.js +182 -18
  47. package/services/swap-service/interface.d.ts +9 -0
  48. package/services/swap-service/interface.js +8 -0
  49. package/services/swap-service/utils.d.ts +9 -1
  50. package/services/swap-service/utils.js +74 -4
  51. package/services/transaction-service/utils.js +4 -1
  52. package/types/service-base.d.ts +6 -2
  53. package/types/swap/index.d.ts +34 -6
  54. package/types/transaction/process.d.ts +0 -6
@@ -8,14 +8,16 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
8
8
  import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
9
9
  import { XCM_MIN_AMOUNT_RATIO } from '@subwallet/extension-base/constants';
10
10
  import { createXcmExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
11
- import { _getAssetDecimals, _getChainNativeTokenSlug, _getTokenOnChainAssetId, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
11
+ import { _getChainNativeTokenSlug, _getTokenMinAmount, _getTokenOnChainAssetId, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
12
12
  import { SwapBaseHandler } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
13
- import { getSwapAlternativeAsset } from '@subwallet/extension-base/services/swap-service/utils';
13
+ import { DynamicSwapType } from '@subwallet/extension-base/services/swap-service/interface';
14
+ import { FEE_RATE_MULTIPLIER, getSwapAlternativeAsset } from '@subwallet/extension-base/services/swap-service/utils';
14
15
  import { BasicTxErrorType } from '@subwallet/extension-base/types';
15
16
  import { CommonStepType } from '@subwallet/extension-base/types/service-base';
16
17
  import { SwapErrorType, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types/swap';
17
18
  import { getId } from '@subwallet/extension-base/utils/getId';
18
19
  import BigNumber from 'bignumber.js';
20
+ import { isHex } from '@polkadot/util';
19
21
  const HYDRADX_SUBWALLET_REFERRAL_CODE = 'WALLET';
20
22
  const HYDRADX_SUBWALLET_REFERRAL_ACCOUNT = '7PCsCpkgsHdNaZhv79wCCQ5z97uxVbSeSCtDMUa1eZHKXy4a';
21
23
  const HYDRADX_TESTNET_SUBWALLET_REFERRAL_CODE = 'ASSETHUB';
@@ -187,35 +189,138 @@ export class HydradxHandler {
187
189
  }
188
190
  return Promise.resolve(undefined);
189
191
  }
192
+ async getXcmStepV2(params) {
193
+ var _params$path$find;
194
+ // todo: improve this function for Round 2
195
+
196
+ const xcmPairInfo = (_params$path$find = params.path.find((step, i) => i === 0 && step.action === DynamicSwapType.BRIDGE)) === null || _params$path$find === void 0 ? void 0 : _params$path$find.pair;
197
+ if (!xcmPairInfo) {
198
+ return undefined;
199
+ }
200
+ const fromTokenInfo = this.chainService.getAssetBySlug(xcmPairInfo.from);
201
+ const toTokenInfo = this.chainService.getAssetBySlug(xcmPairInfo.to);
202
+ const fromChainInfo = this.chainService.getChainInfoByKey(fromTokenInfo.originChain);
203
+ const toChainInfo = this.chainService.getChainInfoByKey(toTokenInfo.originChain);
204
+ if (!fromChainInfo || !toChainInfo || !fromChainInfo || !toChainInfo) {
205
+ throw Error('Token and chain not found');
206
+ }
207
+ try {
208
+ const substrateApi = await this.chainService.getSubstrateApi(fromTokenInfo.originChain).isReady;
209
+ const id = getId();
210
+ const [feeInfo, toTokenBalance] = await Promise.all([this.swapBaseHandler.feeService.subscribeChainFee(id, fromTokenInfo.originChain, 'substrate'), this.balanceService.getTotalBalance(params.request.address, toTokenInfo.originChain, toTokenInfo.slug, ExtrinsicType.TRANSFER_BALANCE)]);
211
+ const xcmTransfer = await createXcmExtrinsic({
212
+ originTokenInfo: fromTokenInfo,
213
+ destinationTokenInfo: toTokenInfo,
214
+ // Mock sending value to get payment info
215
+ sendingValue: params.request.fromAmount,
216
+ recipient: params.request.address,
217
+ substrateApi: substrateApi,
218
+ sender: params.request.address,
219
+ originChain: fromChainInfo,
220
+ destinationChain: toChainInfo,
221
+ feeInfo
222
+ });
223
+ const _xcmFeeInfo = await xcmTransfer.paymentInfo(params.request.address);
224
+ const xcmFeeInfo = _xcmFeeInfo.toPrimitive();
225
+ const fee = {
226
+ feeComponent: [{
227
+ feeType: SwapFeeType.NETWORK_FEE,
228
+ amount: Math.ceil(xcmFeeInfo.partialFee * FEE_RATE_MULTIPLIER.high).toString(),
229
+ tokenSlug: _getChainNativeTokenSlug(fromChainInfo)
230
+ }],
231
+ defaultFeeToken: _getChainNativeTokenSlug(fromChainInfo),
232
+ feeOptions: [_getChainNativeTokenSlug(fromChainInfo)]
233
+ };
234
+ let bnTransferAmount = new BigNumber(params.request.fromAmount);
235
+
236
+ // todo: increase transfer amount when XCM local token
237
+ if (_isNativeToken(fromTokenInfo)) {
238
+ // xcm fee is paid in native token but swap token is not always native token
239
+ // add amount of fee into sending value to ensure has enough token to swap
240
+ const bnXcmFee = new BigNumber(fee.feeComponent[0].amount);
241
+ bnTransferAmount = bnTransferAmount.plus(bnXcmFee);
242
+ } else {
243
+ bnTransferAmount = bnTransferAmount.plus(BigNumber(_getTokenMinAmount(toTokenInfo)).multipliedBy(FEE_RATE_MULTIPLIER.medium));
244
+ }
245
+ if (BigNumber(toTokenBalance.value).lte(0)) {
246
+ bnTransferAmount = bnTransferAmount.plus(_getTokenMinAmount(toTokenInfo));
247
+ }
248
+ const step = {
249
+ metadata: {
250
+ sendingValue: bnTransferAmount.toString(),
251
+ originTokenInfo: fromTokenInfo,
252
+ destinationTokenInfo: toTokenInfo
253
+ },
254
+ name: `Transfer ${fromTokenInfo.symbol} from ${fromChainInfo.name}`,
255
+ type: CommonStepType.XCM
256
+ };
257
+ return [step, fee];
258
+ } catch (e) {
259
+ console.error('Error creating xcm step', e);
260
+ return undefined;
261
+ }
262
+ }
263
+ async getSwapStepV2(params) {
264
+ var _params$path$find2;
265
+ const swapPairInfo = (_params$path$find2 = params.path.find(step => step.action === DynamicSwapType.SWAP)) === null || _params$path$find2 === void 0 ? void 0 : _params$path$find2.pair;
266
+ if (!swapPairInfo) {
267
+ return Promise.resolve(undefined);
268
+ }
269
+ if (!params.selectedQuote) {
270
+ return Promise.resolve(undefined);
271
+ }
272
+ const txHex = params.selectedQuote.metadata;
273
+ if (!txHex || !isHex(txHex)) {
274
+ return Promise.resolve(undefined);
275
+ }
276
+ const metadata = {
277
+ sendingValue: params.request.fromAmount.toString(),
278
+ originTokenInfo: this.chainService.getAssetBySlug(swapPairInfo.from),
279
+ destinationTokenInfo: this.chainService.getAssetBySlug(swapPairInfo.to),
280
+ txHex
281
+ };
282
+ const submitStep = {
283
+ name: 'Swap',
284
+ type: SwapStepType.SWAP,
285
+ // @ts-ignore
286
+ metadata
287
+ };
288
+ return Promise.resolve([submitStep, params.selectedQuote.feeInfo]); // review fee
289
+ }
290
+
190
291
  generateOptimalProcess(params) {
191
292
  return this.swapBaseHandler.generateOptimalProcess(params, [this.getXcmStep.bind(this),
192
293
  // this.getFeeOptionStep.bind(this),
193
294
  this.getSubmitStep.bind(this)]);
194
295
  }
296
+ generateOptimalProcessV2(params) {
297
+ const stepFuncList = params.path.map(step => {
298
+ if (step.action === DynamicSwapType.BRIDGE) {
299
+ return this.getXcmStepV2.bind(this);
300
+ }
301
+ if (step.action === DynamicSwapType.SWAP) {
302
+ return this.getSwapStepV2.bind(this);
303
+ }
304
+ throw new Error(`Error generating optimal process: Action ${step.action} is not supported`);
305
+ });
306
+ return this.swapBaseHandler.generateOptimalProcessV2(params, stepFuncList);
307
+ }
195
308
  async handleXcmStep(params) {
196
- const pair = params.quote.pair;
197
- const alternativeAssetSlug = getSwapAlternativeAsset(pair);
198
- const originAsset = this.chainService.getAssetBySlug(alternativeAssetSlug);
199
- const destinationAsset = this.chainService.getAssetBySlug(pair.from);
309
+ const briefXcmStep = params.process.steps[params.currentStep].metadata;
310
+ if (!briefXcmStep || !briefXcmStep.originTokenInfo || !briefXcmStep.destinationTokenInfo || !briefXcmStep.sendingValue) {
311
+ throw new Error('XCM metadata error');
312
+ }
313
+ const originAsset = briefXcmStep.originTokenInfo;
314
+ const destinationAsset = briefXcmStep.destinationTokenInfo;
200
315
  const originChain = this.chainService.getChainInfoByKey(originAsset.originChain);
201
316
  const destinationChain = this.chainService.getChainInfoByKey(destinationAsset.originChain);
202
317
  const substrateApi = this.chainService.getSubstrateApi(originAsset.originChain);
203
318
  const chainApi = await substrateApi.isReady;
204
- const destinationAssetBalance = await this.balanceService.getTransferableBalance(params.address, destinationAsset.originChain, destinationAsset.slug);
205
- const xcmFee = params.process.totalFee[params.currentStep];
206
- const bnAmount = new BigNumber(params.quote.fromAmount);
207
- const bnDestinationAssetBalance = new BigNumber(destinationAssetBalance.value);
208
- let bnTotalAmount = bnAmount.minus(bnDestinationAssetBalance);
209
- if (_isNativeToken(originAsset)) {
210
- const bnXcmFee = new BigNumber(xcmFee.feeComponent[0].amount); // xcm fee is paid in native token but swap token is not always native token
211
-
212
- bnTotalAmount = bnTotalAmount.plus(bnXcmFee);
213
- }
214
319
  const feeInfo = await this.swapBaseHandler.feeService.subscribeChainFee(getId(), originAsset.originChain, 'substrate');
215
320
  const xcmTransfer = await createXcmExtrinsic({
216
321
  originTokenInfo: originAsset,
217
322
  destinationTokenInfo: destinationAsset,
218
- sendingValue: bnTotalAmount.toString(),
323
+ sendingValue: briefXcmStep.sendingValue,
219
324
  recipient: params.address,
220
325
  substrateApi: chainApi,
221
326
  sender: params.address,
@@ -228,14 +333,14 @@ export class HydradxHandler {
228
333
  destinationNetworkKey: destinationAsset.originChain,
229
334
  from: params.address,
230
335
  to: params.address,
231
- value: bnTotalAmount.toString(),
336
+ value: briefXcmStep.sendingValue,
232
337
  tokenSlug: originAsset.slug,
233
338
  showExtraWarning: true
234
339
  };
235
340
  return {
236
341
  txChain: originAsset.originChain,
237
342
  extrinsic: xcmTransfer,
238
- transferNativeAmount: _isNativeToken(originAsset) ? bnTotalAmount.toString() : '0',
343
+ transferNativeAmount: _isNativeToken(originAsset) ? briefXcmStep.sendingValue : '0',
239
344
  extrinsicType: ExtrinsicType.TRANSFER_XCM,
240
345
  chainType: ChainType.SUBSTRATE,
241
346
  txData: xcmData
@@ -266,18 +371,18 @@ export class HydradxHandler {
266
371
  };
267
372
  }
268
373
  async handleSubmitStep(params) {
269
- const fromAsset = this.chainService.getAssetBySlug(params.quote.pair.from);
270
- const toAsset = this.chainService.getAssetBySlug(params.quote.pair.to);
271
- const fromAssetId = _getTokenOnChainAssetId(fromAsset);
272
- const toAssetId = _getTokenOnChainAssetId(toAsset);
374
+ const metadata = params.process.steps[params.currentStep].metadata;
375
+ const txHex = params.quote.metadata;
376
+ if (!txHex || !isHex(txHex)) {
377
+ return new SwapError(SwapErrorType.UNKNOWN);
378
+ }
379
+ if (!metadata || !metadata.sendingValue || !metadata.txHex || !metadata.destinationTokenInfo || !metadata.originTokenInfo) {
380
+ throw new Error('Swap metadata error');
381
+ }
382
+ const fromAsset = metadata.originTokenInfo;
273
383
  if (!this.isReady || !this.tradeRouter) {
274
384
  return new SwapError(SwapErrorType.UNKNOWN);
275
385
  }
276
- const parsedFromAmount = new BigNumber(params.quote.fromAmount).shiftedBy(-1 * _getAssetDecimals(fromAsset)).toString();
277
- const quoteResponse = await this.tradeRouter.getBestSell(fromAssetId, toAssetId, parsedFromAmount);
278
- const toAmount = quoteResponse.amountOut;
279
- const minReceive = toAmount.times(1 - params.slippage).integerValue();
280
- const txHex = quoteResponse.toTx(minReceive).hex;
281
386
  const substrateApi = this.chainService.getSubstrateApi(this.chain());
282
387
  const chainApi = await substrateApi.isReady;
283
388
  const txData = {
@@ -285,7 +390,7 @@ export class HydradxHandler {
285
390
  quote: params.quote,
286
391
  address: params.address,
287
392
  slippage: params.slippage,
288
- txHex,
393
+ txHex: txHex,
289
394
  process: params.process
290
395
  };
291
396
  let extrinsic;
@@ -313,8 +418,7 @@ export class HydradxHandler {
313
418
  txChain: fromAsset.originChain,
314
419
  txData,
315
420
  extrinsic,
316
- transferNativeAmount: _isNativeToken(fromAsset) ? params.quote.fromAmount : '0',
317
- // todo
421
+ transferNativeAmount: _isNativeToken(fromAsset) ? metadata.sendingValue : '0',
318
422
  extrinsicType: ExtrinsicType.SWAP,
319
423
  chainType: ChainType.SUBSTRATE
320
424
  };
@@ -344,14 +448,22 @@ export class HydradxHandler {
344
448
  if (bnAmount.lte(0)) {
345
449
  return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')];
346
450
  }
451
+ const swapStep = params.process.steps.find(item => item.type === SwapStepType.SWAP);
452
+ if (!swapStep) {
453
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR, 'Swap step not found')];
454
+ }
347
455
  let isXcmOk = false;
456
+ const currentStep = params.currentStep;
348
457
  for (const [index, step] of params.process.steps.entries()) {
458
+ if (currentStep > index) {
459
+ continue;
460
+ }
349
461
  const getErrors = async () => {
350
462
  switch (step.type) {
351
463
  case CommonStepType.DEFAULT:
352
464
  return Promise.resolve([]);
353
465
  case CommonStepType.XCM:
354
- return this.swapBaseHandler.validateXcmStep(params, index);
466
+ return this.swapBaseHandler.validateXcmStepV2(params, index);
355
467
  case CommonStepType.SET_FEE_TOKEN:
356
468
  return this.swapBaseHandler.validateSetFeeTokenStep(params, index);
357
469
  default:
@@ -367,6 +479,38 @@ export class HydradxHandler {
367
479
  }
368
480
  return [];
369
481
  }
482
+ async validateSwapProcessV2(params) {
483
+ // todo: recheck address and recipient format in params
484
+ const {
485
+ process,
486
+ selectedQuote
487
+ } = params; // todo: review flow, currentStep param.
488
+
489
+ // todo: validate path with optimalProcess
490
+ // todo: review error message in case many step swap
491
+ if (BigNumber(selectedQuote.fromAmount).lte(0)) {
492
+ return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')];
493
+ }
494
+ const actionList = JSON.stringify(process.path.map(step => step.action));
495
+ const swap = actionList === JSON.stringify([DynamicSwapType.SWAP]);
496
+ const swapXcm = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
497
+ const xcmSwap = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP]);
498
+ const xcmSwapXcm = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
499
+ if (swap) {
500
+ return this.swapBaseHandler.validateSwapOnlyProcess(params, 1); // todo: create interface for input request
501
+ }
502
+
503
+ if (swapXcm) {
504
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
505
+ }
506
+ if (xcmSwap) {
507
+ return this.swapBaseHandler.validateXcmSwapProcess(params, 2, 1);
508
+ }
509
+ if (xcmSwapXcm) {
510
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
511
+ }
512
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
513
+ }
370
514
  get referralCode() {
371
515
  if (this.isTestnet) {
372
516
  return HYDRADX_TESTNET_SUBWALLET_REFERRAL_CODE;
@@ -1,6 +1,6 @@
1
1
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
2
2
  import FeeService from '@subwallet/extension-base/services/fee-service/service';
3
- import { BaseStepDetail, CommonOptimalPath, CommonStepFeeInfo, OptimalSwapPathParams, SwapProviderId, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types';
3
+ import { BaseStepDetail, CommonOptimalSwapPath, CommonStepFeeInfo, OptimalSwapPathParams, OptimalSwapPathParamsV2, SwapProviderId, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types';
4
4
  import { BalanceService } from '../../balance-service';
5
5
  import { ChainService } from '../../chain-service';
6
6
  import { SwapBaseInterface } from './base-handler';
@@ -15,8 +15,10 @@ export declare class SimpleSwapHandler implements SwapBaseInterface {
15
15
  get providerInfo(): import("@subwallet/extension-base/types").SwapProvider;
16
16
  get name(): string;
17
17
  get slug(): string;
18
- generateOptimalProcess(params: OptimalSwapPathParams): Promise<CommonOptimalPath>;
18
+ generateOptimalProcess(params: OptimalSwapPathParams): Promise<CommonOptimalSwapPath>;
19
+ generateOptimalProcessV2(params: OptimalSwapPathParamsV2): Promise<CommonOptimalSwapPath>;
19
20
  getSubmitStep(params: OptimalSwapPathParams): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
20
21
  handleSwapProcess(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
21
22
  handleSubmitStep(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
23
+ validateSwapProcessV2(params: ValidateSwapProcessParams): Promise<TransactionError[]>;
22
24
  }
@@ -5,6 +5,7 @@ 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
7
  import { _getAssetDecimals, _getContractAddressOfToken, _isChainSubstrateCompatible, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
8
+ import { DynamicSwapType } from '@subwallet/extension-base/services/swap-service/interface';
8
9
  import { BasicTxErrorType, CommonStepType, SwapErrorType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
9
10
  import { _reformatAddressWithChain, formatNumber } from '@subwallet/extension-base/utils';
10
11
  import { getId } from '@subwallet/extension-base/utils/getId';
@@ -105,11 +106,19 @@ export class SimpleSwapHandler {
105
106
  generateOptimalProcess(params) {
106
107
  return this.swapBaseHandler.generateOptimalProcess(params, [this.getSubmitStep.bind(this)]);
107
108
  }
109
+ generateOptimalProcessV2(params) {
110
+ return this.swapBaseHandler.generateOptimalProcessV2(params, [this.getSubmitStep.bind(this)]);
111
+ }
108
112
  async getSubmitStep(params) {
109
113
  if (params.selectedQuote) {
110
114
  const submitStep = {
111
115
  name: 'Swap',
112
- type: SwapStepType.SWAP
116
+ type: SwapStepType.SWAP,
117
+ metadata: {
118
+ sendingValue: params.request.fromAmount.toString(),
119
+ originTokenInfo: this.chainService.getAssetBySlug(params.selectedQuote.pair.from),
120
+ destinationTokenInfo: this.chainService.getAssetBySlug(params.selectedQuote.pair.to)
121
+ }
113
122
  };
114
123
  return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
115
124
  }
@@ -162,6 +171,9 @@ export class SimpleSwapHandler {
162
171
  sender,
163
172
  toAsset
164
173
  });
174
+ if (!id || id.length === 0 || !addressFrom || addressFrom.length === 0) {
175
+ throw new SwapError(SwapErrorType.UNKNOWN);
176
+ }
165
177
 
166
178
  // Validate the amount to be swapped
167
179
  const rate = BigN(amountTo).div(BigN(quote.toAmount)).multipliedBy(100);
@@ -230,4 +242,41 @@ export class SimpleSwapHandler {
230
242
  chainType
231
243
  };
232
244
  }
245
+ async validateSwapProcessV2(params) {
246
+ // todo: recheck address and recipient format in params
247
+ const {
248
+ process,
249
+ selectedQuote
250
+ } = params; // todo: review flow, currentStep param.
251
+
252
+ // todo: validate path with optimalProcess
253
+ // todo: review error message in case many step swap
254
+ if (BigNumber(selectedQuote.fromAmount).lte(0)) {
255
+ return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')];
256
+ }
257
+ const actionList = JSON.stringify(process.path.map(step => step.action));
258
+ const swap = actionList === JSON.stringify([DynamicSwapType.SWAP]);
259
+ const swapXcm = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
260
+ const xcmSwap = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP]);
261
+ const xcmSwapXcm = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
262
+ const swapIndex = params.process.steps.findIndex(step => step.type === SwapStepType.SWAP); // todo
263
+
264
+ if (swapIndex <= -1) {
265
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
266
+ }
267
+ if (swap) {
268
+ return this.swapBaseHandler.validateSwapOnlyProcess(params, swapIndex); // todo: create interface for input request
269
+ }
270
+
271
+ if (swapXcm) {
272
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
273
+ }
274
+ if (xcmSwap) {
275
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
276
+ }
277
+ if (xcmSwapXcm) {
278
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
279
+ }
280
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
281
+ }
233
282
  }
@@ -1,7 +1,7 @@
1
1
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
2
2
  import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
3
3
  import TransactionService from '@subwallet/extension-base/services/transaction-service';
4
- import { BaseStepDetail, CommonOptimalPath, CommonStepFeeInfo, OptimalSwapPathParams, PermitSwapData, SwapProviderId, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types';
4
+ import { BaseStepDetail, CommonOptimalSwapPath, CommonStepFeeInfo, OptimalSwapPathParams, OptimalSwapPathParamsV2, PermitSwapData, SwapProviderId, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types';
5
5
  import { TransactionConfig } from 'web3-core';
6
6
  import { BalanceService } from '../../balance-service';
7
7
  import { ChainService } from '../../chain-service';
@@ -21,7 +21,8 @@ export declare class UniswapHandler implements SwapBaseInterface {
21
21
  get balanceService(): BalanceService;
22
22
  get feeService(): FeeService;
23
23
  get providerInfo(): import("@subwallet/extension-base/types").SwapProvider;
24
- generateOptimalProcess(params: OptimalSwapPathParams): Promise<CommonOptimalPath>;
24
+ generateOptimalProcess(params: OptimalSwapPathParams): Promise<CommonOptimalSwapPath>;
25
+ generateOptimalProcessV2(params: OptimalSwapPathParamsV2): Promise<CommonOptimalSwapPath>;
25
26
  getApprovalStep(params: OptimalSwapPathParams): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
26
27
  getPermitStep(params: OptimalSwapPathParams): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
27
28
  getSubmitStep(params: OptimalSwapPathParams): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
@@ -38,4 +39,5 @@ export declare class UniswapHandler implements SwapBaseInterface {
38
39
  chainType: ChainType;
39
40
  isPermit: boolean;
40
41
  };
42
+ validateSwapProcessV2(params: ValidateSwapProcessParams): Promise<TransactionError[]>;
41
43
  }
@@ -4,6 +4,7 @@
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
5
  import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { validateTypedSignMessageDataV3V4 } from '@subwallet/extension-base/core/logic-validation';
7
+ import { DynamicSwapType } from '@subwallet/extension-base/services/swap-service/interface';
7
8
  import { BasicTxErrorType, CommonStepType, FeeOptionKey, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
8
9
  import BigNumber from 'bignumber.js';
9
10
  import { _getContractAddressOfToken, _isNativeToken } from "../../chain-service/utils/index.js";
@@ -60,6 +61,9 @@ export class UniswapHandler {
60
61
  generateOptimalProcess(params) {
61
62
  return this.swapBaseHandler.generateOptimalProcess(params, [this.getApprovalStep.bind(this), this.getPermitStep.bind(this), this.getSubmitStep.bind(this)]);
62
63
  }
64
+ generateOptimalProcessV2(params) {
65
+ return this.swapBaseHandler.generateOptimalProcessV2(params, [this.getApprovalStep.bind(this), this.getPermitStep.bind(this), this.getSubmitStep.bind(this)]);
66
+ }
63
67
  async getApprovalStep(params) {
64
68
  if (params.selectedQuote) {
65
69
  const walletAddress = params.request.address;
@@ -118,7 +122,12 @@ export class UniswapHandler {
118
122
  if (params.selectedQuote) {
119
123
  const submitStep = {
120
124
  name: 'Swap',
121
- type: SwapStepType.SWAP
125
+ type: SwapStepType.SWAP,
126
+ metadata: {
127
+ sendingValue: params.request.fromAmount.toString(),
128
+ originTokenInfo: this.chainService.getAssetBySlug(params.selectedQuote.pair.from),
129
+ destinationTokenInfo: this.chainService.getAssetBySlug(params.selectedQuote.pair.to)
130
+ }
122
131
  };
123
132
  return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
124
133
  }
@@ -320,4 +329,41 @@ export class UniswapHandler {
320
329
  isPermit: true
321
330
  };
322
331
  }
332
+ async validateSwapProcessV2(params) {
333
+ // todo: recheck address and recipient format in params
334
+ const {
335
+ process,
336
+ selectedQuote
337
+ } = params; // todo: review flow, currentStep param.
338
+
339
+ // todo: validate path with optimalProcess
340
+ // todo: review error message in case many step swap
341
+ if (BigNumber(selectedQuote.fromAmount).lte(0)) {
342
+ return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')];
343
+ }
344
+ const actionList = JSON.stringify(process.path.map(step => step.action));
345
+ const swap = actionList === JSON.stringify([DynamicSwapType.SWAP]);
346
+ const swapXcm = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
347
+ const xcmSwap = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP]);
348
+ const xcmSwapXcm = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
349
+ const swapIndex = params.process.steps.findIndex(step => step.type === SwapStepType.SWAP); // todo
350
+
351
+ if (swapIndex <= -1) {
352
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
353
+ }
354
+ if (swap) {
355
+ return this.swapBaseHandler.validateSwapOnlyProcess(params, swapIndex); // todo: create interface for input request
356
+ }
357
+
358
+ if (swapXcm) {
359
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
360
+ }
361
+ if (xcmSwap) {
362
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
363
+ }
364
+ if (xcmSwapXcm) {
365
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
366
+ }
367
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
368
+ }
323
369
  }
@@ -1,8 +1,10 @@
1
1
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
2
2
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
3
3
  import { ServiceStatus, ServiceWithProcessInterface, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
4
- import { CommonOptimalPath } from '@subwallet/extension-base/types/service-base';
5
- import { OptimalSwapPathParams, SwapPair, SwapProviderId, SwapQuoteResponse, SwapRequest, SwapRequestResult, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
4
+ import { DynamicSwapAction } from '@subwallet/extension-base/services/swap-service/interface';
5
+ import { OptimalSwapPathParamsV2, ValidateSwapProcessParams } from '@subwallet/extension-base/types';
6
+ import { CommonOptimalSwapPath } from '@subwallet/extension-base/types/service-base';
7
+ import { OptimalSwapPathParams, SwapPair, SwapProviderId, SwapQuoteResponse, SwapRequest, SwapRequestResult, SwapSubmitParams, SwapSubmitStepData } from '@subwallet/extension-base/types/swap';
6
8
  import { PromiseHandler } from '@subwallet/extension-base/utils';
7
9
  export declare const _isChainSupportedByProvider: (providerSlug: SwapProviderId, chain: string) => boolean;
8
10
  export declare class SwapService implements ServiceWithProcessInterface, StoppableServiceInterface {
@@ -17,9 +19,18 @@ export declare class SwapService implements ServiceWithProcessInterface, Stoppab
17
19
  constructor(state: KoniState);
18
20
  private askProvidersForQuote;
19
21
  private getDefaultProcess;
20
- generateOptimalProcess(params: OptimalSwapPathParams): Promise<CommonOptimalPath>;
22
+ private getDefaultProcessV2;
23
+ generateOptimalProcess(params: OptimalSwapPathParams): Promise<CommonOptimalSwapPath>;
24
+ generateOptimalProcessV2(params: OptimalSwapPathParamsV2): Promise<CommonOptimalSwapPath>;
25
+ generateOptimalProcessWithoutPath(params: OptimalSwapPathParamsV2): Promise<CommonOptimalSwapPath>;
21
26
  handleSwapRequest(request: SwapRequest): Promise<SwapRequestResult>;
22
- getLatestQuotes(request: SwapRequest): Promise<SwapQuoteResponse>;
27
+ handleSwapRequestV2(request: SwapRequest): Promise<SwapRequestResult>;
28
+ getAvailablePath(request: SwapRequest): [DynamicSwapAction[], SwapRequest | undefined];
29
+ getLatestQuoteFromSwapRequest(request: SwapRequest): Promise<{
30
+ path: DynamicSwapAction[];
31
+ swapQuoteResponse: SwapQuoteResponse;
32
+ }>;
33
+ private getLatestDirectQuotes;
23
34
  private initHandlers;
24
35
  init(): Promise<void>;
25
36
  start(): Promise<void>;
@@ -27,7 +38,6 @@ export declare class SwapService implements ServiceWithProcessInterface, Stoppab
27
38
  waitForStarted(): Promise<void>;
28
39
  waitForStopped(): Promise<void>;
29
40
  getSwapPairs(): SwapPair[];
30
- private getSwapPairMetadata;
31
41
  validateSwapProcess(params: ValidateSwapProcessParams): Promise<TransactionError[]>;
32
42
  handleSwapProcess(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
33
43
  subscribeSwapPairs(callback: (pairs: SwapPair[]) => void): import("rxjs").Subscription;