@subwallet/extension-base 1.3.37-0 → 1.3.39-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.
Files changed (32) hide show
  1. package/background/KoniTypes.d.ts +2 -0
  2. package/cjs/core/logic-validation/request.js +49 -12
  3. package/cjs/koni/background/handlers/State.js +4 -8
  4. package/cjs/koni/background/handlers/Tabs.js +38 -5
  5. package/cjs/packageInfo.js +1 -1
  6. package/cjs/page/cardano/cips/cip30.js +21 -1
  7. package/cjs/page/cardano/index.js +5 -5
  8. package/cjs/services/request-service/handler/AuthRequestHandler.js +2 -0
  9. package/cjs/services/request-service/handler/CardanoRequestHandler.js +4 -3
  10. package/cjs/services/request-service/helper/index.js +19 -17
  11. package/cjs/services/swap-service/handler/base-handler.js +4 -2
  12. package/cjs/services/swap-service/handler/uniswap-handler.js +122 -57
  13. package/cjs/services/swap-service/index.js +1 -1
  14. package/core/logic-validation/request.d.ts +1 -0
  15. package/core/logic-validation/request.js +50 -14
  16. package/koni/background/handlers/State.js +5 -9
  17. package/koni/background/handlers/Tabs.d.ts +1 -0
  18. package/koni/background/handlers/Tabs.js +38 -5
  19. package/package.json +8 -8
  20. package/packageInfo.js +1 -1
  21. package/page/cardano/cips/cip30.d.ts +31 -17
  22. package/page/cardano/cips/cip30.js +17 -1
  23. package/page/cardano/index.d.ts +20 -4
  24. package/page/cardano/index.js +5 -5
  25. package/services/request-service/handler/AuthRequestHandler.js +2 -0
  26. package/services/request-service/handler/CardanoRequestHandler.js +4 -3
  27. package/services/request-service/helper/index.js +19 -17
  28. package/services/swap-service/handler/base-handler.js +4 -2
  29. package/services/swap-service/handler/uniswap-handler.d.ts +1 -1
  30. package/services/swap-service/handler/uniswap-handler.js +99 -34
  31. package/services/swap-service/index.js +1 -1
  32. package/types/service-base.d.ts +1 -0
@@ -1,22 +1,36 @@
1
1
  import { CardanoPaginate, Cbor } from '@subwallet/extension-base/background/KoniTypes';
2
2
  import { SendRequest } from '@subwallet/extension-base/page/types';
3
3
  export declare class CIP30Api {
4
- private sendMessage;
4
+ private readonly sendMessage;
5
5
  constructor(sendMessage: SendRequest);
6
- getExtension(): {
7
- cip: number;
8
- }[];
9
- getNetworkId(): Promise<number>;
10
- getCollateral(payload: {
11
- amount: Cbor;
12
- }): Promise<string[] | null>;
13
- getUtxos(amount?: Cbor, paginate?: CardanoPaginate): Promise<string[] | null>;
14
- getUsedAddresses(): Promise<string[]>;
15
- getChangeAddress(): Promise<string>;
16
- getUnusedAddresses(): Promise<string[]>;
17
- getRewardAddresses(): Promise<string[]>;
18
- signTx(tx: Cbor, partialSign?: boolean): Promise<string>;
19
- signData(address: string, payload: string): Promise<import("@subwallet/extension-base/background/KoniTypes").ResponseCardanoSignData>;
20
- submitTx(tx: Cbor): Promise<string>;
21
- getBalance(): Promise<string>;
6
+ private getExtension;
7
+ private getNetworkId;
8
+ private getCollateral;
9
+ private getUtxos;
10
+ private getUsedAddresses;
11
+ private getChangeAddress;
12
+ private getUnusedAddresses;
13
+ private getRewardAddresses;
14
+ private signTx;
15
+ private signData;
16
+ private submitTx;
17
+ private getBalance;
18
+ get apis(): {
19
+ getExtension: () => {
20
+ cip: number;
21
+ }[];
22
+ getNetworkId: () => Promise<number>;
23
+ getCollateral: (payload: {
24
+ amount: Cbor;
25
+ }) => Promise<string[] | null>;
26
+ getUtxos: (amount?: Cbor, paginate?: CardanoPaginate) => Promise<string[] | null>;
27
+ getUsedAddresses: () => Promise<string[]>;
28
+ getChangeAddress: () => Promise<string>;
29
+ getUnusedAddresses: () => Promise<string[]>;
30
+ getRewardAddresses: () => Promise<string[]>;
31
+ signTx: (tx: Cbor, partialSign?: boolean) => Promise<string>;
32
+ signData: (address: string, payload: string) => Promise<import("@subwallet/extension-base/background/KoniTypes").ResponseCardanoSignData>;
33
+ submitTx: (tx: Cbor) => Promise<string>;
34
+ getBalance: () => Promise<string>;
35
+ };
22
36
  }
