2022-08-17 13:06:25 -07:00
import React , {
Dispatch ,
SetStateAction ,
useEffect ,
useMemo ,
useState ,
} from 'react'
import { TransactionInstruction , PublicKey } from '@solana/web3.js'
import Decimal from 'decimal.js'
2022-09-12 08:53:57 -07:00
import mangoStore from '@store/mangoStore'
2022-08-17 13:06:25 -07:00
import RoutesModal from './RoutesModal'
import Button , { IconButton } from '../shared/Button'
import Loading from '../shared/Loading'
import {
ArrowLeftIcon ,
PencilIcon ,
2022-09-06 21:36:35 -07:00
ArrowsRightLeftIcon ,
2022-09-07 17:47:59 -07:00
CheckCircleIcon ,
2022-09-16 04:37:24 -07:00
ArrowRightIcon ,
2022-09-06 21:36:35 -07:00
} from '@heroicons/react/20/solid'
2022-08-17 13:06:25 -07:00
import { useTranslation } from 'next-i18next'
2022-10-28 14:46:38 -07:00
import Image from 'next/legacy/image'
2022-08-25 14:24:10 -07:00
import {
floorToDecimal ,
formatDecimal ,
formatFixedDecimals ,
} from '../../utils/numbers'
2022-08-19 21:03:26 -07:00
import { notify } from '../../utils/notifications'
2022-11-18 11:11:06 -08:00
import useJupiterMints from '../../hooks/useJupiterMints'
2022-11-18 20:59:06 -08:00
import { RouteInfo } from 'types/jupiter'
2022-11-18 11:11:06 -08:00
import useJupiterSwapData from './useJupiterSwapData'
2022-11-18 20:59:06 -08:00
import { Transaction } from '@solana/web3.js'
2022-08-17 13:06:25 -07:00
type JupiterRouteInfoProps = {
2022-08-17 18:26:38 -07:00
amountIn : Decimal
2022-08-18 13:50:34 -07:00
onClose : ( ) = > void
routes : RouteInfo [ ] | undefined
2022-08-17 13:06:25 -07:00
selectedRoute : RouteInfo | undefined
setSelectedRoute : Dispatch < SetStateAction < RouteInfo | undefined > >
2022-08-18 13:50:34 -07:00
slippage : number
2022-08-17 13:06:25 -07:00
}
const parseJupiterRoute = async (
selectedRoute : RouteInfo ,
2022-11-18 20:59:06 -08:00
userPublicKey : PublicKey ,
slippage : number
2022-08-17 13:06:25 -07:00
) : Promise < TransactionInstruction [ ] > = > {
2022-11-18 11:11:06 -08:00
const transactions = await (
await fetch ( 'https://quote-api.jup.ag/v3/swap' , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
} ,
body : JSON.stringify ( {
// route from /quote api
route : selectedRoute ,
// user public key to be used for the swap
userPublicKey ,
// auto wrap and unwrap SOL. default is true
wrapUnwrapSOL : true ,
// feeAccount is optional. Use if you want to charge a fee. feeBps must have been passed in /quote API.
// This is the ATA account for the output token where the fee will be sent to. If you are swapping from SOL->USDC then this would be the USDC ATA you want to collect the fee.
2022-11-18 20:59:06 -08:00
// feeAccount: 'fee_account_public_key',
slippageBps : Math.ceil ( slippage * 100 ) ,
2022-11-18 11:11:06 -08:00
} ) ,
} )
) . json ( )
2022-11-18 20:59:06 -08:00
2022-08-17 13:06:25 -07:00
const { swapTransaction } = transactions
2022-11-18 20:59:06 -08:00
const parsedSwapTransaction = Transaction . from (
Buffer . from ( swapTransaction , 'base64' )
)
2022-08-17 13:06:25 -07:00
const instructions = [ ]
2022-11-18 20:59:06 -08:00
for ( const ix of parsedSwapTransaction . instructions ) {
2022-08-17 13:06:25 -07:00
if (
2022-11-18 20:59:06 -08:00
ix . programId . toBase58 ( ) === 'JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB'
2022-08-17 13:06:25 -07:00
) {
instructions . push ( ix )
}
}
return instructions
}
2022-08-25 13:24:37 -07:00
const EMPTY_COINGECKO_PRICES = {
inputCoingeckoPrice : 0 ,
outputCoingeckoPrice : 0 ,
}
2022-08-17 13:06:25 -07:00
const JupiterRouteInfo = ( {
amountIn ,
onClose ,
routes ,
selectedRoute ,
setSelectedRoute ,
} : JupiterRouteInfoProps ) = > {
2022-08-26 10:17:31 -07:00
const { t } = useTranslation ( [ 'common' , 'trade' ] )
2022-08-17 13:06:25 -07:00
const [ showRoutesModal , setShowRoutesModal ] = useState ( false )
const [ swapRate , setSwapRate ] = useState < boolean > ( false )
2022-11-19 11:20:36 -08:00
const [ feeValue ] = useState < number | null > ( null )
2022-08-19 21:03:26 -07:00
const [ submitting , setSubmitting ] = useState ( false )
2022-08-25 13:24:37 -07:00
const [ coingeckoPrices , setCoingeckoPrices ] = useState ( EMPTY_COINGECKO_PRICES )
2022-11-18 11:11:06 -08:00
const { mangoTokens } = useJupiterMints ( )
const { inputTokenInfo , outputTokenInfo } = useJupiterSwapData ( )
2022-09-05 15:38:47 -07:00
const inputBank = mangoStore ( ( s ) = > s . swap . inputBank )
2022-08-17 13:06:25 -07:00
const inputTokenIconUri = useMemo ( ( ) = > {
2022-08-18 13:50:34 -07:00
return inputTokenInfo ? inputTokenInfo . logoURI : ''
} , [ inputTokenInfo ] )
2022-08-17 13:06:25 -07:00
const amountOut = useMemo ( ( ) = > {
if ( ! selectedRoute || ! outputTokenInfo ) return
2022-09-02 16:52:07 -07:00
return new Decimal ( selectedRoute . outAmount . toString ( ) ) . div (
10 * * outputTokenInfo . decimals
2022-08-17 13:06:25 -07:00
)
} , [ selectedRoute , outputTokenInfo ] )
2022-08-25 13:24:37 -07:00
useEffect ( ( ) = > {
setCoingeckoPrices ( EMPTY_COINGECKO_PRICES )
const fetchTokenPrices = async ( ) = > {
const inputId = inputTokenInfo ? . extensions ? . coingeckoId
const outputId = outputTokenInfo ? . extensions ? . coingeckoId
if ( inputId && outputId ) {
const results = await fetch (
` https://api.coingecko.com/api/v3/simple/price?ids= ${ inputId } , ${ outputId } &vs_currencies=usd `
)
const json = await results . json ( )
if ( json [ inputId ] ? . usd && json [ outputId ] ? . usd ) {
setCoingeckoPrices ( {
inputCoingeckoPrice : json [ inputId ] . usd ,
outputCoingeckoPrice : json [ outputId ] . usd ,
} )
}
}
}
if ( inputTokenInfo && outputTokenInfo ) {
fetchTokenPrices ( )
}
} , [ inputTokenInfo , outputTokenInfo ] )
2022-08-17 13:06:25 -07:00
const onSwap = async ( ) = > {
2022-11-18 11:11:06 -08:00
if ( ! selectedRoute ) return
2022-08-19 21:03:26 -07:00
try {
const client = mangoStore . getState ( ) . client
const group = mangoStore . getState ( ) . group
const actions = mangoStore . getState ( ) . actions
const mangoAccount = mangoStore . getState ( ) . mangoAccount . current
const inputBank = mangoStore . getState ( ) . swap . inputBank
const outputBank = mangoStore . getState ( ) . swap . outputBank
2022-11-18 20:59:06 -08:00
const slippage = mangoStore . getState ( ) . swap . slippage
2022-11-21 19:23:54 -08:00
const set = mangoStore . getState ( ) . set
2022-08-19 21:03:26 -07:00
if ( ! mangoAccount || ! group || ! inputBank || ! outputBank ) return
2022-11-18 20:59:06 -08:00
const ixs = await parseJupiterRoute (
selectedRoute ,
2022-11-19 11:20:36 -08:00
mangoAccount . owner ,
2022-11-18 20:59:06 -08:00
slippage
)
2022-08-19 21:03:26 -07:00
try {
setSubmitting ( true )
const tx = await client . marginTrade ( {
group ,
mangoAccount ,
inputMintPk : inputBank.mint ,
amountIn : amountIn.toNumber ( ) ,
outputMintPk : outputBank.mint ,
userDefinedInstructions : ixs ,
flashLoanType : { swap : { } } ,
} )
2022-11-21 19:23:54 -08:00
set ( ( s ) = > {
s . swap . success = true
} )
2022-08-19 21:03:26 -07:00
notify ( {
title : 'Transaction confirmed' ,
type : 'success' ,
txid : tx ,
} )
2022-09-02 16:51:35 -07:00
actions . fetchGroup ( )
2022-08-25 20:30:39 -07:00
await actions . reloadMangoAccount ( )
2022-08-19 21:03:26 -07:00
} catch ( e : any ) {
2022-08-20 17:09:36 -07:00
console . error ( 'onSwap error: ' , e )
2022-08-19 21:03:26 -07:00
notify ( {
title : 'Transaction failed' ,
description : e.message ,
txid : e?.signature ,
type : 'error' ,
} )
} finally {
setSubmitting ( false )
}
} catch ( e ) {
console . error ( 'Swap error:' , e )
} finally {
onClose ( )
}
2022-08-17 13:06:25 -07:00
}
2022-08-25 13:24:37 -07:00
const borrowAmount = useMemo ( ( ) = > {
const mangoAccount = mangoStore . getState ( ) . mangoAccount . current
const inputBank = mangoStore . getState ( ) . swap . inputBank
if ( ! mangoAccount || ! inputBank ) return 0
const remainingBalance =
mangoAccount . getTokenDepositsUi ( inputBank ) - amountIn . toNumber ( )
2022-11-18 11:11:06 -08:00
const x = remainingBalance < 0 ? Math . abs ( remainingBalance ) : 0
console . log ( 'borrowAmount' , x )
return x
2022-08-25 13:24:37 -07:00
} , [ amountIn ] )
const coinGeckoPriceDifference = useMemo ( ( ) = > {
return amountOut
2022-08-25 14:24:10 -07:00
? floorToDecimal (
2022-09-02 11:36:57 -07:00
amountIn
. div ( amountOut )
. minus (
new Decimal ( coingeckoPrices ? . outputCoingeckoPrice ) . div (
coingeckoPrices ? . inputCoingeckoPrice
)
)
. div ( amountIn . div ( amountOut ) ) ,
2022-08-25 14:24:10 -07:00
1
)
2022-09-02 11:36:57 -07:00
: new Decimal ( 0 )
2022-08-25 13:24:37 -07:00
} , [ coingeckoPrices , amountIn , amountOut ] )
2022-11-18 11:11:06 -08:00
console . log ( 'selectedRoute' , selectedRoute )
2022-08-17 13:06:25 -07:00
return routes ? . length && selectedRoute && outputTokenInfo && amountOut ? (
< div className = "flex h-full flex-col justify-between" >
< div >
< IconButton
2022-09-14 19:41:55 -07:00
className = "absolute mr-3 text-th-fgd-2"
2022-08-17 13:06:25 -07:00
onClick = { onClose }
size = "small"
>
< ArrowLeftIcon className = "h-5 w-5" / >
< / IconButton >
2022-08-25 06:00:42 -07:00
< div className = "mb-6 mt-4 flex justify-center" >
2022-08-17 13:06:25 -07:00
< div className = "flex flex-col items-center" >
< div className = "relative mb-2 w-[72px]" >
< Image alt = "" width = "40" height = "40" src = { inputTokenIconUri } / >
< div className = "absolute right-0 top-0" >
< Image
className = "drop-shadow-md"
alt = ""
width = "40"
height = "40"
src = { outputTokenInfo . logoURI }
/ >
< / div >
< / div >
2022-09-16 04:37:24 -07:00
< p className = "mb-0.5 flex items-center text-center text-lg" >
2022-09-22 03:46:51 -07:00
< span className = "mr-1 font-mono text-th-fgd-1" > { ` ${ formatFixedDecimals (
2022-09-05 15:38:47 -07:00
amountIn . toNumber ( )
) } ` }</span>{' '}
2022-09-16 04:37:24 -07:00
{ inputTokenInfo ! . symbol }
< ArrowRightIcon className = "mx-2 h-5 w-5 text-th-fgd-4" / >
2022-09-22 03:46:51 -07:00
< span className = "mr-1 font-mono text-th-fgd-1" > { ` ${ formatFixedDecimals (
2022-09-05 15:38:47 -07:00
amountOut . toNumber ( )
) } ` }</span>{' '}
{ ` ${ outputTokenInfo . symbol } ` }
< / p >
2022-08-17 13:06:25 -07:00
< / div >
< / div >
< div className = "space-y-2 px-1" >
2022-08-25 13:24:37 -07:00
< div className = "flex justify-between" >
2022-09-14 18:06:00 -07:00
< p className = "text-sm text-th-fgd-3" > { t ( 'swap:rate' ) } < / p >
2022-08-25 13:24:37 -07:00
< div >
< div className = "flex items-center justify-end" >
2022-09-22 03:46:51 -07:00
< p className = "text-right font-mono text-sm text-th-fgd-1" >
2022-08-25 13:24:37 -07:00
{ swapRate ? (
< >
2022-09-16 04:37:24 -07:00
1 { ' ' }
< span className = "font-body tracking-wide" >
{ inputTokenInfo ! . name } ≈ { ' ' }
< / span >
2022-09-05 15:38:47 -07:00
{ formatFixedDecimals ( amountOut . div ( amountIn ) . toNumber ( ) ) } { ' ' }
2022-09-16 04:37:24 -07:00
< span className = "font-body tracking-wide" >
{ outputTokenInfo ? . symbol }
< / span >
2022-08-25 13:24:37 -07:00
< / >
) : (
< >
2022-09-16 04:37:24 -07:00
1 { ' ' }
< span className = "font-body tracking-wide" >
{ outputTokenInfo ? . symbol } ≈ { ' ' }
< / span >
2022-09-05 15:38:47 -07:00
{ formatFixedDecimals ( amountIn . div ( amountOut ) . toNumber ( ) ) } { ' ' }
2022-09-16 04:37:24 -07:00
< span className = "font-body tracking-wide" >
{ inputTokenInfo ! . symbol }
< / span >
2022-08-25 13:24:37 -07:00
< / >
) }
< / p >
2022-09-06 21:36:35 -07:00
< ArrowsRightLeftIcon
2022-09-07 19:49:12 -07:00
className = "default-transition ml-1 h-4 w-4 cursor-pointer text-th-fgd-1 hover:text-th-primary"
2022-08-25 13:24:37 -07:00
onClick = { ( ) = > setSwapRate ( ! swapRate ) }
/ >
< / div >
2022-09-07 19:49:12 -07:00
< div className = "space-y-2 px-1 text-xs" >
2022-08-25 13:24:37 -07:00
{ coingeckoPrices ? . outputCoingeckoPrice &&
coingeckoPrices ? . inputCoingeckoPrice ? (
< div
2022-09-22 03:46:51 -07:00
className = { ` text-right font-mono ${
2022-09-02 11:36:57 -07:00
coinGeckoPriceDifference . gt ( 0 )
2022-08-25 13:24:37 -07:00
? 'text-th-red'
: 'text-th-green'
} ` }
>
2022-09-02 11:36:57 -07:00
{ Decimal . abs ( coinGeckoPriceDifference ) . toFixed ( 1 ) } % { ' ' }
2022-09-16 04:37:24 -07:00
< span className = "font-body tracking-wide text-th-fgd-3" > { ` ${
2022-09-02 11:36:57 -07:00
coinGeckoPriceDifference . lte ( 0 )
2022-08-25 13:24:37 -07:00
? 'cheaper'
: 'more expensive'
} than CoinGecko ` }</span>
< / div >
) : null }
< / div >
< / div >
< / div >
2022-08-17 13:06:25 -07:00
< div className = "flex justify-between" >
< p className = "text-sm text-th-fgd-3" >
2022-09-14 18:06:00 -07:00
{ t ( 'swap:minimum-received' ) }
2022-08-17 13:06:25 -07:00
< / p >
{ outputTokenInfo ? . decimals ? (
2022-09-22 03:46:51 -07:00
< p className = "text-right font-mono text-sm text-th-fgd-1" >
2022-08-17 13:06:25 -07:00
{ formatDecimal (
2022-11-18 11:11:06 -08:00
selectedRoute ? . otherAmountThreshold /
2022-08-17 13:06:25 -07:00
10 * * outputTokenInfo . decimals || 1 ,
2022-09-05 15:38:47 -07:00
outputTokenInfo . decimals
2022-08-17 13:06:25 -07:00
) } { ' ' }
2022-09-16 04:37:24 -07:00
< span className = "font-body tracking-wide" >
{ outputTokenInfo ? . symbol }
< / span >
2022-08-17 13:06:25 -07:00
< / p >
) : null }
< / div >
2022-08-25 13:24:37 -07:00
{ borrowAmount ? (
2022-09-05 15:38:47 -07:00
< >
< div className = "flex justify-between" >
< p className = "text-sm text-th-fgd-3" > { t ( 'borrow-amount' ) } < / p >
2022-09-22 03:46:51 -07:00
< p className = "text-right font-mono text-sm text-th-fgd-1" >
2022-09-16 04:37:24 -07:00
~ { formatFixedDecimals ( borrowAmount ) } { ' ' }
< span className = "font-body tracking-wide" >
{ inputTokenInfo ? . symbol }
< / span >
2022-09-05 15:38:47 -07:00
< / p >
< / div >
< div className = "flex justify-between" >
< p className = "text-sm text-th-fgd-3" > Borrow Fee < / p >
2022-09-22 03:46:51 -07:00
< p className = "text-right font-mono text-sm text-th-fgd-1" >
2022-09-05 15:38:47 -07:00
~ { ' ' }
{ formatFixedDecimals (
amountIn
. mul ( inputBank ! . loanOriginationFeeRate . toFixed ( ) )
. toNumber ( )
) } { ' ' }
2022-09-16 04:37:24 -07:00
< span className = "font-body tracking-wide" >
{ inputBank ! . name }
< / span >
2022-09-05 15:38:47 -07:00
< / p >
< / div >
< / >
2022-08-25 13:24:37 -07:00
) : null }
2022-08-17 13:06:25 -07:00
< div className = "flex justify-between" >
2022-09-14 18:06:00 -07:00
< p className = "text-sm text-th-fgd-3" > Est . { t ( 'swap:slippage' ) } < / p >
2022-09-22 03:46:51 -07:00
< p className = "text-right font-mono text-sm text-th-fgd-1" >
2022-08-17 13:06:25 -07:00
{ selectedRoute ? . priceImpactPct * 100 < 0.1
? '< 0.1%'
2022-09-05 15:38:47 -07:00
: ` ${ ( selectedRoute ? . priceImpactPct * 100 ) . toFixed ( 2 ) } % ` }
2022-08-17 13:06:25 -07:00
< / p >
< / div >
< div className = "flex items-center justify-between" >
< p className = "text-sm text-th-fgd-3" > Swap Route < / p >
< div
className = "flex items-center text-th-fgd-1 md:hover:cursor-pointer md:hover:text-th-fgd-3"
role = "button"
onClick = { ( ) = > setShowRoutesModal ( true ) }
>
< span className = "overflow-ellipsis whitespace-nowrap" >
{ selectedRoute ? . marketInfos . map ( ( info , index ) = > {
let includeSeparator = false
if (
selectedRoute ? . marketInfos . length > 1 &&
index !== selectedRoute ? . marketInfos . length - 1
) {
includeSeparator = true
}
return (
2022-11-18 11:11:06 -08:00
< span key = { index } > { ` ${ info ? . label } ${
2022-08-17 13:06:25 -07:00
includeSeparator ? 'x ' : ''
} ` }</span>
)
} ) }
< / span >
2022-09-05 15:38:47 -07:00
< PencilIcon className = "ml-2 h-4 w-4 hover:text-th-primary" / >
2022-08-17 13:06:25 -07:00
< / div >
< / div >
{ typeof feeValue === 'number' ? (
< div className = "flex justify-between" >
< p className = "text-sm text-th-fgd-3" > { t ( 'fee' ) } < / p >
< div className = "flex items-center" >
2022-09-22 03:46:51 -07:00
< p className = "text-right font-mono text-sm text-th-fgd-1" >
2022-08-17 13:06:25 -07:00
≈ $ { feeValue ? . toFixed ( 2 ) }
< / p >
< / div >
< / div >
) : (
selectedRoute ? . marketInfos . map ( ( info , index ) = > {
2022-11-18 11:11:06 -08:00
const feeToken = mangoTokens . find (
2022-08-17 13:06:25 -07:00
( item ) = > item ? . address === info . lpFee ? . mint
)
return (
< div className = "flex justify-between" key = { index } >
< p className = "text-sm text-th-fgd-3" >
2022-09-14 18:06:00 -07:00
{ t ( 'swap:fees-paid-to' , {
2022-11-18 11:11:06 -08:00
route : info?.label ,
2022-08-17 13:06:25 -07:00
} ) }
< / p >
{ feeToken ? . decimals && (
2022-09-22 03:46:51 -07:00
< p className = "text-right font-mono text-sm text-th-fgd-1" >
2022-08-17 13:06:25 -07:00
{ (
2022-11-18 11:11:06 -08:00
info . lpFee ? . amount / Math . pow ( 10 , feeToken . decimals )
2022-08-17 13:06:25 -07:00
) . toFixed ( 6 ) } { ' ' }
2022-09-16 04:37:24 -07:00
< span className = "font-body tracking-wide" >
{ feeToken ? . symbol }
< / span > { ' ' }
( { info . lpFee ? . pct * 100 } % )
2022-08-17 13:06:25 -07:00
< / p >
) }
< / div >
)
} )
) }
{ / * { c o n n e c t e d ? (
< >
< div className = "flex justify-between" >
< span > { t ( 'swap:transaction-fee' ) } < / span >
< div className = "text-right text-th-fgd-1" >
{ depositAndFee
? depositAndFee ? . signatureFee / Math . pow ( 10 , 9 )
: '-' } { ' ' }
SOL
< / div >
< / div >
{ depositAndFee ? . ataDepositLength ||
depositAndFee ? . openOrdersDeposits ? . length ? (
< div className = "flex justify-between" >
< div className = "flex items-center" >
< span > { t ( 'deposit' ) } < / span >
< Tooltip
content = {
< >
{ depositAndFee ? . ataDepositLength ? (
< div > { t ( 'need-ata-account' ) } < / div >
) : null }
{ depositAndFee ? . openOrdersDeposits ? . length ? (
< div className = "mt-2" >
{ t ( 'swap:serum-requires-openorders' ) } { ' ' }
< a
href = "https://docs.google.com/document/d/1qEWc_Bmc1aAxyCUcilKB4ZYpOu3B0BxIbe__dRYmVns/"
target = "_blank"
rel = "noopener noreferrer"
>
{ t ( 'swap:heres-how' ) }
< / a >
< / div >
) : null }
< / >
}
placement = { 'left' }
>
< InformationCircleIcon className = "ml-1.5 h-3.5 w-3.5 cursor-help text-th-primary" / >
< / Tooltip >
< / div >
< div >
{ depositAndFee ? . ataDepositLength ? (
< div className = "text-right text-th-fgd-1" >
{ depositAndFee ? . ataDepositLength === 1
? t ( 'swap:ata-deposit-details' , {
cost : (
depositAndFee ? . ataDeposit / Math . pow ( 10 , 9 )
) . toFixed ( 5 ) ,
count : depositAndFee?.ataDepositLength ,
} )
: t ( 'swap:ata-deposit-details_plural' , {
cost : (
depositAndFee ? . ataDeposit / Math . pow ( 10 , 9 )
) . toFixed ( 5 ) ,
count : depositAndFee?.ataDepositLength ,
} ) }
< / div >
) : null }
{ depositAndFee ? . openOrdersDeposits ? . length ? (
< div className = "text-right text-th-fgd-1" >
{ depositAndFee ? . openOrdersDeposits . length > 1
? t ( 'swap:serum-details_plural' , {
cost : (
sum ( depositAndFee ? . openOrdersDeposits ) /
Math . pow ( 10 , 9 )
) . toFixed ( 5 ) ,
count : depositAndFee?.openOrdersDeposits.length ,
} )
: t ( 'swap:serum-details' , {
cost : (
sum ( depositAndFee ? . openOrdersDeposits ) /
Math . pow ( 10 , 9 )
) . toFixed ( 5 ) ,
count : depositAndFee?.openOrdersDeposits.length ,
} ) }
< / div >
) : null }
< / div >
< / div >
) : null }
< / >
) : null } * / }
< / div >
{ showRoutesModal ? (
< RoutesModal
show = { showRoutesModal }
onClose = { ( ) = > setShowRoutesModal ( false ) }
setSelectedRoute = { setSelectedRoute }
selectedRoute = { selectedRoute }
routes = { routes }
2022-08-18 13:50:34 -07:00
inputTokenSymbol = { inputTokenInfo ! . name }
2022-08-17 13:06:25 -07:00
outputTokenInfo = { outputTokenInfo }
/ >
) : null }
< / div >
< div className = "flex items-center justify-center pb-6" >
< Button
onClick = { onSwap }
className = "flex w-full items-center justify-center text-base"
size = "large"
>
{ submitting ? (
< Loading className = "mr-2 h-5 w-5" / >
) : (
2022-09-07 17:47:59 -07:00
< div className = "flex items-center" >
< CheckCircleIcon className = "mr-2 h-5 w-5" / >
2022-09-14 18:06:00 -07:00
{ t ( 'swap:confirm-swap' ) }
2022-09-07 17:47:59 -07:00
< / div >
2022-08-17 13:06:25 -07:00
) }
< / Button >
< / div >
< / div >
) : null
}
export default React . memo ( JupiterRouteInfo )