diff --git a/packages/checkout/sdk/src/smartCheckout/routing/bridge/bridgeRoute.test.ts b/packages/checkout/sdk/src/smartCheckout/routing/bridge/bridgeRoute.test.ts index 14025c820e..de10498b18 100644 --- a/packages/checkout/sdk/src/smartCheckout/routing/bridge/bridgeRoute.test.ts +++ b/packages/checkout/sdk/src/smartCheckout/routing/bridge/bridgeRoute.test.ts @@ -1,6 +1,6 @@ import { Environment } from '@imtbl/config'; import { JsonRpcProvider } from '@ethersproject/providers'; -import { BigNumber } from 'ethers'; +import { BigNumber, utils } from 'ethers'; import { BridgeRequirement, bridgeRoute, @@ -12,6 +12,7 @@ import { CheckoutConfiguration } from '../../../config'; import { BridgeRouteFeeEstimate, ChainId, + DEFAULT_TOKEN_DECIMALS, FundingRouteFeeEstimate, FundingStepType, ItemType, @@ -47,7 +48,7 @@ describe('bridgeRoute', () => { { type: FundingStepType.BRIDGE, gasFee: { - estimatedAmount: BigNumber.from(1), + estimatedAmount: BigNumber.from(2), token: { name: 'Ethereum', symbol: 'ETH', @@ -55,14 +56,14 @@ describe('bridgeRoute', () => { }, }, bridgeFee: { - estimatedAmount: BigNumber.from(1), + estimatedAmount: BigNumber.from(3), token: { name: 'Ethereum', symbol: 'ETH', decimals: 18, }, }, - totalFees: BigNumber.from(2), + totalFees: BigNumber.from(5), }, ], ]); @@ -110,8 +111,8 @@ describe('bridgeRoute', () => { }, }, { - balance: BigNumber.from(13), - formattedBalance: '13', + balance: BigNumber.from(16), + formattedBalance: '16', token: { name: 'Ethereum', symbol: 'ETH', @@ -144,8 +145,8 @@ describe('bridgeRoute', () => { formattedAmount: '10', }, userBalance: { - balance: BigNumber.from(13), - formattedBalance: '13', + balance: BigNumber.from(16), + formattedBalance: '16', }, token: { name: 'Ethereum', @@ -154,19 +155,33 @@ describe('bridgeRoute', () => { address: undefined, }, }, - // WT-1734 - Add fees fees: { approvalGasFees: { amount: BigNumber.from(0), - formattedAmount: '0', + formattedAmount: utils.formatUnits(BigNumber.from(0), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }, bridgeGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(2), + formattedAmount: utils.formatUnits(BigNumber.from(2), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }, bridgeFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(3), + formattedAmount: utils.formatUnits(BigNumber.from(3), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }], }, }); @@ -178,8 +193,8 @@ describe('bridgeRoute', () => { success: true, balances: [ { - balance: BigNumber.from(12), - formattedBalance: '12', + balance: BigNumber.from(15), + formattedBalance: '15', token: { name: 'Ethereum', symbol: 'ETH', @@ -212,8 +227,8 @@ describe('bridgeRoute', () => { formattedAmount: '10', }, userBalance: { - balance: BigNumber.from(12), - formattedBalance: '12', + balance: BigNumber.from(15), + formattedBalance: '15', }, token: { name: 'Ethereum', @@ -222,19 +237,33 @@ describe('bridgeRoute', () => { address: undefined, }, }, - // WT-1734 - Add fees fees: { approvalGasFees: { amount: BigNumber.from(0), - formattedAmount: '0', + formattedAmount: utils.formatUnits(BigNumber.from(0), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }, bridgeGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(2), + formattedAmount: utils.formatUnits(BigNumber.from(2), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }, bridgeFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(3), + formattedAmount: utils.formatUnits(BigNumber.from(3), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }], }, }); @@ -246,8 +275,8 @@ describe('bridgeRoute', () => { success: true, balances: [ { - balance: BigNumber.from(11), - formattedBalance: '11', + balance: BigNumber.from(14), + formattedBalance: '14', token: { name: 'Ethereum', symbol: 'ETH', @@ -289,8 +318,8 @@ describe('bridgeRoute', () => { }, }, { - balance: BigNumber.from(12), - formattedBalance: '12', + balance: BigNumber.from(20), + formattedBalance: '20', token: { name: 'Ethereum', symbol: 'ETH', @@ -353,8 +382,8 @@ describe('bridgeRoute', () => { success: true, balances: [ { - balance: BigNumber.from(10), - formattedBalance: '10', + balance: BigNumber.from(7), + formattedBalance: '7', token: { name: 'Ethereum', symbol: 'ETH', @@ -362,8 +391,8 @@ describe('bridgeRoute', () => { }, }, { - balance: BigNumber.from(11), - formattedBalance: '11', + balance: BigNumber.from(10), + formattedBalance: '10', token: { name: '0xERC20', symbol: '0xERC20', @@ -397,8 +426,8 @@ describe('bridgeRoute', () => { formattedAmount: '10', }, userBalance: { - balance: BigNumber.from(11), - formattedBalance: '11', + balance: BigNumber.from(10), + formattedBalance: '10', }, token: { name: '0xERC20', @@ -407,19 +436,33 @@ describe('bridgeRoute', () => { decimals: 18, }, }, - // WT-1734 - Add fees fees: { approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(1), + formattedAmount: utils.formatUnits(BigNumber.from(1), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }, bridgeGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(2), + formattedAmount: utils.formatUnits(BigNumber.from(2), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }, bridgeFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(3), + formattedAmount: utils.formatUnits(BigNumber.from(3), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }], }, }); @@ -431,8 +474,8 @@ describe('bridgeRoute', () => { success: true, balances: [ { - balance: BigNumber.from(2), - formattedBalance: '2', + balance: BigNumber.from(6), + formattedBalance: '6', token: { name: 'Ethereum', symbol: 'ETH', @@ -485,19 +528,33 @@ describe('bridgeRoute', () => { decimals: 18, }, }, - // WT-1734 - Add fees fees: { approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(1), + formattedAmount: utils.formatUnits(BigNumber.from(1), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }, bridgeGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(2), + formattedAmount: utils.formatUnits(BigNumber.from(2), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }, bridgeFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(3), + formattedAmount: utils.formatUnits(BigNumber.from(3), DEFAULT_TOKEN_DECIMALS), + token: { + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + }, }], }, }); @@ -509,8 +566,8 @@ describe('bridgeRoute', () => { success: true, balances: [ { - balance: BigNumber.from(2), - formattedBalance: '2', + balance: BigNumber.from(10), + formattedBalance: '10', token: { name: 'Ethereum', symbol: 'ETH', @@ -552,8 +609,8 @@ describe('bridgeRoute', () => { success: true, balances: [ { - balance: BigNumber.from(1), - formattedBalance: '1', + balance: BigNumber.from(4), + formattedBalance: '4', token: { name: 'Ethereum', symbol: 'ETH', diff --git a/packages/checkout/sdk/src/smartCheckout/routing/bridge/bridgeRoute.ts b/packages/checkout/sdk/src/smartCheckout/routing/bridge/bridgeRoute.ts index 76c62b7871..e67f7c9755 100644 --- a/packages/checkout/sdk/src/smartCheckout/routing/bridge/bridgeRoute.ts +++ b/packages/checkout/sdk/src/smartCheckout/routing/bridge/bridgeRoute.ts @@ -1,4 +1,4 @@ -import { BigNumber, ethers } from 'ethers'; +import { BigNumber, ethers, utils } from 'ethers'; import { BridgeFundingStep, ChainId, @@ -9,6 +9,9 @@ import { AvailableRoutingOptions, BridgeRouteFeeEstimate, FundingRouteFeeEstimate, + BridgeFees, + TokenInfo, + DEFAULT_TOKEN_DECIMALS, } from '../../../types'; import { CheckoutConfiguration, getL1ChainId } from '../../../config'; import { @@ -58,11 +61,43 @@ export const getBridgeGasEstimate = async ( return bridgeFeeEstimate; }; +const constructFees = ( + approvalGasFees: BigNumber, + bridgeGasFees: { + estimatedAmount: BigNumber, + token?: TokenInfo, + }, + bridgeFee: { + estimatedAmount: BigNumber, + token?: TokenInfo, + }, +): BridgeFees => { + const bridgeFeeDecimals = bridgeFee.token?.decimals ?? DEFAULT_TOKEN_DECIMALS; + return { + approvalGasFees: { + amount: approvalGasFees, + formattedAmount: utils.formatUnits(approvalGasFees, DEFAULT_TOKEN_DECIMALS), + token: bridgeGasFees.token, + }, + bridgeGasFees: { + amount: bridgeGasFees.estimatedAmount, + formattedAmount: utils.formatUnits(bridgeGasFees.estimatedAmount, DEFAULT_TOKEN_DECIMALS), + token: bridgeGasFees.token, + }, + bridgeFees: [{ + amount: bridgeFee.estimatedAmount, + formattedAmount: utils.formatUnits(bridgeFee.estimatedAmount, bridgeFeeDecimals), + token: bridgeFee.token, + }], + }; +}; + const constructBridgeFundingRoute = ( chainId: ChainId, balance: GetBalanceResult, bridgeRequirement: BridgeRequirement, itemType: ItemType.NATIVE | ItemType.ERC20, + fees: BridgeFees, ): BridgeFundingStep => ({ type: FundingStepType.BRIDGE, chainId, @@ -83,21 +118,7 @@ const constructBridgeFundingRoute = ( decimals: balance.token.decimals, }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - bridgeGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - bridgeFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, + fees, }); export const isNativeEth = (address: string | undefined): boolean => { @@ -183,13 +204,19 @@ export const bridgeRoute = async ( if (nativeETHBalance && nativeETHBalance.balance.gte( bridgeRequirement.amount.add(totalFees), )) { - return constructBridgeFundingRoute(chainId, nativeETHBalance, bridgeRequirement, ItemType.NATIVE); + const bridgeFees = constructFees( + gasForApproval, + bridgeFeeEstimate.gasFee, + bridgeFeeEstimate.bridgeFee, + ); + return constructBridgeFundingRoute(chainId, nativeETHBalance, bridgeRequirement, ItemType.NATIVE, bridgeFees); } return undefined; } totalFees.add(gasForApproval).add(bridgeFeeEstimate.gasFee.estimatedAmount); + if (!hasSufficientL1Eth( tokenBalanceResult, totalFees, @@ -197,10 +224,16 @@ export const bridgeRoute = async ( // Find the balance of the L1 representation of the token and check if the balance covers the delta const erc20balance = tokenBalanceResult.balances.find((balance) => balance.token.address === l1address); + if (erc20balance && erc20balance.balance.gte( bridgeRequirement.amount, )) { - return constructBridgeFundingRoute(chainId, erc20balance, bridgeRequirement, ItemType.ERC20); + const bridgeFees = constructFees( + gasForApproval, + bridgeFeeEstimate.gasFee, + bridgeFeeEstimate.bridgeFee, + ); + return constructBridgeFundingRoute(chainId, erc20balance, bridgeRequirement, ItemType.ERC20, bridgeFees); } return undefined; diff --git a/packages/checkout/sdk/src/smartCheckout/routing/routingCalculator.test.ts b/packages/checkout/sdk/src/smartCheckout/routing/routingCalculator.test.ts index 9589a7cd8e..0af37a3958 100644 --- a/packages/checkout/sdk/src/smartCheckout/routing/routingCalculator.test.ts +++ b/packages/checkout/sdk/src/smartCheckout/routing/routingCalculator.test.ts @@ -337,21 +337,6 @@ describe('routingCalculator', () => { fundingRoutes: [{ priority: 1, steps: [bridgeFundingStep], - // WT-1734 - Add fees - totalFees: { - gas: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - other: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - total: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - }, }], }); }); @@ -470,21 +455,6 @@ describe('routingCalculator', () => { address: '0xERC20_2', }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, }; (swapRoute as jest.Mock).mockResolvedValue([swapFundingStep]); @@ -505,21 +475,6 @@ describe('routingCalculator', () => { fundingRoutes: [{ priority: 1, steps: [swapFundingStep], - // WT-1734 - Add fees - totalFees: { - gas: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - other: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - total: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - }, }], }); }); @@ -654,21 +609,6 @@ describe('routingCalculator', () => { address: '0xERC20_2', }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, }; const swapFundingStep2 = { @@ -691,21 +631,6 @@ describe('routingCalculator', () => { address: '0xERC20_3', }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, }; (swapRoute as jest.Mock).mockResolvedValue([swapFundingStep1, swapFundingStep2]); @@ -727,39 +652,9 @@ describe('routingCalculator', () => { fundingRoutes: [{ priority: 1, steps: [swapFundingStep1], - // WT-1734 - Add fees - totalFees: { - gas: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - other: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - total: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - }, }, { priority: 1, steps: [swapFundingStep2], - // WT-1734 - Add fees - totalFees: { - gas: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - other: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - total: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - }, }], }); }); @@ -1070,21 +965,6 @@ describe('routingCalculator', () => { address: '0xERC20_2', }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, }; (swapRoute as jest.Mock).mockResolvedValue([swapFundingStep]); @@ -1108,21 +988,6 @@ describe('routingCalculator', () => { address: '0xIMXL1', }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - bridgeGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - bridgeFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, }; const swapImxFundingStep = { type: FundingStepType.SWAP, @@ -1144,21 +1009,6 @@ describe('routingCalculator', () => { address: '0xIMX', }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, }; (bridgeAndSwapRoute as jest.Mock).mockResolvedValue([ { @@ -1185,40 +1035,10 @@ describe('routingCalculator', () => { { priority: 1, steps: [bridgeFundingStep], - // WT-1734 - Add fees - totalFees: { - gas: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - other: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - total: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - }, }, { priority: 2, steps: [swapFundingStep], - // WT-1734 - Add fees - totalFees: { - gas: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - other: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - total: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - }, }, { priority: 3, @@ -1226,21 +1046,6 @@ describe('routingCalculator', () => { bridgeImxFundingStep, swapImxFundingStep, ], - // WT-1734 - Add fees - totalFees: { - gas: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - other: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - total: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - }, }, ], }); @@ -1470,21 +1275,6 @@ describe('routingCalculator', () => { address: '0xERC20_2', }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, }; (swapRoute as jest.Mock).mockResolvedValue([swapFundingStep]); @@ -1568,6 +1358,10 @@ describe('routingCalculator', () => { address: '0xERC20_2', }, ], + { + sufficient: false, + balanceRequirements: [balanceRequirement], + }, ); expect(swapFundingSteps).toEqual([swapFundingStep]); @@ -1623,6 +1417,10 @@ describe('routingCalculator', () => { address: '0xERC20_2', }, ], + { + sufficient: false, + balanceRequirements: [], + }, ); expect(swapFundingSteps).toEqual([]); @@ -1709,6 +1507,10 @@ describe('routingCalculator', () => { address: '0xERC20_2', }, ], + { + sufficient: false, + balanceRequirements: [balanceRequirement], + }, ); expect(swapFundingSteps).toEqual([]); @@ -1796,6 +1598,10 @@ describe('routingCalculator', () => { address: '0xERC20_2', }, ], + { + sufficient: false, + balanceRequirements: [balanceRequirement], + }, ); expect(swapFundingSteps).toEqual([]); @@ -1882,6 +1688,10 @@ describe('routingCalculator', () => { address: '0xERC20_2', }, ], + { + sufficient: false, + balanceRequirements: [balanceRequirement], + }, ); expect(swapFundingSteps).toEqual([]); @@ -1970,6 +1780,10 @@ describe('routingCalculator', () => { '0xADDRESS', balances, [], + { + sufficient: false, + balanceRequirements: [balanceRequirement], + }, ); expect(swapFundingSteps).toEqual([]); @@ -2271,21 +2085,6 @@ describe('routingCalculator', () => { address: '0xIMXL1', }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - bridgeGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - bridgeFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, }; const swapFundingStep = { type: FundingStepType.SWAP, @@ -2307,21 +2106,6 @@ describe('routingCalculator', () => { address: '0xIMX', }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, }; (bridgeAndSwapRoute as jest.Mock).mockResolvedValue([ { diff --git a/packages/checkout/sdk/src/smartCheckout/routing/routingCalculator.ts b/packages/checkout/sdk/src/smartCheckout/routing/routingCalculator.ts index 387db8f965..3a6f5dac1d 100644 --- a/packages/checkout/sdk/src/smartCheckout/routing/routingCalculator.ts +++ b/packages/checkout/sdk/src/smartCheckout/routing/routingCalculator.ts @@ -1,4 +1,3 @@ -import { BigNumber } from 'ethers'; import { JsonRpcProvider } from '@ethersproject/providers'; import { BalanceCheckResult, @@ -326,21 +325,6 @@ export const routingCalculator = async ( response.fundingRoutes.push({ priority, steps: [bridgeFundingStep], - // WT-1734 - Add fees - totalFees: { - gas: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - other: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - total: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - }, }); } @@ -350,21 +334,6 @@ export const routingCalculator = async ( response.fundingRoutes.push({ priority, steps: [swapFundingStep], - // WT-1734 - Add fees - totalFees: { - gas: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - other: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - total: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - }, }); }); } @@ -385,21 +354,6 @@ export const routingCalculator = async ( response.fundingRoutes.push({ priority, steps: [bridgeStep, swapStep], - // WT-1734 - Add fees - totalFees: { - gas: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - other: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - total: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - }, }); }); } diff --git a/packages/checkout/sdk/src/smartCheckout/routing/swap/swapRoute.test.ts b/packages/checkout/sdk/src/smartCheckout/routing/swap/swapRoute.test.ts index 1bafb96104..f80e58fb1e 100644 --- a/packages/checkout/sdk/src/smartCheckout/routing/swap/swapRoute.test.ts +++ b/packages/checkout/sdk/src/smartCheckout/routing/swap/swapRoute.test.ts @@ -58,7 +58,7 @@ describe('swapRoute', () => { fees: [ { amount: { - value: BigNumber.from(1), + value: BigNumber.from(3), token: { chainId: ChainId.IMTBL_ZKEVM_TESTNET, name: 'IMX', @@ -83,8 +83,14 @@ describe('swapRoute', () => { } as TokenInfo, }, swap: { - value: BigNumber.from(1), - token: {} as TokenInfo, + value: BigNumber.from(2), + token: { + chainId: ChainId.IMTBL_ZKEVM_TESTNET, + name: 'IMX', + symbol: 'IMX', + decimals: 18, + address: IMX_ADDRESS_ZKEVM, + } as TokenInfo, }, }, ], @@ -109,7 +115,7 @@ describe('swapRoute', () => { fees: [ { amount: { - value: BigNumber.from(1), + value: BigNumber.from(3), token: { chainId: ChainId.IMTBL_ZKEVM_TESTNET, name: 'IMX', @@ -134,8 +140,14 @@ describe('swapRoute', () => { } as TokenInfo, }, swap: { - value: BigNumber.from(1), - token: {} as TokenInfo, + value: BigNumber.from(2), + token: { + chainId: ChainId.IMTBL_ZKEVM_TESTNET, + name: 'IMX', + symbol: 'IMX', + decimals: 18, + address: IMX_ADDRESS_ZKEVM, + } as TokenInfo, }, }, ], @@ -299,19 +311,36 @@ describe('swapRoute', () => { symbol: 'ERC20', }, }, - // WT-1734 - Add fees fees: { approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(1), + formattedAmount: utils.formatUnits(BigNumber.from(1), 18), + token: { + address: IMX_ADDRESS_ZKEVM, + decimals: 18, + name: 'IMX', + symbol: 'IMX', + }, }, swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(2), + formattedAmount: utils.formatUnits(BigNumber.from(2), 18), + token: { + address: IMX_ADDRESS_ZKEVM, + decimals: 18, + name: 'IMX', + symbol: 'IMX', + }, }, swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(3), + formattedAmount: utils.formatUnits(BigNumber.from(3), 18), + token: { + address: IMX_ADDRESS_ZKEVM, + decimals: 18, + name: 'IMX', + symbol: 'IMX', + }, }], }, }, @@ -426,19 +455,36 @@ describe('swapRoute', () => { address: '0xERC20_2', }, }, - // WT-1734 - Add fees fees: { approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(1), + formattedAmount: utils.formatUnits(BigNumber.from(1), 18), + token: { + address: IMX_ADDRESS_ZKEVM, + decimals: 18, + name: 'IMX', + symbol: 'IMX', + }, }, swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(2), + formattedAmount: utils.formatUnits(BigNumber.from(2), 18), + token: { + address: IMX_ADDRESS_ZKEVM, + decimals: 18, + name: 'IMX', + symbol: 'IMX', + }, }, swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(3), + formattedAmount: utils.formatUnits(BigNumber.from(3), 18), + token: { + address: IMX_ADDRESS_ZKEVM, + decimals: 18, + name: 'IMX', + symbol: 'IMX', + }, }], }, }, @@ -462,19 +508,36 @@ describe('swapRoute', () => { address: '0xERC20_3', }, }, - // WT-1734 - Add fees fees: { approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(1), + formattedAmount: utils.formatUnits(BigNumber.from(1), 18), + token: { + address: IMX_ADDRESS_ZKEVM, + decimals: 18, + name: 'IMX', + symbol: 'IMX', + }, }, swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(2), + formattedAmount: utils.formatUnits(BigNumber.from(2), 18), + token: { + address: IMX_ADDRESS_ZKEVM, + decimals: 18, + name: 'IMX', + symbol: 'IMX', + }, }, swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', + amount: BigNumber.from(3), + formattedAmount: utils.formatUnits(BigNumber.from(3), 18), + token: { + address: IMX_ADDRESS_ZKEVM, + decimals: 18, + name: 'IMX', + symbol: 'IMX', + }, }], }, }, @@ -1017,8 +1080,22 @@ describe('swapRoute', () => { address: IMX_ADDRESS_ZKEVM, }, }; + const fees = { + approvalGasFees: { + amount: BigNumber.from(1), + formattedAmount: '1', + }, + swapGasFees: { + amount: BigNumber.from(2), + formattedAmount: '2', + }, + swapFees: [{ + amount: BigNumber.from(3), + formattedAmount: '3', + }], + }; - const route = constructSwapRoute(chainId, fundsRequired, userBalance); + const route = constructSwapRoute(chainId, fundsRequired, userBalance, fees); expect(route).toEqual( { type: FundingStepType.SWAP, @@ -1040,21 +1117,7 @@ describe('swapRoute', () => { symbol: 'IMX', }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, + fees, }, ); }); @@ -1072,8 +1135,22 @@ describe('swapRoute', () => { address: '0xERC20', }, }; + const fees = { + approvalGasFees: { + amount: BigNumber.from(1), + formattedAmount: '1', + }, + swapGasFees: { + amount: BigNumber.from(2), + formattedAmount: '2', + }, + swapFees: [{ + amount: BigNumber.from(3), + formattedAmount: '3', + }], + }; - const route = constructSwapRoute(chainId, fundsRequired, userBalance); + const route = constructSwapRoute(chainId, fundsRequired, userBalance, fees); expect(route).toEqual( { type: FundingStepType.SWAP, @@ -1095,21 +1172,7 @@ describe('swapRoute', () => { symbol: 'ERC20', }, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, + fees, }, ); }); diff --git a/packages/checkout/sdk/src/smartCheckout/routing/swap/swapRoute.ts b/packages/checkout/sdk/src/smartCheckout/routing/swap/swapRoute.ts index 389492598d..bb72777a8a 100644 --- a/packages/checkout/sdk/src/smartCheckout/routing/swap/swapRoute.ts +++ b/packages/checkout/sdk/src/smartCheckout/routing/swap/swapRoute.ts @@ -8,16 +8,81 @@ import { GetBalanceResult, IMX_ADDRESS_ZKEVM, ItemType, + SwapFees, SwapFundingStep, + TokenInfo, } from '../../../types'; import { BalanceCheckResult, BalanceRequirement } from '../../balanceCheck/types'; import { DexQuoteCache, TokenBalanceResult } from '../types'; import { getOrSetQuotesFromCache } from './dexQuoteCache'; +const constructFees = ( + approvalGasFees: Amount | null | undefined, + swapGasFees: Amount | null, + swapFees: Fee[], +): SwapFees => { + let approvalGasFeeAmount = BigNumber.from(0); + let approvalGasFeeFormatted = '0'; + let approvalToken: TokenInfo | undefined; + if (approvalGasFees) { + approvalGasFeeAmount = approvalGasFees.value; + approvalGasFeeFormatted = utils.formatUnits(approvalGasFees.value, approvalGasFees.token.decimals); + approvalToken = { + name: approvalGasFees.token.name ?? '', + symbol: approvalGasFees.token.symbol ?? '', + address: approvalGasFees.token.address, + decimals: approvalGasFees.token.decimals, + }; + } + + let swapGasFeeAmount = BigNumber.from(0); + let swapGasFeeFormatted = '0'; + let swapGasToken: TokenInfo | undefined; + if (swapGasFees) { + swapGasFeeAmount = swapGasFees.value; + swapGasFeeFormatted = utils.formatUnits(swapGasFees.value, swapGasFees.token.decimals); + swapGasToken = { + name: swapGasFees.token.name ?? '', + symbol: swapGasFees.token.symbol ?? '', + address: swapGasFees.token.address, + decimals: swapGasFees.token.decimals, + }; + } + + const fees = []; + for (const swapFee of swapFees) { + fees.push({ + amount: swapFee.amount.value, + formattedAmount: utils.formatUnits(swapFee.amount.value, swapFee.amount.token.decimals), + token: { + name: swapFee.amount.token.name ?? '', + symbol: swapFee.amount.token.symbol ?? '', + address: swapFee.amount.token.address, + decimals: swapFee.amount.token.decimals, + }, + }); + } + + return { + approvalGasFees: { + amount: approvalGasFeeAmount, + formattedAmount: approvalGasFeeFormatted, + token: approvalToken, + }, + swapGasFees: { + amount: swapGasFeeAmount, + formattedAmount: swapGasFeeFormatted, + token: swapGasToken, + }, + swapFees: fees, + }; +}; + export const constructSwapRoute = ( chainId: ChainId, fundsRequired: BigNumber, userBalance: GetBalanceResult, + fees: SwapFees, ): SwapFundingStep => { const tokenAddress = userBalance.token.address; @@ -44,21 +109,7 @@ export const constructSwapRoute = ( }, token: userBalance.token, }, - // WT-1734 - Add fees - fees: { - approvalGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapGasFees: { - amount: BigNumber.from(0), - formattedAmount: '0', - }, - swapFees: [{ - amount: BigNumber.from(0), - formattedAmount: '0', - }], - }, + fees, }; }; @@ -286,6 +337,8 @@ export const swapRoute = async ( quote.quote.fees, )) continue; + const fees = constructFees(quote.approval, quote.swap, quote.quote.fees); + // User has sufficient funds of this token to cover any gas fees, swap fees and balance requirements // so add this token to the possible swap options fundingSteps.push( @@ -293,6 +346,7 @@ export const swapRoute = async ( chainId, amountOfQuoteTokenRequired.value, userBalanceOfQuotedToken, + fees, ), ); } diff --git a/packages/checkout/sdk/src/types/smartCheckout.ts b/packages/checkout/sdk/src/types/smartCheckout.ts index 1deaaeaa2c..24c3da169b 100644 --- a/packages/checkout/sdk/src/types/smartCheckout.ts +++ b/packages/checkout/sdk/src/types/smartCheckout.ts @@ -450,34 +450,22 @@ export type NoRouteOptions = { * Represents a funding route * @property {number} priority - The priority of the route * @property {FundingStep[]} steps - The steps associated with this funding route - * @property {TotalFees | undefined} totalFees - The total fees for this route */ export type FundingRoute = { priority: number; steps: FundingStep[] - totalFees?: TotalFees, -}; - -/** - * Represents the total fees for a route - * @property {Fee} gas - The total gas fees for this funding step - * @property {Fee} other - The total of all other fees associated with this funding step - * @property {Fee} total - The total combined gas and other fees for this funding step - */ -export type TotalFees = { - gas: Fee, - other: Fee, - total: Fee, }; /** * Represents a fee * @property {BigNumber} amount - The amount of the fee * @property {string} formatted - The formatted amount of the fee + * @property {TokenInfo | undefined} token - The token info for the fee */ export type Fee = { amount: BigNumber; formattedAmount: string; + token?: TokenInfo; }; /*