@@ -32,7 +32,7 @@ export class CIP30Api {
32
32
  return new Promise(resolve => resolve([]));
33
33
  }
34
34
  async getRewardAddresses() {
35
- return new Promise(resolve => resolve([]));
35
+ return await this.sendMessage('cardano(account.get.reward.address)');
36
36
  }
37
37
  async signTx(tx, partialSign = false) {
38
38
  return await this.sendMessage('cardano(transaction.sign)', {
@@ -52,4 +52,20 @@ export class CIP30Api {
52
52
  async getBalance() {
53
53
  return await this.sendMessage('cardano(account.get.balance)');
54
54
  }
55
+ get apis() {
56
+ return {
57
+ getExtension: () => this.getExtension(),
58
+ getNetworkId: () => this.getNetworkId(),
59
+ getCollateral: payload => this.getCollateral(payload),
60
+ getUtxos: (amount, paginate) => this.getUtxos(amount, paginate),
61
+ getUsedAddresses: () => this.getUsedAddresses(),
62
+ getChangeAddress: () => this.getChangeAddress(),
63
+ getUnusedAddresses: () => this.getUnusedAddresses(),
64
+ getRewardAddresses: () => this.getRewardAddresses(),
65
+ signTx: (tx, partialSign = false) => this.signTx(tx, partialSign),
66
+ signData: (address, payload) => this.signData(address, payload),
67
+ submitTx: tx => this.submitTx(tx),
68
+ getBalance: () => this.getBalance()
69
+ };
70
+ }
55
71
  }
@@ -1,13 +1,29 @@
1
1
  import type { CardanoExtensionCIP, CardanoProvider } from '@subwallet/extension-inject/types';
2
- import { CIP30Api } from '@subwallet/extension-base/page/cardano/cips';
3
2
  import { SendRequest } from '@subwallet/extension-base/page/types';
4
3
  export default class SubWalletCardanoProvider implements CardanoProvider {
5
4
  readonly apiVersion: string;
6
5
  readonly icon: string;
7
6
  readonly name: string;
8
7
  readonly supportedExtensions: CardanoExtensionCIP[];
9
- protected sendMessage: SendRequest;
8
+ private readonly sendMessage;
10
9
  constructor(sendMessage: SendRequest);
11
- enable(): Promise<Readonly<CIP30Api>>;
12
- isEnable(): Promise<boolean>;
10
+ enable: () => Promise<Readonly<{
11
+ getExtension: () => {
12
+ cip: number;
13
+ }[];
14
+ getNetworkId: () => Promise<number>;
15
+ getCollateral: (payload: {
16
+ amount: string;
17
+ }) => Promise<string[] | null>;
18
+ getUtxos: (amount?: string | undefined, paginate?: import("../../background/KoniTypes").CardanoPaginate | undefined) => Promise<string[] | null>;
19
+ getUsedAddresses: () => Promise<string[]>;
20
+ getChangeAddress: () => Promise<string>;
21
+ getUnusedAddresses: () => Promise<string[]>;
22
+ getRewardAddresses: () => Promise<string[]>;
23
+ signTx: (tx: string, partialSign?: boolean) => Promise<string>;
24
+ signData: (address: string, payload: string) => Promise<import("../../background/KoniTypes").ResponseCardanoSignData>;
25
+ submitTx: (tx: string) => Promise<string>;
26
+ getBalance: () => Promise<string>;
27
+ }>>;
28
+ isEnable: () => Promise<boolean>;
13
29
  }
@@ -14,7 +14,7 @@ export default class SubWalletCardanoProvider {
14
14
  this.icon = WALLET_ICON;
15
15
  this.sendMessage = sendMessage;
16
16
  }
17
- async enable() {
17
+ enable = async () => {
18
18
  const isEnabled = await this.sendMessage('pub(authorize.tabV2)', {
19
19
  origin,
20
20
  accountAuthTypes: ['cardano']
@@ -23,12 +23,12 @@ export default class SubWalletCardanoProvider {
23
23
  throw new Error('Access to the wallet is denied');
24
24
  }
25
25
  const CIP30 = new CIP30Api(this.sendMessage);
26
- return Object.freeze(CIP30);
27
- }
28
- async isEnable() {
26
+ return Object.freeze(CIP30.apis);
27
+ };
28
+ isEnable = async () => {
29
29
  const accountList = await this.sendMessage('pub(accounts.list)', {
30
30
  accountAuthType: 'cardano'
31
31
  });
32
32
  return accountList.length > 0;
33
- }
33
+ };
34
34
  }
@@ -43,6 +43,8 @@ export default class AuthRequestHandler {
43
43
  evm: existKeyEvmNetworkConnect
44
44
  };
45
45
  needUpdateAuthList = true;
46
+ } else if (!value.currentNetworkMap) {
47
+ value.currentNetworkMap = {};
46
48
  }
47
49
  acc[key] = {
48
50
  ...value
@@ -132,14 +132,15 @@ export default class CardanoRequestHandler {
132
132
  }
133
133
  signMessage(confirmation) {
134
134
  const {
135
- address,
135
+ address: addressToSign,
136
+ currentAddress,
136
137
  payload
137
138
  } = confirmation.payload;
138
- const pair = keyring.getPair(address);
139
+ const pair = keyring.getPair(currentAddress);
139
140
  if (pair.isLocked) {
140
141
  keyring.unlockPair(pair.address);
141
142
  }
142
- return pair.cardano.signMessage(payload, true);
143
+ return pair.cardano.signMessage(payload, addressToSign);
143
144
  }
144
145
  signTransactionCardano(confirmation) {
145
146
  // alibaba
@@ -46,25 +46,27 @@ export const extractMetadata = store => {
46
46
  export const convertAssetToValue = amount => {
47
47
  const value = CardanoWasm.Value.new(CardanoWasm.BigNum.from_str('0'));
48
48
  const multiAsset = CardanoWasm.MultiAsset.new();
49
- for (const item of amount) {
50
- if (item.unit === 'lovelace') {
51
- value.set_coin(CardanoWasm.BigNum.from_str(item.quantity));
52
- } else {
53
- const policyIdHex = item.unit.slice(0, 56);
54
- const assetNameHex = item.unit.slice(56);
55
- const scriptHash = CardanoWasm.ScriptHash.from_bytes(Buffer.from(policyIdHex, 'hex'));
56
- const assetName = CardanoWasm.AssetName.new(Buffer.from(assetNameHex, 'hex'));
57
- const quantity = CardanoWasm.BigNum.from_str(item.quantity);
58
- let assets = multiAsset.get(scriptHash);
59
- if (!assets) {
60
- assets = CardanoWasm.Assets.new();
49
+ if (amount !== null && amount !== void 0 && amount.length) {
50
+ for (const item of amount) {
51
+ if (item.unit === 'lovelace') {
52
+ value.set_coin(CardanoWasm.BigNum.from_str(item.quantity));
53
+ } else {
54
+ const policyIdHex = item.unit.slice(0, 56);
55
+ const assetNameHex = item.unit.slice(56);
56
+ const scriptHash = CardanoWasm.ScriptHash.from_bytes(Buffer.from(policyIdHex, 'hex'));
57
+ const assetName = CardanoWasm.AssetName.new(Buffer.from(assetNameHex, 'hex'));
58
+ const quantity = CardanoWasm.BigNum.from_str(item.quantity);
59
+ let assets = multiAsset.get(scriptHash);
60
+ if (!assets) {
61
+ assets = CardanoWasm.Assets.new();
62
+ }
63
+ assets.insert(assetName, quantity);
64
+ multiAsset.insert(scriptHash, assets);
61
65
  }
62
- assets.insert(assetName, quantity);
63
- multiAsset.insert(scriptHash, assets);
64
66
  }
65
- }
66
- if (multiAsset.len() > 0) {
67
- value.set_multiasset(multiAsset);
67
+ if (multiAsset.len() > 0) {
68
+ value.set_multiasset(multiAsset);
69
+ }
68
70
  }
69
71
  return value;
70
72
  };
@@ -165,6 +165,8 @@ export class SwapBaseHandler {
165
165
  if (needEditAmount) {
166
166
  bnSendingValue = BigN(selectedQuote.toAmount).multipliedBy(DEFAULT_EXCESS_AMOUNT_WEIGHT); // need to round
167
167
  } else {
168
+ // todo: remove
169
+ console.log('The code cannot run into here, if it runs into here, pls ask dev to check');
168
170
  bnSendingValue = BigN(selectedQuote.toAmount);
169
171
  }
170
172
  }
@@ -365,8 +367,8 @@ export class SwapBaseHandler {
365
367
  if (recipient) {
366
368
  const isEvmAddress = isEthereumAddress(recipient);
367
369
  const isEvmDestChain = _isChainEvmCompatible(swapToChain);
368
- if (isEvmAddress && !isEvmDestChain || !isEvmAddress && isEvmDestChain) {
369
- // todo: update this condition
370
+ if (isEvmAddress !== isEvmDestChain) {
371
+ // todo: update condition if support swap chain # EVM or Substrate
370
372
  return [new TransactionError(SwapErrorType.INVALID_RECIPIENT)];
371
373
  }
372
374
  }
@@ -71,7 +71,7 @@ export declare class UniswapHandler implements SwapBaseInterface {
71
71
  generateOptimalProcessV2(params: OptimalSwapPathParamsV2): Promise<CommonOptimalSwapPath>;
72
72
  getApprovalStep(params: OptimalSwapPathParamsV2, stepIndex: number): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
73
73
  getApproveSwap(params: OptimalSwapPathParamsV2): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
74
- getApproveBridge(params: OptimalSwapPathParamsV2): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
74
+ getApproveBridge(params: OptimalSwapPathParamsV2, isBridgeFirst: boolean): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
75
75
  getPermitStep(params: OptimalSwapPathParamsV2, stepIndex: number): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
76
76
  getSubmitStep(params: OptimalSwapPathParamsV2, stepIndex: number): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
77
77
  getBridgeStep(params: OptimalSwapPathParamsV2, stepIndex: number): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
@@ -7,6 +7,7 @@ import { validateTypedSignMessageDataV3V4 } from '@subwallet/extension-base/core
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
9
  import { getAcrossQuote } from '@subwallet/extension-base/services/balance-service/transfer/xcm/acrossBridge';
10
+ import { DEFAULT_EXCESS_AMOUNT_WEIGHT, FEE_RATE_MULTIPLIER } from '@subwallet/extension-base/services/swap-service/utils';
10
11
  import { BasicTxErrorType, CommonStepType, DynamicSwapType, FeeOptionKey, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
11
12
  import { _reformatAddressWithChain } from '@subwallet/extension-base/utils';
12
13
  import { getId } from '@subwallet/extension-base/utils/getId';
@@ -94,7 +95,8 @@ export class UniswapHandler {
94
95
  const stepFuncList = [];
95
96
  /**
96
97
  * approve - permit - swap or
97
- * approve - permit - swap - approve - bridge
98
+ * approve - permit - swap - approve - bridge or
99
+ * approve - bridge - approve - permit - swap
98
100
  */
99
101
 
100
102
  params.path.forEach(step => {
@@ -111,11 +113,26 @@ export class UniswapHandler {
111
113
  return this.swapBaseHandler.generateOptimalProcessV2(params, stepFuncList);
112
114
  }
113
115
  async getApprovalStep(params, stepIndex) {
114
- if (stepIndex === 0) {
116
+ /**
117
+ * Explain: All processes will go through one of below processes. If a step do not have, it returns undefined and
118
+ * the stepIndex is still counted up
119
+ *
120
+ * Processes:
121
+ * approve - permit - swap or
122
+ * approve - permit - swap - approve - bridge or
123
+ * approve - bridge - approve - permit - swap
124
+ */
125
+ const actionList = JSON.stringify(params.path.map(step => step.action));
126
+ const swap = actionList === JSON.stringify([DynamicSwapType.SWAP]);
127
+ const swapBridge = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
128
+ const bridgeSwap = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP]);
129
+ const isApproveBridge = stepIndex === 3 && swapBridge || stepIndex === 0 && bridgeSwap;
130
+ const isApproveSwap = stepIndex === 0 && swap || stepIndex === 0 && swapBridge || stepIndex === 2 && bridgeSwap;
131
+ if (isApproveSwap) {
115
132
  return this.getApproveSwap(params);
116
133
  }
117
- if (stepIndex === 3) {
118
- return this.getApproveBridge(params);
134
+ if (isApproveBridge) {
135
+ return this.getApproveBridge(params, bridgeSwap);
119
136
  }
120
137
  return Promise.resolve(undefined);
121
138
  }
@@ -196,20 +213,28 @@ export class UniswapHandler {
196
213
  };
197
214
  return Promise.resolve([submitStep, feeInfo]);
198
215
  }
199
- async getApproveBridge(params) {
200
- const quote = params.selectedQuote;
201
- if (!quote) {
216
+ async getApproveBridge(params, isBridgeFirst) {
217
+ const {
218
+ path,
219
+ request,
220
+ selectedQuote
221
+ } = params;
222
+ if (!selectedQuote) {
202
223
  return Promise.resolve(undefined);
203
224
  }
204
- console.log('params', params);
205
- const sendingAmount = quote.toAmount;
206
- const senderAddress = params.request.address;
207
- const fromTokenInfo = this.chainService.getAssetBySlug(quote.pair.to);
225
+ const bridgePairInfo = path.find(action => action.action === DynamicSwapType.BRIDGE);
226
+ if (!bridgePairInfo || !bridgePairInfo.pair) {
227
+ return Promise.resolve(undefined);
228
+ }
229
+ const _sendingAmount = isBridgeFirst ? request.fromAmount : selectedQuote.toAmount;
230
+ const sendingAmount = BigNumber(_sendingAmount).multipliedBy(2).toFixed(0, 1); // ensure approve enough amount
231
+ const senderAddress = request.address;
232
+ const fromTokenInfo = this.chainService.getAssetBySlug(bridgePairInfo.pair.from);
208
233
  const fromChainInfo = this.chainService.getChainInfoByKey(_getAssetOriginChain(fromTokenInfo));
209
234
  const fromChainId = _getEvmChainId(fromChainInfo);
210
235
  const evmApi = this.chainService.getEvmApi(fromChainInfo.slug);
211
236
  const tokenContract = _getContractAddressOfToken(fromTokenInfo);
212
- const toTokenInfo = this.chainService.getAssetBySlug(params.request.pair.to);
237
+ const toTokenInfo = this.chainService.getAssetBySlug(bridgePairInfo.pair.to);
213
238
  const toChainInfo = this.chainService.getChainInfoByKey(_getAssetOriginChain(toTokenInfo));
214
239
  if (_isNativeToken(fromTokenInfo)) {
215
240
  return Promise.resolve(undefined);
@@ -220,9 +245,10 @@ export class UniswapHandler {
220
245
  const inputData = {
221
246
  destinationTokenInfo: toTokenInfo,
222
247
  originTokenInfo: fromTokenInfo,
223
- sendingValue: sendingAmount,
248
+ sendingValue: _sendingAmount,
224
249
  sender: senderAddress,
225
250
  recipient: senderAddress,
251
+ // todo: there's a case swap - bridge to another address
226
252
  destinationChain: toChainInfo,
227
253
  originChain: fromChainInfo
228
254
  };
@@ -295,6 +321,10 @@ export class UniswapHandler {
295
321
  if (!selectedQuote) {
296
322
  return Promise.resolve(undefined);
297
323
  }
324
+ const actionList = JSON.stringify(path.map(step => step.action));
325
+ const swapXcm = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
326
+ const sendingValue = swapXcm ? BigNumber(request.fromAmount).multipliedBy(DEFAULT_EXCESS_AMOUNT_WEIGHT).toFixed(0, 1) : request.fromAmount;
327
+ const expectedReceive = swapXcm ? BigNumber(selectedQuote.toAmount).multipliedBy(DEFAULT_EXCESS_AMOUNT_WEIGHT).toFixed(0, 1) : selectedQuote.toAmount;
298
328
  const originTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.from);
299
329
  const destinationTokenInfo = this.chainService.getAssetBySlug(selectedQuote.pair.to);
300
330
  const originChain = this.chainService.getChainInfoByKey(originTokenInfo.originChain);
@@ -304,8 +334,8 @@ export class UniswapHandler {
304
334
  type: SwapStepType.SWAP,
305
335
  // @ts-ignore
306
336
  metadata: {
307
- sendingValue: request.fromAmount.toString(),
308
- expectedReceive: selectedQuote.toAmount,
337
+ sendingValue,
338
+ expectedReceive,
309
339
  originTokenInfo,
310
340
  destinationTokenInfo,
311
341
  sender: _reformatAddressWithChain(request.address, originChain),
@@ -321,6 +351,20 @@ export class UniswapHandler {
321
351
  request,
322
352
  selectedQuote
323
353
  } = params;
354
+ /**
355
+ * Explain: All processes will go through one of below processes. If a step do not have, it returns undefined and
356
+ * the stepIndex is still counted up
357
+ *
358
+ * Processes:
359
+ * approve - permit - swap or
360
+ * approve - permit - swap - approve - bridge or
361
+ * approve - bridge - approve - permit - swap
362
+ */
363
+ const actionList = JSON.stringify(path.map(step => step.action));
364
+ const bridgeSwap = actionList === JSON.stringify([DynamicSwapType.BRIDGE, DynamicSwapType.SWAP]);
365
+ const swapBridge = actionList === JSON.stringify([DynamicSwapType.SWAP, DynamicSwapType.BRIDGE]);
366
+ const isBridgeFirst = stepIndex === 1 && bridgeSwap;
367
+ const isBridgeSecond = stepIndex === 4 && swapBridge;
324
368
 
325
369
  // stepIndex is not corresponding index in path, because uniswap include approval and permit step
326
370
  const bridgePairInfo = path.find(action => action.action === DynamicSwapType.BRIDGE);
@@ -337,9 +381,18 @@ export class UniswapHandler {
337
381
  if (!fromChainInfo || !toChainInfo || !fromChainInfo || !toChainInfo) {
338
382
  throw Error('Token or chain not found');
339
383
  }
384
+ let receiverAddress;
385
+ let mockSendingValue;
340
386
  const senderAddress = _reformatAddressWithChain(request.address, fromChainInfo);
341
- const receiverAddress = _reformatAddressWithChain(request.recipient || request.address, toChainInfo);
342
- const sendingValue = BigNumber(selectedQuote.toAmount).div(1.02).toFixed(0, 1);
387
+ if (isBridgeFirst) {
388
+ receiverAddress = _reformatAddressWithChain(request.address, toChainInfo);
389
+ mockSendingValue = BigNumber(selectedQuote.fromAmount).toFixed(0, 1);
390
+ } else if (isBridgeSecond) {
391
+ receiverAddress = _reformatAddressWithChain(request.recipient || request.address, toChainInfo);
392
+ mockSendingValue = BigNumber(selectedQuote.toAmount).toFixed(0, 1);
393
+ } else {
394
+ return undefined;
395
+ }
343
396
  try {
344
397
  const evmApi = await this.chainService.getEvmApi(fromChainInfo.slug).isReady;
345
398
  const feeInfo = await this.feeService.subscribeChainFee(getId(), fromTokenInfo.originChain, 'evm');
@@ -351,25 +404,37 @@ export class UniswapHandler {
351
404
  evmApi,
352
405
  feeInfo,
353
406
  // Mock sending value to get payment info
354
- sendingValue,
407
+ sendingValue: mockSendingValue,
355
408
  sender: senderAddress,
356
409
  recipient: receiverAddress
357
410
  });
358
-
359
- // // todo: wait until this ready to get destination fee. the real receiveAmount is deduce by this fee
360
- // const acrossQuote = await getAcrossQuote({
361
- // destinationChain: toChainInfo,
362
- // destinationTokenInfo: toTokenInfo,
363
- // originChain: fromChainInfo,
364
- // originTokenInfo: fromTokenInfo,
365
- // recipient: receiverAddress,
366
- // sender: senderAddress,
367
- // sendingValue,
368
- // feeInfo
369
- // });
370
-
411
+ const acrossQuote = await getAcrossQuote({
412
+ destinationChain: toChainInfo,
413
+ destinationTokenInfo: toTokenInfo,
414
+ originChain: fromChainInfo,
415
+ originTokenInfo: fromTokenInfo,
416
+ recipient: receiverAddress,
417
+ sender: senderAddress,
418
+ sendingValue: mockSendingValue,
419
+ feeInfo
420
+ });
421
+ const acrossQuoteMetadata = acrossQuote.metadata;
371
422
  const estimatedBridgeFee = await estimateTxFee(tx, evmApi, feeInfo);
372
- const expectedReceive = BigNumber(sendingValue).minus(estimatedBridgeFee).toFixed(0, 1);
423
+ const estimatedDestinationFee = BigNumber(mockSendingValue).minus(acrossQuoteMetadata.outputAmount).toFixed(0, 1); // todo: should better handle on backend and return desFee metadata instead of minus like this
424
+
425
+ let sendingValue;
426
+ let expectedReceive;
427
+ if (isBridgeFirst) {
428
+ expectedReceive = selectedQuote.fromAmount;
429
+ sendingValue = BigNumber(estimatedDestinationFee).multipliedBy(FEE_RATE_MULTIPLIER.medium).plus(selectedQuote.fromAmount).toFixed(0, 1);
430
+ } else if (isBridgeSecond) {
431
+ expectedReceive = selectedQuote.toAmount;
432
+ sendingValue = BigNumber(selectedQuote.toAmount).multipliedBy(DEFAULT_EXCESS_AMOUNT_WEIGHT).toFixed(0, 1);
433
+ } else {
434
+ return undefined;
435
+ }
436
+ console.log('[i] estimatedBridgeFee', estimatedBridgeFee);
437
+ console.log('[i] estimatedDestinationFee', estimatedDestinationFee);
373
438
  const fee = {
374
439
  feeComponent: [{
375
440
  feeType: SwapFeeType.NETWORK_FEE,
@@ -738,7 +803,7 @@ export class UniswapHandler {
738
803
  if (swapIndex <= -1) {
739
804
  return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
740
805
  }
741
- if (swapXcm && bridgeIndex <= -1) {
806
+ if ((swapXcm || xcmSwap) && bridgeIndex <= -1) {
742
807
  return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
743
808
  }
744
809
  if (swap) {
@@ -749,7 +814,7 @@ export class UniswapHandler {
749
814
  return this.swapBaseHandler.validateSwapXcmProcess(params, swapIndex, bridgeIndex);
750
815
  }
751
816
  if (xcmSwap) {
752
- return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
817
+ return this.swapBaseHandler.validateXcmSwapProcess(params, swapIndex, bridgeIndex);
753
818
  }
754
819
  if (xcmSwapXcm) {
755
820
  return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
@@ -39,7 +39,7 @@ export class SwapService {
39
39
  var _subwalletApiSdk$swap;
40
40
  const availableQuotes = [];
41
41
 
42
- // hotfix
42
+ // hotfix // todo: remove later
43
43
  const request = {
44
44
  ..._request,
45
45
  isSupportKyberVersion: true
@@ -20,6 +20,7 @@ export interface CommonFeeComponent {
20
20
  feeType: BaseFeeType;
21
21
  amount: string;
22
22
  tokenSlug: string;
23
+ percentage?: number;
23
24
  }
24
25
  export interface CommonStepFeeInfo {
25
26
  feeComponent: CommonFeeComponent[];