11import { SwapQuote } from '@0xsequence/api'
2- import { sendTransactions } from '@0xsequence/connect'
2+ import { getNativeTokenInfoByChainId , sendTransactions } from '@0xsequence/connect'
33import { compareAddress , useToast } from '@0xsequence/design-system'
44import { useAPIClient , useIndexerClient } from '@0xsequence/hooks'
55import { ReactNode , useEffect , useState } from 'react'
6- import { Hex , zeroAddress } from 'viem'
7- import { useAccount , useChainId , usePublicClient , useWalletClient } from 'wagmi'
6+ import { formatUnits , Hex , zeroAddress } from 'viem'
7+ import { useAccount , useChainId , useChains , usePublicClient , useWalletClient } from 'wagmi'
88
99import { SwapContextProvider } from '../../../contexts/Swap'
1010import { useNavigation } from '../../../hooks/useNavigation'
@@ -16,13 +16,12 @@ export const SwapProvider = ({ children }: { children: ReactNode }) => {
1616 const { setNavigation } = useNavigation ( )
1717 const apiClient = useAPIClient ( )
1818 const connectedChainId = useChainId ( )
19-
19+ const chains = useChains ( )
2020 const [ fromCoin , _setFromCoin ] = useState < TokenBalanceWithPrice > ( )
21- const [ fromAmount , setFromAmount ] = useState < number > ( 0 )
2221 const [ toCoin , _setToCoin ] = useState < TokenBalanceWithPrice > ( )
23- const [ toAmount , setToAmount ] = useState < number > ( 0 )
22+ const [ amount , _setAmount ] = useState < number > ( 0 )
23+ const [ nonRecentAmount , setNonRecentAmount ] = useState < number > ( 0 )
2424 const [ recentInput , setRecentInput ] = useState < 'from' | 'to' > ( 'from' )
25- const [ setNonRecentAmount , _setNonRecentAmount ] = useState < ( ) => void > ( ( ) => 0 )
2625
2726 const [ isSwapReady , setIsSwapReady ] = useState ( false )
2827 const [ swapQuoteData , setSwapQuoteData ] = useState < SwapQuote > ( )
@@ -39,10 +38,9 @@ export const SwapProvider = ({ children }: { children: ReactNode }) => {
3938
4039 const resetSwapStates = ( ) => {
4140 setFromCoin ( undefined )
42- setFromAmount ( 0 )
4341 setToCoin ( undefined )
44- setToAmount ( 0 )
45- setRecentInput ( 'from' )
42+ setAmount ( 0 , 'from' )
43+ setNonRecentAmount ( 0 )
4644 setIsSwapReady ( false )
4745 setSwapQuoteData ( undefined )
4846 setIsSwapQuotePending ( false )
@@ -55,23 +53,15 @@ export const SwapProvider = ({ children }: { children: ReactNode }) => {
5553 resetSwapStates ( )
5654 } , [ userAddress , connectedChainId ] )
5755
58- useEffect ( ( ) => {
59- if ( recentInput === 'from' ) {
60- _setNonRecentAmount ( ( ) => setFromAmount )
61- } else {
62- _setNonRecentAmount ( ( ) => setToAmount )
63- }
64- } , [ recentInput ] )
65-
6656 useEffect ( ( ) => {
6757 setIsSwapReady ( false )
6858 setSwapQuoteData ( undefined )
6959 setIsErrorSwapQuote ( false )
70- } , [ fromCoin , toCoin , fromAmount , toAmount ] )
60+ } , [ fromCoin , toCoin , amount ] )
7161
7262 useEffect ( ( ) => {
7363 const fetchSwapQuote = async ( ) => {
74- if ( ! fromCoin || ! toCoin || ( fromAmount === 0 && toAmount === 0 ) ) {
64+ if ( ! fromCoin || ! toCoin || amount === 0 ) {
7565 return
7666 }
7767
@@ -94,7 +84,7 @@ export const SwapProvider = ({ children }: { children: ReactNode }) => {
9484 userAddress : String ( userAddress ) ,
9585 buyCurrencyAddress : toCoin . contractAddress ,
9686 sellCurrencyAddress : fromCoin . contractAddress ,
97- buyAmount : String ( toAmount ) ,
87+ buyAmount : String ( amount ) ,
9888 chainId : connectedChainId ,
9989 includeApprove : true
10090 } )
@@ -103,11 +93,7 @@ export const SwapProvider = ({ children }: { children: ReactNode }) => {
10393
10494 // TODO: change this to "amount" from return
10595
106- if ( recentInput === 'from' ) {
107- setToAmount ( Number ( transactionValue ) )
108- } else {
109- setFromAmount ( Number ( transactionValue ) )
110- }
96+ setNonRecentAmount ( Number ( transactionValue ) )
11197
11298 setSwapQuoteData ( swapQuote ?. swapQuote )
11399 setIsSwapReady ( true )
@@ -120,7 +106,7 @@ export const SwapProvider = ({ children }: { children: ReactNode }) => {
120106 }
121107
122108 fetchSwapQuote ( )
123- } , [ fromCoin , toCoin , fromAmount , toAmount ] )
109+ } , [ fromCoin , toCoin , amount ] )
124110
125111 const setFromCoin = ( coin : TokenBalanceWithPrice | undefined ) => {
126112 if ( coin ?. chainId === toCoin ?. chainId && coin ?. contractAddress === toCoin ?. contractAddress ) {
@@ -138,20 +124,28 @@ export const SwapProvider = ({ children }: { children: ReactNode }) => {
138124 }
139125 }
140126
127+ const setAmount = ( newAmount : number , type : 'from' | 'to' ) => {
128+ if ( type === recentInput ) {
129+ _setAmount ( newAmount )
130+ } else {
131+ const tempAmount = amount
132+ setRecentInput ( recentInput === 'from' ? 'to' : 'from' )
133+ _setAmount ( newAmount )
134+ setNonRecentAmount ( tempAmount )
135+ }
136+ }
137+
141138 const switchCoinOrder = ( ) => {
142139 const tempFrom = fromCoin
143140 const tempTo = toCoin
144- const tempFromAmount = fromAmount
145- const tempToAmount = toAmount
146141 _setFromCoin ( tempTo )
147142 _setToCoin ( tempFrom )
148- setFromAmount ( tempToAmount )
149- setToAmount ( tempFromAmount )
143+ setRecentInput ( recentInput === 'from' ? 'to' : 'from' )
150144 }
151145
152146 const onSubmitSwap = async ( ) => {
153- if ( isErrorSwapQuote || ! userAddress || ! publicClient || ! walletClient || ! connector ) {
154- console . error ( 'Please ensure validation before submitting ' )
147+ if ( isErrorSwapQuote || ! userAddress || ! publicClient || ! walletClient || ! connector || ! fromCoin || ! toCoin || ! amount ) {
148+ console . error ( 'Please ensure validation before allowing users to submit a swap ' )
155149 return
156150 }
157151
@@ -197,6 +191,21 @@ export const SwapProvider = ({ children }: { children: ReactNode }) => {
197191 await walletClient . switchChain ( { id : connectedChainId } )
198192 }
199193
194+ const isFromCoinNative = fromCoin . contractType === 'NATIVE'
195+ const isToCoinNative = toCoin . contractType === 'NATIVE'
196+ const fromCoinNativeInfo = getNativeTokenInfoByChainId ( fromCoin . chainId , chains )
197+ const toCoinNativeInfo = getNativeTokenInfoByChainId ( toCoin . chainId , chains )
198+ const toastFromCoinName = isFromCoinNative ? fromCoinNativeInfo . symbol : fromCoin . contractInfo ?. symbol
199+ const toastToCoinName = isToCoinNative ? toCoinNativeInfo . symbol : toCoin . contractInfo ?. symbol
200+ const toastFromAmount = formatUnits (
201+ BigInt ( recentInput === 'from' ? amount : nonRecentAmount ) ,
202+ ( isFromCoinNative ? fromCoinNativeInfo . decimals : fromCoin . contractInfo ?. decimals ) || 18
203+ )
204+ const toastToAmount = formatUnits (
205+ BigInt ( recentInput === 'from' ? nonRecentAmount : amount ) ,
206+ ( isToCoinNative ? toCoinNativeInfo . decimals : toCoin . contractInfo ?. decimals ) || 18
207+ )
208+
200209 await sendTransactions ( {
201210 connector,
202211 walletClient,
@@ -209,7 +218,7 @@ export const SwapProvider = ({ children }: { children: ReactNode }) => {
209218
210219 toast ( {
211220 title : 'Transaction sent' ,
212- description : `Successfully swapped ${ fromAmount } ${ fromCoin ?. contractInfo ?. name } for ${ toAmount } ${ toCoin ?. contractInfo ?. name } ` ,
221+ description : `Successfully swapped ${ toastFromAmount } ${ toastFromCoinName } for ${ toastToAmount } ${ toastToCoinName } ` ,
213222 variant : 'success'
214223 } )
215224
@@ -228,9 +237,9 @@ export const SwapProvider = ({ children }: { children: ReactNode }) => {
228237 < SwapContextProvider
229238 value = { {
230239 fromCoin,
231- fromAmount,
232240 toCoin,
233- toAmount,
241+ amount,
242+ nonRecentAmount,
234243 recentInput,
235244 isSwapReady,
236245 isSwapQuotePending,
@@ -239,11 +248,8 @@ export const SwapProvider = ({ children }: { children: ReactNode }) => {
239248 isTxnPending,
240249 isErrorTxn,
241250 setFromCoin,
242- setFromAmount,
243251 setToCoin,
244- setToAmount,
245- setRecentInput,
246- setNonRecentAmount,
252+ setAmount,
247253 switchCoinOrder,
248254 onSubmitSwap,
249255 resetSwapStates
0 commit comments