@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
@@ -11,6 +11,7 @@ import { CampaignDataType, ChainType, ExternalRequestPromiseStatus, ExtrinsicTyp
11
11
  import { _SUPPORT_TOKEN_PAY_FEE_GROUP, ALL_ACCOUNT_KEY, LATEST_SESSION } from '@subwallet/extension-base/constants';
12
12
  import { additionalValidateTransferForRecipient, additionalValidateXcmTransfer, validateTransferRequest, validateXcmTransferRequest } from '@subwallet/extension-base/core/logic-validation/transfer';
13
13
  import { _isSnowBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser';
14
+ import { _isSufficientToken } from '@subwallet/extension-base/core/utils';
14
15
  import { ALLOWED_PATH } from '@subwallet/extension-base/defaults';
15
16
  import { getERC20SpendingApprovalTx } from '@subwallet/extension-base/koni/api/contract-handler/evm/web3';
16
17
  import { _ERC721_ABI, isAvailBridgeGatewayContract, isSnowBridgeGatewayContract } from '@subwallet/extension-base/koni/api/contract-handler/utils';
@@ -32,9 +33,9 @@ import { createAvailBridgeExtrinsicFromAvail, createAvailBridgeTxFromEth, create
32
33
  import { getClaimTxOnAvail, getClaimTxOnEthereum, isAvailChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/availBridge';
33
34
  import { _isPolygonChainBridge, getClaimPolygonBridge, isClaimedPolygonBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/polygonBridge';
34
35
  import { _isPosChainBridge, getClaimPosBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/posBridge';
35
- import { _DEFAULT_MANTA_ZK_CHAIN, _MANTA_ZK_CHAIN_GROUP, _ZK_ASSET_PREFIX, SUFFICIENT_CHAIN } from '@subwallet/extension-base/services/chain-service/constants';
36
+ import { _DEFAULT_MANTA_ZK_CHAIN, _MANTA_ZK_CHAIN_GROUP, _ZK_ASSET_PREFIX } from '@subwallet/extension-base/services/chain-service/constants';
36
37
  import { _ChainConnectionStatus } from '@subwallet/extension-base/services/chain-service/types';
37
- import { _getAssetDecimals, _getAssetSymbol, _getChainNativeTokenBasicInfo, _getContractAddressOfToken, _getEvmChainId, _getTokenOnChainAssetId, _getXcmAssetMultilocation, _isAssetSmartContractNft, _isBridgedToken, _isChainEvmCompatible, _isChainSubstrateCompatible, _isCustomAsset, _isLocalToken, _isMantaZkAsset, _isNativeToken, _isNativeTokenBySlug, _isPureEvmChain, _isTokenEvmSmartContract, _isTokenTransferredByCardano, _isTokenTransferredByEvm, _isTokenTransferredByTon } from '@subwallet/extension-base/services/chain-service/utils';
38
+ import { _getAssetDecimals, _getAssetSymbol, _getChainNativeTokenBasicInfo, _getContractAddressOfToken, _getEvmChainId, _isAssetSmartContractNft, _isChainEvmCompatible, _isChainSubstrateCompatible, _isCustomAsset, _isLocalToken, _isMantaZkAsset, _isNativeToken, _isNativeTokenBySlug, _isPureEvmChain, _isTokenEvmSmartContract, _isTokenTransferredByCardano, _isTokenTransferredByEvm, _isTokenTransferredByTon } from '@subwallet/extension-base/services/chain-service/utils';
38
39
  import { calculateToAmountByReservePool } from '@subwallet/extension-base/services/fee-service/utils';
39
40
  import { batchExtrinsicSetFeeHydration, getAssetHubTokensCanPayFee, getHydrationTokensCanPayFee } from '@subwallet/extension-base/services/fee-service/utils/tokenPayFee';
40
41
  import { EXTENSION_REQUEST_URL } from '@subwallet/extension-base/services/request-service/constants';
@@ -1299,7 +1300,7 @@ export default class KoniExtension {
1299
1300
  const receiverSendingTokenKeepAliveBalance = BigInt(_receiverSendingTokenKeepAliveBalance);
1300
1301
  const amount = BigInt(transferAmount.value);
1301
1302
  const substrateApi = this.#koniState.getSubstrateApi(chain);
1302
- const isSendingTokenSufficient = await this.isSufficientToken(transferTokenInfo, substrateApi);
1303
+ const isSendingTokenSufficient = await _isSufficientToken(transferTokenInfo, substrateApi);
1303
1304
  const [warnings, errors] = additionalValidateTransferForRecipient(transferTokenInfo, nativeTokenInfo, extrinsicType, receiverSendingTokenKeepAliveBalance, amount, senderSendingTokenTransferable, receiverSystemAccountInfo, isSendingTokenSufficient);
1304
1305
  warnings.length && inputTransaction.warnings.push(...warnings);
1305
1306
  errors.length && inputTransaction.errors.push(...errors);
@@ -1663,25 +1664,6 @@ export default class KoniExtension {
1663
1664
  };
1664
1665
  }
1665
1666
  }
1666
- async isSufficientToken(tokenInfo, substrateApi) {
1667
- let metadata;
1668
- if (SUFFICIENT_CHAIN.includes(tokenInfo.originChain) && tokenInfo.assetType !== _AssetType.NATIVE) {
1669
- const assetId = _isBridgedToken(tokenInfo) ? _getXcmAssetMultilocation(tokenInfo) : _getTokenOnChainAssetId(tokenInfo);
1670
- const queryParams = {
1671
- section: 'query',
1672
- module: 'foreignAssets',
1673
- method: 'asset',
1674
- args: [assetId]
1675
- };
1676
- if (!_isBridgedToken(tokenInfo)) {
1677
- queryParams.module = 'assets';
1678
- }
1679
- metadata = await substrateApi.makeRpcQuery(queryParams);
1680
- } else {
1681
- return false;
1682
- }
1683
- return metadata.isSufficient;
1684
- }
1685
1667
  async deleteCustomAsset(assetSlug) {
1686
1668
  const assetInfo = this.#koniState.getAssetBySlug(assetSlug);
1687
1669
  if (assetInfo && _isCustomAsset(assetSlug)) {
@@ -3603,14 +3585,20 @@ export default class KoniExtension {
3603
3585
  ready = true;
3604
3586
  return this.#koniState.swapService.getSwapPairs();
3605
3587
  }
3606
- async generateOptimalProcess(request) {
3607
- return this.#koniState.swapService.generateOptimalProcess(request);
3588
+ async getOptimalSwapProcessOnSelectQuote(request) {
3589
+ return this.#koniState.swapService.generateOptimalProcessWithoutPath(request);
3608
3590
  }
3609
3591
  async handleSwapRequest(request) {
3610
3592
  return this.#koniState.swapService.handleSwapRequest(request);
3611
3593
  }
3594
+ async handleSwapRequestV2(request) {
3595
+ return this.#koniState.swapService.handleSwapRequestV2(request);
3596
+ }
3612
3597
  async getLatestSwapQuote(swapRequest) {
3613
- return this.#koniState.swapService.getLatestQuotes(swapRequest);
3598
+ const {
3599
+ swapQuoteResponse
3600
+ } = await this.#koniState.swapService.getLatestQuoteFromSwapRequest(swapRequest);
3601
+ return swapQuoteResponse;
3614
3602
  }
3615
3603
  async validateSwapProcess(params) {
3616
3604
  return this.#koniState.swapService.validateSwapProcess(params);
@@ -3647,7 +3635,8 @@ export default class KoniExtension {
3647
3635
  address,
3648
3636
  process,
3649
3637
  selectedQuote: quote,
3650
- recipient
3638
+ recipient,
3639
+ currentStep: inputData.currentStep
3651
3640
  });
3652
3641
  if (swapValidations.length > 0) {
3653
3642
  if (step) {
@@ -3668,6 +3657,7 @@ export default class KoniExtension {
3668
3657
  }
3669
3658
  throw e;
3670
3659
  }
3660
+ console.log('swap data', submitData);
3671
3661
 
3672
3662
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
3673
3663
  const {
@@ -4716,10 +4706,12 @@ export default class KoniExtension {
4716
4706
  /* Swap service */
4717
4707
  case 'pri(swapService.subscribePairs)':
4718
4708
  return this.subscribeSwapPairs(id, port);
4719
- case 'pri(swapService.generateOptimalProcess)':
4720
- return this.generateOptimalProcess(request);
4709
+ case 'pri(swapService.getOptimalProcessOnSelectQuote)':
4710
+ return this.getOptimalSwapProcessOnSelectQuote(request);
4721
4711
  case 'pri(swapService.handleSwapRequest)':
4722
4712
  return this.handleSwapRequest(request);
4713
+ case 'pri(swapService.handleSwapRequestV2)':
4714
+ return this.handleSwapRequestV2(request);
4723
4715
  case 'pri(swapService.getLatestQuote)':
4724
4716
  return this.getLatestSwapQuote(request);
4725
4717
  case 'pri(swapService.validateSwapProcess)':
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "./cjs/detectPackage.js"
18
18
  ],
19
19
  "type": "module",
20
- "version": "1.3.26-0",
20
+ "version": "1.3.27-1",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -1886,6 +1886,11 @@
1886
1886
  "require": "./cjs/services/swap-service/handler/uniswap-handler.js",
1887
1887
  "default": "./services/swap-service/handler/uniswap-handler.js"
1888
1888
  },
1889
+ "./services/swap-service/interface": {
1890
+ "types": "./services/swap-service/interface.d.ts",
1891
+ "require": "./cjs/services/swap-service/interface.js",
1892
+ "default": "./services/swap-service/interface.js"
1893
+ },
1889
1894
  "./services/swap-service/utils": {
1890
1895
  "types": "./services/swap-service/utils.d.ts",
1891
1896
  "require": "./cjs/services/swap-service/utils.js",
@@ -2664,13 +2669,13 @@
2664
2669
  "@reduxjs/toolkit": "^1.9.1",
2665
2670
  "@sora-substrate/type-definitions": "^1.17.7",
2666
2671
  "@substrate/connect": "^0.8.9",
2667
- "@subwallet/chain-list": "0.2.101",
2668
- "@subwallet/extension-base": "^1.3.26-0",
2669
- "@subwallet/extension-chains": "^1.3.26-0",
2670
- "@subwallet/extension-dapp": "^1.3.26-0",
2671
- "@subwallet/extension-inject": "^1.3.26-0",
2672
+ "@subwallet/chain-list": "0.2.102",
2673
+ "@subwallet/extension-base": "^1.3.27-1",
2674
+ "@subwallet/extension-chains": "^1.3.27-1",
2675
+ "@subwallet/extension-dapp": "^1.3.27-1",
2676
+ "@subwallet/extension-inject": "^1.3.27-1",
2672
2677
  "@subwallet/keyring": "^0.1.9",
2673
- "@subwallet/subwallet-api-sdk": "^1.3.26-0",
2678
+ "@subwallet/subwallet-api-sdk": "^1.3.27-1",
2674
2679
  "@subwallet/ui-keyring": "^0.1.9",
2675
2680
  "@ton/core": "^0.56.3",
2676
2681
  "@ton/crypto": "^3.2.0",
package/packageInfo.js CHANGED
@@ -7,5 +7,5 @@ export const packageInfo = {
7
7
  name: '@subwallet/extension-base',
8
8
  path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto',
9
9
  type: 'esm',
10
- version: '1.3.26-0'
10
+ version: '1.3.27-1'
11
11
  };
@@ -1,7 +1,7 @@
1
1
  import { _ChainAsset } from '@subwallet/chain-list/types';
2
2
  import { _Address } from '@subwallet/extension-base/background/KoniTypes';
3
3
  import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types';
4
- import { CommonOptimalPath } from '@subwallet/extension-base/types/service-base';
4
+ import { CommonOptimalTransferPath } from '@subwallet/extension-base/types/service-base';
5
5
  export interface RequestOptimalTransferProcess {
6
6
  originChain: string;
7
7
  destChain?: string;
@@ -9,5 +9,5 @@ export interface RequestOptimalTransferProcess {
9
9
  address: _Address;
10
10
  amount: string;
11
11
  }
12
- export declare function getDefaultTransferProcess(): CommonOptimalPath;
13
- export declare function getSnowbridgeTransferProcessFromEvm(address: string, evmApi: _EvmApi, tokenInfo: _ChainAsset, amount: string): Promise<CommonOptimalPath>;
12
+ export declare function getDefaultTransferProcess(): CommonOptimalTransferPath;
13
+ export declare function getSnowbridgeTransferProcessFromEvm(address: string, evmApi: _EvmApi, tokenInfo: _ChainAsset, amount: string): Promise<CommonOptimalTransferPath>;
@@ -3,8 +3,7 @@ import KoniState from '@subwallet/extension-base/koni/background/handlers/State'
3
3
  import { RequestOptimalTransferProcess } from '@subwallet/extension-base/services/balance-service/helpers/process';
4
4
  import { ServiceStatus, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
5
5
  import { EventItem, EventType } from '@subwallet/extension-base/services/event-service/types';
6
- import { BalanceItem, BalanceJson } from '@subwallet/extension-base/types';
7
- import { CommonOptimalPath } from '@subwallet/extension-base/types/service-base';
6
+ import { BalanceItem, BalanceJson, CommonOptimalTransferPath } from '@subwallet/extension-base/types';
8
7
  import { PromiseHandler } from '@subwallet/extension-base/utils';
9
8
  import { BehaviorSubject } from 'rxjs';
10
9
  /**
@@ -99,5 +98,5 @@ export declare class BalanceService implements StoppableServiceInterface {
99
98
  private startBalanceDetectCache;
100
99
  private startScanBalance;
101
100
  private stopScanBalance;
102
- getOptimalTransferProcess(params: RequestOptimalTransferProcess): Promise<CommonOptimalPath>;
101
+ getOptimalTransferProcess(params: RequestOptimalTransferProcess): Promise<CommonOptimalTransferPath>;
103
102
  }
@@ -5,7 +5,7 @@ const PRODUCTION_BRANCHES = ['master', 'webapp', 'webapp-dev'];
5
5
  const branchName = process.env.BRANCH_NAME || 'subwallet-dev';
6
6
  const fetchDomain = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'https://chain-list-assets.subwallet.app' : 'https://dev.sw-chain-list-assets.pages.dev';
7
7
  const fetchFile = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'list.json' : 'preview.json';
8
- const ChainListVersion = '0.2.101'; // update this when build chainlist
8
+ const ChainListVersion = '0.2.102'; // update this when build chainlist
9
9
 
10
10
  // todo: move this interface to chainlist
11
11
 
@@ -2,8 +2,7 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
2
2
  import { BalanceService } from '@subwallet/extension-base/services/balance-service';
3
3
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
4
4
  import FeeService from '@subwallet/extension-base/services/fee-service/service';
5
- import { BaseStepDetail, CommonOptimalPath, CommonStepFeeInfo } from '@subwallet/extension-base/types/service-base';
6
- import { OptimalSwapPathParams, SwapProviderId, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
5
+ import { BaseStepDetail, CommonOptimalSwapPath, CommonStepFeeInfo, OptimalSwapPathParams, OptimalSwapPathParamsV2, SwapProviderId, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types';
7
6
  import { SwapBaseInterface } from '../base-handler';
8
7
  export declare class AssetHubSwapHandler implements SwapBaseInterface {
9
8
  private swapBaseHandler;
@@ -20,10 +19,14 @@ export declare class AssetHubSwapHandler implements SwapBaseInterface {
20
19
  init(): Promise<void>;
21
20
  getXcmStep(params: OptimalSwapPathParams): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
22
21
  getSubmitStep(params: OptimalSwapPathParams): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
23
- generateOptimalProcess(params: OptimalSwapPathParams): Promise<CommonOptimalPath>;
22
+ getXcmStepV2(params: OptimalSwapPathParamsV2): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
23
+ getSwapStepV2(params: OptimalSwapPathParamsV2): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
24
+ generateOptimalProcess(params: OptimalSwapPathParams): Promise<CommonOptimalSwapPath>;
25
+ generateOptimalProcessV2(params: OptimalSwapPathParamsV2): Promise<CommonOptimalSwapPath>;
24
26
  handleXcmStep(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
25
27
  handleSubmitStep(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
26
28
  handleSwapProcess(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
27
29
  validateSwapStep(params: ValidateSwapProcessParams, isXcmOk: boolean, stepIndex: number): Promise<TransactionError[]>;
28
30
  validateSwapProcess(params: ValidateSwapProcessParams): Promise<TransactionError[]>;
31
+ validateSwapProcessV2(params: ValidateSwapProcessParams): Promise<TransactionError[]>;
29
32
  }
@@ -1,16 +1,16 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-base
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
4
5
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
6
  import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
7
  import { XCM_MIN_AMOUNT_RATIO } from '@subwallet/extension-base/constants';
7
8
  import { _validateBalanceToSwapOnAssetHub, _validateSwapRecipient } from '@subwallet/extension-base/core/logic-validation/swap';
8
9
  import { createXcmExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
9
- import { _getChainNativeTokenSlug, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
10
- import { getSwapAlternativeAsset } from '@subwallet/extension-base/services/swap-service/utils';
11
- import { BasicTxErrorType } from '@subwallet/extension-base/types';
12
- import { CommonStepType } from '@subwallet/extension-base/types/service-base';
13
- import { SwapErrorType, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types/swap';
10
+ import { _getChainNativeTokenSlug, _getTokenMinAmount, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
11
+ import { DynamicSwapType } from '@subwallet/extension-base/services/swap-service/interface';
12
+ import { FEE_RATE_MULTIPLIER, getSwapAlternativeAsset } from '@subwallet/extension-base/services/swap-service/utils';
13
+ import { BasicTxErrorType, CommonStepType, SwapErrorType, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
14
14
  import { getId } from '@subwallet/extension-base/utils/getId';
15
15
  import BigN from 'bignumber.js';
16
16
  import { SwapBaseHandler } from "../base-handler.js";
@@ -145,39 +145,131 @@ export class AssetHubSwapHandler {
145
145
  }
146
146
  return Promise.resolve(undefined);
147
147
  }
148
+ async getXcmStepV2(params) {
149
+ var _params$path$find;
150
+ // todo: improve this function for Round 2
151
+
152
+ 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;
153
+ if (!xcmPairInfo) {
154
+ return undefined;
155
+ }
156
+ const fromTokenInfo = this.chainService.getAssetBySlug(xcmPairInfo.from);
157
+ const toTokenInfo = this.chainService.getAssetBySlug(xcmPairInfo.to);
158
+ const fromChainInfo = this.chainService.getChainInfoByKey(fromTokenInfo.originChain);
159
+ const toChainInfo = this.chainService.getChainInfoByKey(toTokenInfo.originChain);
160
+ const substrateApi = await this.chainService.getSubstrateApi(fromTokenInfo.originChain).isReady;
161
+ if (!fromChainInfo || !toChainInfo || !fromChainInfo || !toChainInfo) {
162
+ throw Error('Token and chain not found');
163
+ }
164
+ try {
165
+ const id = getId();
166
+ 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)]);
167
+ const xcmTransfer = await createXcmExtrinsic({
168
+ originTokenInfo: fromTokenInfo,
169
+ destinationTokenInfo: toTokenInfo,
170
+ // Mock sending value to get payment info
171
+ sendingValue: params.request.fromAmount,
172
+ recipient: params.request.address,
173
+ substrateApi: substrateApi,
174
+ sender: params.request.address,
175
+ originChain: fromChainInfo,
176
+ destinationChain: toChainInfo,
177
+ feeInfo
178
+ });
179
+ const _xcmFeeInfo = await xcmTransfer.paymentInfo(params.request.address);
180
+ const xcmFeeInfo = _xcmFeeInfo.toPrimitive();
181
+ const fee = {
182
+ feeComponent: [{
183
+ feeType: SwapFeeType.NETWORK_FEE,
184
+ amount: Math.ceil(xcmFeeInfo.partialFee * FEE_RATE_MULTIPLIER.high).toString(),
185
+ tokenSlug: _getChainNativeTokenSlug(fromChainInfo)
186
+ }],
187
+ defaultFeeToken: _getChainNativeTokenSlug(fromChainInfo),
188
+ feeOptions: [_getChainNativeTokenSlug(fromChainInfo)]
189
+ };
190
+ let bnTransferAmount = new BigN(params.request.fromAmount);
191
+ if (_isNativeToken(fromTokenInfo)) {
192
+ // xcm fee is paid in native token but swap token is not always native token
193
+ // add amount of fee into sending value to ensure has enough token to swap
194
+ const bnXcmFee = new BigN(fee.feeComponent[0].amount);
195
+ bnTransferAmount = bnTransferAmount.plus(bnXcmFee);
196
+ } else {
197
+ bnTransferAmount = bnTransferAmount.plus(BigN(_getTokenMinAmount(toTokenInfo)).multipliedBy(FEE_RATE_MULTIPLIER.medium));
198
+ }
199
+ if (BigN(toTokenBalance.value).lte(0)) {
200
+ bnTransferAmount = bnTransferAmount.plus(_getTokenMinAmount(toTokenInfo));
201
+ }
202
+ const step = {
203
+ metadata: {
204
+ sendingValue: bnTransferAmount.toString(),
205
+ originTokenInfo: fromTokenInfo,
206
+ destinationTokenInfo: toTokenInfo
207
+ },
208
+ name: `Transfer ${fromTokenInfo.symbol} from ${fromChainInfo.name}`,
209
+ type: CommonStepType.XCM
210
+ };
211
+ return [step, fee];
212
+ } catch (e) {
213
+ console.error('Error creating xcm step', e);
214
+ return undefined;
215
+ }
216
+ }
217
+ async getSwapStepV2(params) {
218
+ var _params$path$find2;
219
+ 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;
220
+ if (!swapPairInfo) {
221
+ return Promise.resolve(undefined);
222
+ }
223
+ if (params.selectedQuote) {
224
+ const submitStep = {
225
+ name: 'Swap',
226
+ type: SwapStepType.SWAP,
227
+ metadata: {
228
+ sendingValue: params.request.fromAmount.toString(),
229
+ originTokenInfo: this.chainService.getAssetBySlug(swapPairInfo.from),
230
+ destinationTokenInfo: this.chainService.getAssetBySlug(swapPairInfo.to)
231
+ }
232
+ };
233
+ return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
234
+ }
235
+ return Promise.resolve(undefined);
236
+ }
148
237
  generateOptimalProcess(params) {
149
238
  return this.swapBaseHandler.generateOptimalProcess(params, [this.getXcmStep.bind(this), this.getSubmitStep.bind(this)]);
150
239
  }
240
+ generateOptimalProcessV2(params) {
241
+ const stepFuncList = params.path.map(step => {
242
+ if (step.action === DynamicSwapType.BRIDGE) {
243
+ return this.getXcmStepV2.bind(this);
244
+ }
245
+ if (step.action === DynamicSwapType.SWAP) {
246
+ return this.getSwapStepV2.bind(this);
247
+ }
248
+ throw new Error(`Error generating optimal process: Action ${step.action} is not supported`);
249
+ });
250
+ return this.swapBaseHandler.generateOptimalProcessV2(params, stepFuncList);
251
+ }
151
252
  async handleXcmStep(params) {
152
- const pair = params.quote.pair;
153
- const alternativeAssetSlug = getSwapAlternativeAsset(pair);
154
- const originAsset = this.chainService.getAssetBySlug(alternativeAssetSlug);
155
- const destinationAsset = this.chainService.getAssetBySlug(pair.from);
253
+ const briefXcmStep = params.process.steps[params.currentStep].metadata;
254
+ if (!briefXcmStep || !briefXcmStep.originTokenInfo || !briefXcmStep.destinationTokenInfo || !briefXcmStep.sendingValue) {
255
+ throw new Error('XCM metadata error');
256
+ }
257
+ const originAsset = briefXcmStep.originTokenInfo;
258
+ const destinationAsset = briefXcmStep.destinationTokenInfo;
156
259
  const originChain = this.chainService.getChainInfoByKey(originAsset.originChain);
157
260
  const destinationChain = this.chainService.getChainInfoByKey(destinationAsset.originChain);
158
261
  const substrateApi = this.chainService.getSubstrateApi(originAsset.originChain);
159
262
  const chainApi = await substrateApi.isReady;
160
- const destinationAssetBalance = await this.balanceService.getTransferableBalance(params.address, destinationAsset.originChain, destinationAsset.slug);
161
- const xcmFee = params.process.totalFee[params.currentStep];
162
- const bnAmount = new BigN(params.quote.fromAmount);
163
- const bnDestinationAssetBalance = new BigN(destinationAssetBalance.value);
164
- const id = getId();
165
- const feeInfo = await this.swapBaseHandler.feeService.subscribeChainFee(id, originChain.slug, 'substrate');
166
- let bnTotalAmount = bnAmount.minus(bnDestinationAssetBalance);
167
- if (_isNativeToken(originAsset)) {
168
- const bnXcmFee = new BigN(xcmFee.feeComponent[0].amount); // xcm fee is paid in native token but swap token is not always native token
169
-
170
- bnTotalAmount = bnTotalAmount.plus(bnXcmFee);
171
- }
263
+ const feeInfo = await this.swapBaseHandler.feeService.subscribeChainFee(getId(), originAsset.originChain, 'substrate');
172
264
  const xcmTransfer = await createXcmExtrinsic({
173
265
  originTokenInfo: originAsset,
174
266
  destinationTokenInfo: destinationAsset,
175
- sendingValue: bnTotalAmount.toString(),
267
+ sendingValue: briefXcmStep.sendingValue,
176
268
  recipient: params.address,
177
269
  substrateApi: chainApi,
178
270
  sender: params.address,
179
- originChain: originChain,
180
- destinationChain: destinationChain,
271
+ destinationChain,
272
+ originChain,
181
273
  feeInfo
182
274
  });
183
275
  const xcmData = {
@@ -185,14 +277,14 @@ export class AssetHubSwapHandler {
185
277
  destinationNetworkKey: destinationAsset.originChain,
186
278
  from: params.address,
187
279
  to: params.address,
188
- value: bnTotalAmount.toString(),
280
+ value: briefXcmStep.sendingValue,
189
281
  tokenSlug: originAsset.slug,
190
282
  showExtraWarning: true
191
283
  };
192
284
  return {
193
285
  txChain: originAsset.originChain,
194
286
  extrinsic: xcmTransfer,
195
- transferNativeAmount: _isNativeToken(originAsset) ? bnTotalAmount.toString() : '0',
287
+ transferNativeAmount: _isNativeToken(originAsset) ? briefXcmStep.sendingValue : '0',
196
288
  extrinsicType: ExtrinsicType.TRANSFER_XCM,
197
289
  chainType: ChainType.SUBSTRATE,
198
290
  txData: xcmData
@@ -200,7 +292,11 @@ export class AssetHubSwapHandler {
200
292
  }
201
293
  async handleSubmitStep(params) {
202
294
  var _this$router;
203
- const fromAsset = this.chainService.getAssetBySlug(params.quote.pair.from);
295
+ const metadata = params.process.steps[params.currentStep].metadata;
296
+ if (!metadata || !metadata.sendingValue || !metadata.destinationTokenInfo || !metadata.originTokenInfo) {
297
+ return new SwapError(SwapErrorType.UNKNOWN);
298
+ }
299
+ const fromAsset = metadata.originTokenInfo;
204
300
  const txData = {
205
301
  provider: this.providerInfo,
206
302
  quote: params.quote,
@@ -213,7 +309,12 @@ export class AssetHubSwapHandler {
213
309
  fromAmount,
214
310
  toAmount
215
311
  } = params.quote;
312
+
313
+ // todo: move to gen process
216
314
  const minReceive = new BigN(1 - params.slippage).times(toAmount).integerValue(BigN.ROUND_DOWN);
315
+ if (!params.address || !paths || !fromAmount || !minReceive) {
316
+ throw new SwapError(SwapErrorType.UNKNOWN);
317
+ }
217
318
  const extrinsic = await ((_this$router = this.router) === null || _this$router === void 0 ? void 0 : _this$router.buildSwapExtrinsic(paths, params.address, fromAmount, minReceive.toString()));
218
319
  return {
219
320
  txChain: fromAsset.originChain,
@@ -286,14 +387,22 @@ export class AssetHubSwapHandler {
286
387
  if (bnAmount.lte(0)) {
287
388
  return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')];
288
389
  }
390
+ const swapStep = params.process.steps.find(item => item.type === SwapStepType.SWAP);
391
+ if (!swapStep) {
392
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR, 'Swap step not found')];
393
+ }
289
394
  let isXcmOk = false;
395
+ const currentStep = params.currentStep;
290
396
  for (const [index, step] of params.process.steps.entries()) {
397
+ if (currentStep > index) {
398
+ continue;
399
+ }
291
400
  const getErrors = async () => {
292
401
  switch (step.type) {
293
402
  case CommonStepType.DEFAULT:
294
403
  return Promise.resolve([]);
295
404
  case CommonStepType.XCM:
296
- return this.swapBaseHandler.validateXcmStep(params, index);
405
+ return this.swapBaseHandler.validateXcmStepV2(params, index);
297
406
  case SwapStepType.SWAP:
298
407
  return this.validateSwapStep(params, isXcmOk, index);
299
408
  default:
@@ -309,4 +418,37 @@ export class AssetHubSwapHandler {
309
418
  }
310
419
  return [];
311
420
  }
421
+ async validateSwapProcessV2(params) {
422
+ // todo: recheck address and recipient format in params
423
+ const {
424
+ process,
425
+ selectedQuote
426
+ } = params; // todo: review flow, currentStep param.
427
+
428
+ // todo: validate path with optimalProcess
429
+ // todo: review error message in case many step swap
430
+ if (BigN(selectedQuote.fromAmount).lte(0)) {
431
+ return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')];
432
+ }
433
+ const actionList = process.steps.map(step => step.type);
434
+ const [firstStep, secondStep, thirdStep, fourthStep, fifthStep] = actionList;
435
+ const swap = firstStep === CommonStepType.DEFAULT && secondStep === SwapStepType.SWAP && !thirdStep;
436
+ const swapXcm = firstStep === CommonStepType.DEFAULT && secondStep === SwapStepType.SWAP && thirdStep === CommonStepType.XCM && !fourthStep;
437
+ const xcmSwap = firstStep === CommonStepType.DEFAULT && secondStep === CommonStepType.XCM && thirdStep === SwapStepType.SWAP && !fourthStep;
438
+ const xcmSwapXcm = firstStep === CommonStepType.DEFAULT && secondStep === CommonStepType.XCM && thirdStep === SwapStepType.SWAP && fourthStep === CommonStepType.XCM && !fifthStep;
439
+ if (swap) {
440
+ return this.swapBaseHandler.validateSwapOnlyProcess(params, 1); // todo: create interface for input request
441
+ }
442
+
443
+ if (swapXcm) {
444
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
445
+ }
446
+ if (xcmSwap) {
447
+ return this.swapBaseHandler.validateXcmSwapProcess(params, 2, 1);
448
+ }
449
+ if (xcmSwapXcm) {
450
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
451
+ }
452
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
453
+ }
312
454
  }
@@ -128,6 +128,9 @@ export const checkMinAmountForPath = (reserves, amounts, minAmounts) => {
128
128
  export const buildSwapExtrinsic = (api, paths, recipient, amountIn, amountOutMin, keepAlive = true) => {
129
129
  const pathsInfo = paths.map(asset => {
130
130
  const multilocation = _getXcmAssetMultilocation(asset);
131
+ if (!multilocation) {
132
+ throw new Error('Error getting multilocation');
133
+ }
131
134
  return api.createType('MultiLocation', multilocation).toU8a();
132
135
  });
133
136
  return api.tx.assetConversion.swapExactTokensForTokens(pathsInfo, amountIn, amountOutMin, recipient, keepAlive);
@@ -2,13 +2,16 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
2
2
  import { BalanceService } from '@subwallet/extension-base/services/balance-service';
3
3
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
4
4
  import FeeService from '@subwallet/extension-base/services/fee-service/service';
5
- import { BaseStepDetail, CommonOptimalPath, CommonStepFeeInfo } from '@subwallet/extension-base/types/service-base';
5
+ import { GenSwapStepFuncV2, OptimalSwapPathParamsV2 } from '@subwallet/extension-base/types';
6
+ import { BaseStepDetail, CommonOptimalSwapPath, CommonStepFeeInfo } from '@subwallet/extension-base/types/service-base';
6
7
  import { GenSwapStepFunc, OptimalSwapPathParams, SwapProvider, SwapProviderId, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
7
8
  export interface SwapBaseInterface {
8
9
  providerSlug: SwapProviderId;
9
- generateOptimalProcess: (params: OptimalSwapPathParams) => Promise<CommonOptimalPath>;
10
+ generateOptimalProcess: (params: OptimalSwapPathParams) => Promise<CommonOptimalSwapPath>;
11
+ generateOptimalProcessV2: (params: OptimalSwapPathParamsV2) => Promise<CommonOptimalSwapPath>;
10
12
  getSubmitStep: (params: OptimalSwapPathParams) => Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
11
13
  validateSwapProcess: (params: ValidateSwapProcessParams) => Promise<TransactionError[]>;
14
+ validateSwapProcessV2: (params: ValidateSwapProcessParams) => Promise<TransactionError[]>;
12
15
  handleSwapProcess: (params: SwapSubmitParams) => Promise<SwapSubmitStepData>;
13
16
  handleSubmitStep: (params: SwapSubmitParams) => Promise<SwapSubmitStepData>;
14
17
  isReady?: boolean;
@@ -28,11 +31,17 @@ export declare class SwapBaseHandler {
28
31
  balanceService: BalanceService;
29
32
  feeService: FeeService;
30
33
  constructor({ balanceService, chainService, feeService, providerName, providerSlug }: SwapBaseHandlerInitParams);
31
- generateOptimalProcess(params: OptimalSwapPathParams, genStepFuncList: GenSwapStepFunc[]): Promise<CommonOptimalPath>;
34
+ generateOptimalProcess(params: OptimalSwapPathParams, genStepFuncList: GenSwapStepFunc[]): Promise<CommonOptimalSwapPath>;
35
+ generateOptimalProcessV2(params: OptimalSwapPathParamsV2, genStepFuncList: GenSwapStepFuncV2[]): Promise<CommonOptimalSwapPath>;
32
36
  validateXcmStep(params: ValidateSwapProcessParams, stepIndex: number): Promise<TransactionError[]>;
37
+ validateXcmStepV2(params: ValidateSwapProcessParams, stepIndex: number): Promise<TransactionError[]>;
33
38
  validateTokenApproveStep(params: ValidateSwapProcessParams, stepIndex: number): Promise<TransactionError[]>;
34
39
  validateSetFeeTokenStep(params: ValidateSwapProcessParams, stepIndex: number): Promise<TransactionError[]>;
35
40
  validateSwapStep(params: ValidateSwapProcessParams, isXcmOk: boolean, stepIndex: number): Promise<TransactionError[]>;
41
+ private validateBridgeStep;
42
+ private validateSwapStepV2;
43
+ validateSwapOnlyProcess(params: ValidateSwapProcessParams, swapIndex: number): Promise<TransactionError[]>;
44
+ validateXcmSwapProcess(params: ValidateSwapProcessParams, swapIndex: number, xcmIndex: number): Promise<TransactionError[]>;
36
45
  get name(): string;
37
46
  get slug(): string;
38
47
  get providerInfo(): SwapProvider;