1- import { normalize } from '@aave/math-utils' ;
2- import { getOrderToSign , LimitTradeParameters , OrderKind , TradingSdk } from '@cowprotocol/cow-sdk' ;
3- import { AaveCollateralSwapSdk , HASH_ZERO } from '@cowprotocol/sdk-flash-loans' ;
1+ import { normalize , normalizeBN } from '@aave/math-utils' ;
2+ import { getOrderToSign , LimitTradeParameters , OrderKind } from '@cowprotocol/cow-sdk' ;
3+ import { AaveFlashLoanType , HASH_ZERO } from '@cowprotocol/sdk-flash-loans' ;
44import { Trans } from '@lingui/macro' ;
5- import { Dispatch , useEffect , useState } from 'react' ;
5+ import { Dispatch , useEffect , useMemo , useState } from 'react' ;
66import { TxActionsWrapper } from 'src/components/transactions/TxActionsWrapper' ;
7+ import { calculateSignedAmount } from 'src/hooks/paraswap/common' ;
78import { useModalContext } from 'src/hooks/useModal' ;
89import { useRootStore } from 'src/store/root' ;
910import { getErrorTextFromError , TxAction } from 'src/ui-config/errorMapping' ;
1011import { useShallow } from 'zustand/react/shallow' ;
1112
1213import { TrackAnalyticsHandlers } from '../../analytics/useTrackAnalytics' ;
13- import { COW_PARTNER_FEE , FLASH_LOAN_FEE_BPS } from '../../constants/cow.constants' ;
14+ import { FLASH_LOAN_FEE_BPS } from '../../constants/cow.constants' ;
1415import { APP_CODE_PER_SWAP_TYPE } from '../../constants/shared.constants' ;
15- import { getCowAdapter } from '../../helpers/cow' ;
16- import { calculateInstanceAddress } from '../../helpers/cow/adapters.helpers' ;
16+ import { getCowFlashLoanSdk , getCowTradingSdkByChainIdAndAppCode } from '../../helpers/cow' ;
17+ import { calculateInstanceAddress , OrderCore } from '../../helpers/cow/adapters.helpers' ;
1718import { useSwapGasEstimation } from '../../hooks/useSwapGasEstimation' ;
18- import { OrderType , SwapParams , SwapState } from '../../types' ;
19+ import { ExpiryToSecondsMap , OrderType , SwapParams , SwapState } from '../../types' ;
1920import { useSwapTokenApproval } from '../approval/useSwapTokenApproval' ;
2021
22+ export const getCollateralSwapOrderCore = ( state : SwapState ) : OrderCore => {
23+ // In limit orders, slippage is zero.
24+ let slippageInPercentage = state . orderType === OrderType . LIMIT ? 0 : Number ( state . slippage ) / 100 ;
25+
26+ const sellToken = state . sourceToken ;
27+ const buyToken = state . destinationToken ;
28+ const side = state . side ;
29+
30+ // If side is sell, we allow less buy amount to ensure sell amount
31+ // If side is buy, we allow more sell amount to ensure buy amount
32+ const sellAmount =
33+ side === 'sell'
34+ ? normalizeBN ( state . inputAmount , - sellToken . decimals )
35+ : normalizeBN ( state . inputAmount , - sellToken . decimals )
36+ . multipliedBy ( 1 + slippageInPercentage )
37+ . decimalPlaces ( 0 ) ;
38+ const buyAmount =
39+ side === 'sell'
40+ ? normalizeBN ( state . outputAmount , - buyToken . decimals )
41+ . dividedBy ( 1 + slippageInPercentage )
42+ . decimalPlaces ( 0 )
43+ : normalizeBN ( state . outputAmount , - buyToken . decimals ) . decimalPlaces ( 0 ) ;
44+
45+ // TODO: REQUIRES FIX IN COW SDK
46+ // slippageBps = slippageInPercentage * 10000
47+ // const partnerFee = COW_PARTNER_FEE(state.sourceToken.symbol, state.destinationToken.symbol);
48+
49+ const partnerFee = {
50+ volumeBps : 0 ,
51+ recipient : '0x0000000000000000000000000000000000000000' ,
52+ } ;
53+ const slippageBps = 0 ;
54+
55+ return {
56+ chainId : state . chainId ,
57+ sellAmount,
58+ buyAmount,
59+ sellToken,
60+ buyToken,
61+ side,
62+ slippageBps,
63+ partnerFee,
64+ } ;
65+ } ;
66+
2167export const CollateralSwapActionsViaCowAdapters = ( {
2268 params,
2369 state,
@@ -37,15 +83,36 @@ export const CollateralSwapActionsViaCowAdapters = ({
3783 const [ precalculatedInstanceAddress , setPrecalculatedInstanceAddress ] = useState <
3884 string | undefined
3985 > ( ) ;
40- const validTo = state . expiry || Math . floor ( Date . now ( ) / 1000 ) + 10 * 60 ; // 10 minutes
4186
42- const slippageBps =
43- state . orderType === OrderType . LIMIT ? 0 : Math . round ( Number ( state . slippage ) * 100 ) ; // percent to bps
87+ const validTo = useMemo (
88+ ( ) => Math . floor ( Date . now ( ) / 1000 ) + ExpiryToSecondsMap [ state . expiry ] ,
89+ [ state . expiry ]
90+ ) ;
91+
92+ const orderCore = useMemo (
93+ ( ) => getCollateralSwapOrderCore ( state ) ,
94+ [
95+ state . inputAmount ,
96+ state . outputAmount ,
97+ state . sourceToken ,
98+ state . destinationToken ,
99+ state . side ,
100+ state . slippage ,
101+ state . orderType ,
102+ state . chainId ,
103+ ]
104+ ) ;
105+ console . log ( 'validTo' , validTo , state . expiry ) ;
44106
45107 // Pre-compute instance address
46108 useEffect ( ( ) => {
47109 if ( state . chainId !== 100 ) return ; // TODO: remove this once we have a supported chainId
48- calculateInstanceAddress ( state , user , validTo )
110+ calculateInstanceAddress ( {
111+ user,
112+ validTo,
113+ type : AaveFlashLoanType . CollateralSwap ,
114+ orderCore,
115+ } )
49116 . catch ( ( error ) => {
50117 console . error ( 'calculateInstanceAddress error' , error ) ;
51118 setTxError ( getErrorTextFromError ( error , TxAction . MAIN_ACTION , true ) ) ;
@@ -58,24 +125,23 @@ export const CollateralSwapActionsViaCowAdapters = ({
58125 . then ( ( address ) => {
59126 if ( address ) setPrecalculatedInstanceAddress ( address ) ;
60127 } ) ;
61- } , [
62- user ,
63- state . inputAmount ,
64- state . minimumReceived ,
65- state . destinationToken . underlyingAddress ,
66- state . sourceToken . symbol ,
67- state . destinationToken . symbol ,
68- state . slippage ,
69- state . autoSlippage ,
70- APP_CODE_PER_SWAP_TYPE [ state . swapType ] ,
71- ] ) ;
128+ } , [ user , validTo , orderCore , state . chainId ] ) ;
72129
73130 // Approval is aToken ERC20 Approval
131+ const amountToApprove = useMemo (
132+ ( ) =>
133+ calculateSignedAmount (
134+ normalizeBN ( orderCore . sellAmount . toString ( ) , orderCore . sellToken . decimals ) . toString ( ) ,
135+ orderCore . sellToken . decimals
136+ ) ,
137+ [ orderCore . sellAmount , orderCore . sellToken . decimals ]
138+ ) ;
139+
74140 const { requiresApproval, approval, tryPermit, signatureParams } = useSwapTokenApproval ( {
75141 chainId : state . chainId ,
76142 token : state . sourceToken . addressToSwap ,
77143 symbol : state . sourceToken . symbol ,
78- amount : state . inputAmount ,
144+ amount : normalize ( amountToApprove . toString ( ) , orderCore . sellToken . decimals ) ,
79145 decimals : state . sourceToken . decimals ,
80146 spender : precalculatedInstanceAddress ,
81147 setState,
@@ -101,23 +167,13 @@ export const CollateralSwapActionsViaCowAdapters = ({
101167 } ) ;
102168
103169 try {
104- if ( ! state . minimumReceived ) return ;
105-
106- const sellAmount = normalize ( state . inputAmount , - state . sourceToken . decimals ) ;
107- const buyAmount = normalize ( state . minimumReceived , - state . destinationToken . decimals ) ;
108-
109- const adapter = await getCowAdapter ( state . chainId ) ;
110- const tradingSdk = new TradingSdk (
111- {
112- chainId : state . chainId ,
113- appCode : APP_CODE_PER_SWAP_TYPE [ state . swapType ] ,
114- env : 'staging' ,
115- signer : adapter . signer ,
116- } ,
117- { } ,
118- adapter
170+ const tradingSdk = await getCowTradingSdkByChainIdAndAppCode (
171+ orderCore . chainId ,
172+ APP_CODE_PER_SWAP_TYPE [ state . swapType ] ,
173+ 'staging'
119174 ) ;
120- const flashLoanSdk = new AaveCollateralSwapSdk ( ) ;
175+ const flashLoanSdk = await getCowFlashLoanSdk ( orderCore . chainId ) ;
176+
121177 const collateralPermit = signatureParams
122178 ? {
123179 amount : signatureParams ?. amount ,
@@ -128,42 +184,41 @@ export const CollateralSwapActionsViaCowAdapters = ({
128184 }
129185 : undefined ;
130186
131- const partnerFee = COW_PARTNER_FEE ( state . sourceToken . symbol , state . destinationToken . symbol ) ;
132-
133187 const { flashLoanFeeAmount, sellAmountToSign } = flashLoanSdk . calculateFlashLoanAmounts ( {
134188 flashLoanFeePercent : FLASH_LOAN_FEE_BPS / 100 ,
135- sellAmount : BigInt ( sellAmount ) ,
189+ sellAmount : BigInt ( orderCore . sellAmount . toString ( ) ) ,
136190 } ) ;
137191
138192 const limitOrder : LimitTradeParameters = {
139- sellToken : state . sourceToken . underlyingAddress ,
140- sellTokenDecimals : state . sourceToken . decimals ,
141- buyToken : state . destinationToken . underlyingAddress ,
142- buyTokenDecimals : state . destinationToken . decimals ,
193+ sellToken : orderCore . sellToken . underlyingAddress ,
194+ sellTokenDecimals : orderCore . sellToken . decimals ,
195+ buyToken : orderCore . buyToken . underlyingAddress ,
196+ buyTokenDecimals : orderCore . buyToken . decimals ,
143197 sellAmount : sellAmountToSign . toString ( ) ,
144- buyAmount : buyAmount . toString ( ) ,
145- kind : state . side === 'buy' ? OrderKind . BUY : OrderKind . SELL ,
198+ buyAmount : orderCore . buyAmount . toString ( ) ,
199+ kind : orderCore . side === 'buy' ? OrderKind . BUY : OrderKind . SELL ,
146200 validTo,
147- slippageBps,
148- partnerFee,
201+ slippageBps : orderCore . slippageBps ,
202+ partnerFee : orderCore . partnerFee ,
149203 } ;
150204
151205 const orderToSign = getOrderToSign (
152- { chainId : state . chainId , from : user , networkCostsAmount : '0' , isEthFlow : false } ,
206+ { chainId : orderCore . chainId , from : user , networkCostsAmount : '0' , isEthFlow : false } ,
153207 limitOrder ,
154208 HASH_ZERO
155209 ) ;
156210
157211 const orderPostParams = await flashLoanSdk . getOrderPostingSettings (
212+ AaveFlashLoanType . CollateralSwap ,
158213 {
159- chainId : state . chainId ,
214+ chainId : orderCore . chainId ,
160215 validTo,
161216 owner : user as `0x${string } `,
162- flashLoanFeeAmount,
217+ flashLoanFeeAmount : flashLoanFeeAmount + BigInt ( 1 ) , // Fix for flashloanfee rounding error
163218 } ,
164219 {
165- sellAmount : BigInt ( sellAmount ) ,
166- buyAmount : BigInt ( buyAmount ) ,
220+ sellAmount : BigInt ( orderCore . sellAmount . toString ( ) ) ,
221+ buyAmount : BigInt ( orderCore . buyAmount . toString ( ) ) ,
167222 orderToSign,
168223 collateralPermit,
169224 }
0 commit comments