import { BigNumber } from '@ethersproject/bignumber' ; import { Provider } from '@ethersproject/providers' ; import { AddressZero , WeiPerEther as ONE } from '@ethersproject/constants' ; import { Lido , getStEthRate } from './pools/lido' ; import { SwapTypes , SwapInfo , SorConfig } from './types' ; import { TokensToUnbuttonWrapperMap , getWrapperRate as getUnbuttonWrapperRate , } from './wrappers/unbutton' ; import { isSameAddress } from './utils' ; export interface WrappedInfo { swapAmountOriginal : BigNumber ; swapAmountForSwaps : BigNumber ; tokenIn : TokenInfo ; tokenOut : TokenInfo ; } export interface TokenInfo { addressOriginal : string ; addressForSwaps : string ; wrapType : WrapTypes ; rate : BigNumber ; } export enum WrapTypes { None , ETH , stETH , Unbutton } export async function getWrappedInfo ( provider , swapType , tokenIn , tokenOut , config , swapAmount ) { tokenIn = tokenIn . toLowerCase ( ) ; tokenOut = tokenOut . toLowerCase ( ) ; let swapAmountForSwaps = swapAmount ; let tokenInForSwaps = tokenIn ; let tokenInWrapType = WrapTypes . None ; let tokenOutForSwaps = tokenOut ; let tokenOutWrapType = WrapTypes . None ; let tokenInRate = ONE ; let tokenOutRate = ONE ; if ( tokenIn === AddressZero ) { tokenInForSwaps = config . weth . toLowerCase ( ) ; tokenInWrapType = WrapTypes . ETH ; } if ( tokenOut === AddressZero ) { tokenOutForSwaps = config . weth . toLowerCase ( ) ; tokenOutWrapType = WrapTypes . ETH ; } if ( tokenIn === Lido . stETH [ config . chainId ] ) { tokenInForSwaps = Lido . wstETH [ config . chainId ] ; tokenInWrapType = WrapTypes . stETH ; const rate = await getStEthRate ( provider , config . chainId ) ; tokenInRate = rate ; if ( swapType === SwapTypes . SwapExactIn ) swapAmountForSwaps = swapAmount . mul ( rate ) . div ( ONE ) ; } if ( tokenOut === Lido . stETH [ config . chainId ] ) { tokenOutForSwaps = Lido . wstETH [ config . chainId ] ; tokenOutWrapType = WrapTypes . stETH ; const rate = await getStEthRate ( provider , config . chainId ) ; tokenOutRate = rate ; if ( swapType === SwapTypes . SwapExactOut ) swapAmountForSwaps = swapAmount . mul ( rate ) . div ( ONE ) ; } const tokensToUBWrapperMap = TokensToUnbuttonWrapperMap [ config . chainId ] || { } ; if ( tokensToUBWrapperMap [ tokenIn ] ) { tokenInForSwaps = tokensToUBWrapperMap [ tokenIn ] ; tokenInWrapType = WrapTypes . Unbutton ; tokenInRate = await getUnbuttonWrapperRate ( provider , tokenInForSwaps ) ; if ( swapType === SwapTypes . SwapExactIn ) swapAmountForSwaps = swapAmount . mul ( tokenInRate ) . div ( ONE ) ; } if ( tokensToUBWrapperMap [ tokenOut ] ) { tokenOutForSwaps = tokensToUBWrapperMap [ tokenOut ] ; tokenOutWrapType = WrapTypes . Unbutton ; tokenOutRate = await getUnbuttonWrapperRate ( provider , tokenOutForSwaps ) ; if ( swapType === SwapTypes . SwapExactOut ) swapAmountForSwaps = swapAmount . mul ( tokenOutRate ) . div ( ONE ) ; } return { swapAmountOriginal : swapAmount , swapAmountForSwaps : swapAmountForSwaps , tokenIn : { addressOriginal : tokenIn , addressForSwaps : tokenInForSwaps , wrapType : tokenInWrapType , rate : tokenInRate , } , tokenOut : { addressOriginal : tokenOut , addressForSwaps : tokenOutForSwaps , wrapType : tokenOutWrapType , rate : tokenOutRate , } , } ; } export function setWrappedInfo ( swapInfo , swapType , wrappedInfo , config ) { if ( swapInfo . swaps . length === 0 ) return swapInfo ; swapInfo . tokenIn = wrappedInfo . tokenIn . addressOriginal ; swapInfo . tokenOut = wrappedInfo . tokenOut . addressOriginal ; swapInfo . swapAmountForSwaps = swapInfo . swapAmount ; swapInfo . returnAmountFromSwaps = swapInfo . returnAmount ; if ( wrappedInfo . tokenIn . wrapType === WrapTypes . None && wrappedInfo . tokenOut . wrapType === WrapTypes . None ) { return swapInfo ; } if ( wrappedInfo . tokenIn . wrapType === WrapTypes . ETH || wrappedInfo . tokenOut . wrapType === WrapTypes . ETH ) { swapInfo . tokenAddresses = swapInfo . tokenAddresses . map ( ( addr ) => isSameAddress ( addr , config . weth ) ? AddressZero : addr ) ; } const isScaledWrapper = ( wrapType ) => wrapType === WrapTypes . stETH || wrapType === WrapTypes . Unbutton ; if ( ( isScaledWrapper ( wrappedInfo . tokenIn . wrapType ) && swapType === SwapTypes . SwapExactIn ) || ( isScaledWrapper ( wrappedInfo . tokenOut . wrapType ) && swapType === SwapTypes . SwapExactOut ) ) { swapInfo . swapAmount = wrappedInfo . swapAmountOriginal ; swapInfo . swapAmountForSwaps = wrappedInfo . swapAmountForSwaps ; } if ( swapType === SwapTypes . SwapExactIn && isScaledWrapper ( wrappedInfo . tokenOut . wrapType ) ) { swapInfo . returnAmount = swapInfo . returnAmount . mul ( ONE ) . div ( wrappedInfo . tokenOut . rate ) ; swapInfo . returnAmountConsideringFees = swapInfo . returnAmountConsideringFees . mul ( ONE ) . div ( wrappedInfo . tokenOut . rate ) ; } if ( swapType === SwapTypes . SwapExactOut && isScaledWrapper ( wrappedInfo . tokenIn . wrapType ) ) { swapInfo . returnAmount = swapInfo . returnAmount . mul ( ONE ) . div ( wrappedInfo . tokenIn . rate ) ; swapInfo . returnAmountConsideringFees = swapInfo . returnAmountConsideringFees . mul ( ONE ) . div ( wrappedInfo . tokenIn . rate ) ; } return swapInfo ; }