test placing orders and swap orders table
This commit is contained in:
parent
840991961f
commit
7e600cfd20
|
@ -13,7 +13,6 @@ import NumberFormat, {
|
|||
} from 'react-number-format'
|
||||
import Decimal from 'decimal.js'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import useDebounce from '../shared/useDebounce'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { SIZE_INPUT_UI_KEY } from '../../utils/constants'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
|
@ -24,6 +23,12 @@ import { floorToDecimal } from 'utils/numbers'
|
|||
import { withValueLimit } from './MarketSwapForm'
|
||||
import SellTokenInput from './SellTokenInput'
|
||||
import BuyTokenInput from './BuyTokenInput'
|
||||
import { notify } from 'utils/notifications'
|
||||
import * as sentry from '@sentry/nextjs'
|
||||
import { isMangoError } from 'types'
|
||||
import Button from '@components/shared/Button'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import Loading from '@components/shared/Loading'
|
||||
|
||||
type LimitSwapFormProps = {
|
||||
setShowTokenSelect: Dispatch<SetStateAction<'input' | 'output' | undefined>>
|
||||
|
@ -35,9 +40,11 @@ const set = mangoStore.getState().set
|
|||
|
||||
const LimitSwapForm = ({ setShowTokenSelect }: LimitSwapFormProps) => {
|
||||
const { t } = useTranslation(['common', 'swap', 'trade'])
|
||||
const { connected } = useWallet()
|
||||
const [animateSwitchArrow, setAnimateSwitchArrow] = useState(0)
|
||||
const [orderType, setOrderType] = useState(ORDER_TYPES[0])
|
||||
const [triggerPrice, setTriggerPrice] = useState('')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [swapFormSizeUi] = useLocalStorageState(SIZE_INPUT_UI_KEY, 'slider')
|
||||
|
||||
const {
|
||||
|
@ -48,20 +55,28 @@ const LimitSwapForm = ({ setShowTokenSelect }: LimitSwapFormProps) => {
|
|||
amountOut: amountOutFormValue,
|
||||
limitPrice,
|
||||
} = mangoStore((s) => s.swap)
|
||||
const [debouncedAmountIn] = useDebounce(amountInFormValue, 300)
|
||||
const [debouncedAmountOut] = useDebounce(amountOutFormValue, 300)
|
||||
|
||||
const amountInAsDecimal: Decimal | null = useMemo(() => {
|
||||
return Number(debouncedAmountIn)
|
||||
? new Decimal(debouncedAmountIn)
|
||||
return Number(amountInFormValue)
|
||||
? new Decimal(amountInFormValue)
|
||||
: new Decimal(0)
|
||||
}, [debouncedAmountIn])
|
||||
}, [amountInFormValue])
|
||||
|
||||
const amountOutAsDecimal: Decimal | null = useMemo(() => {
|
||||
return Number(debouncedAmountOut)
|
||||
? new Decimal(debouncedAmountOut)
|
||||
return Number(amountOutFormValue)
|
||||
? new Decimal(amountOutFormValue)
|
||||
: new Decimal(0)
|
||||
}, [debouncedAmountOut])
|
||||
}, [amountOutFormValue])
|
||||
|
||||
const [baseBank, quoteBank] = useMemo(() => {
|
||||
if (inputBank && inputBank.name === 'USDC') {
|
||||
return [outputBank, inputBank]
|
||||
} else if (outputBank && outputBank.name === 'USDC') {
|
||||
return [inputBank, outputBank]
|
||||
} else if (inputBank && inputBank.name === 'SOL') {
|
||||
return [outputBank, inputBank]
|
||||
} else return [inputBank, outputBank]
|
||||
}, [inputBank, outputBank])
|
||||
|
||||
const setAmountInFormValue = useCallback((amountIn: string) => {
|
||||
set((s) => {
|
||||
|
@ -87,6 +102,16 @@ const LimitSwapForm = ({ setShowTokenSelect }: LimitSwapFormProps) => {
|
|||
})
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!baseBank || !quoteBank) return
|
||||
const initialLimitPrice = baseBank.uiPrice / quoteBank.uiPrice
|
||||
if (!limitPrice) {
|
||||
set((s) => {
|
||||
s.swap.limitPrice = initialLimitPrice.toString()
|
||||
})
|
||||
}
|
||||
}, [baseBank, limitPrice, quoteBank])
|
||||
|
||||
/*
|
||||
If the use margin setting is toggled, clear the form values
|
||||
*/
|
||||
|
@ -100,14 +125,26 @@ const LimitSwapForm = ({ setShowTokenSelect }: LimitSwapFormProps) => {
|
|||
if (info.source !== 'event') return
|
||||
setAmountInFormValue(e.value)
|
||||
if (parseFloat(e.value) > 0 && limitPrice && outputBank) {
|
||||
const amount = floorToDecimal(
|
||||
parseFloat(e.value) / parseFloat(limitPrice),
|
||||
outputBank.mintDecimals,
|
||||
)
|
||||
const amount =
|
||||
outputBank.name === quoteBank?.name
|
||||
? floorToDecimal(
|
||||
parseFloat(e.value) * parseFloat(limitPrice),
|
||||
outputBank.mintDecimals,
|
||||
)
|
||||
: floorToDecimal(
|
||||
parseFloat(e.value) / parseFloat(limitPrice),
|
||||
outputBank.mintDecimals,
|
||||
)
|
||||
setAmountOutFormValue(amount.toString())
|
||||
}
|
||||
},
|
||||
[limitPrice, outputBank, setAmountInFormValue, setAmountOutFormValue],
|
||||
[
|
||||
limitPrice,
|
||||
outputBank,
|
||||
quoteBank,
|
||||
setAmountInFormValue,
|
||||
setAmountOutFormValue,
|
||||
],
|
||||
)
|
||||
|
||||
const handleAmountOutChange = useCallback(
|
||||
|
@ -115,14 +152,26 @@ const LimitSwapForm = ({ setShowTokenSelect }: LimitSwapFormProps) => {
|
|||
if (info.source !== 'event') return
|
||||
setAmountOutFormValue(e.value)
|
||||
if (parseFloat(e.value) > 0 && limitPrice && inputBank) {
|
||||
const amount = floorToDecimal(
|
||||
parseFloat(e.value) * parseFloat(limitPrice),
|
||||
inputBank.mintDecimals,
|
||||
)
|
||||
const amount =
|
||||
outputBank?.name === quoteBank?.name
|
||||
? floorToDecimal(
|
||||
parseFloat(e.value) / parseFloat(limitPrice),
|
||||
inputBank.mintDecimals,
|
||||
)
|
||||
: floorToDecimal(
|
||||
parseFloat(e.value) * parseFloat(limitPrice),
|
||||
inputBank.mintDecimals,
|
||||
)
|
||||
setAmountInFormValue(amount.toString())
|
||||
}
|
||||
},
|
||||
[inputBank, limitPrice, setAmountInFormValue, setAmountOutFormValue],
|
||||
[
|
||||
inputBank,
|
||||
outputBank,
|
||||
limitPrice,
|
||||
setAmountInFormValue,
|
||||
setAmountOutFormValue,
|
||||
],
|
||||
)
|
||||
|
||||
const handleAmountInUi = useCallback(
|
||||
|
@ -149,7 +198,7 @@ const LimitSwapForm = ({ setShowTokenSelect }: LimitSwapFormProps) => {
|
|||
outputBank
|
||||
) {
|
||||
const amount = floorToDecimal(
|
||||
parseFloat(amountInFormValue) / parseFloat(e.value),
|
||||
parseFloat(amountInFormValue) * parseFloat(e.value),
|
||||
outputBank.mintDecimals,
|
||||
)
|
||||
setAmountOutFormValue(amount.toString())
|
||||
|
@ -166,20 +215,101 @@ const LimitSwapForm = ({ setShowTokenSelect }: LimitSwapFormProps) => {
|
|||
[setTriggerPrice],
|
||||
)
|
||||
|
||||
const handleSwitchTokens = useCallback(() => {
|
||||
if (amountInAsDecimal?.gt(0) && amountOutAsDecimal.gte(0)) {
|
||||
setAmountInFormValue(amountOutAsDecimal.toString())
|
||||
const handleLimitSwap = useCallback(async () => {
|
||||
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
|
||||
|
||||
if (
|
||||
!mangoAccount ||
|
||||
!group ||
|
||||
!inputBank ||
|
||||
!outputBank ||
|
||||
(!triggerPrice && orderType !== 'trade:limit') ||
|
||||
(!limitPrice && orderType !== 'trade:stop-market')
|
||||
)
|
||||
return
|
||||
setSubmitting(true)
|
||||
|
||||
const orderPrice =
|
||||
orderType === 'trade:limit'
|
||||
? parseFloat(limitPrice!)
|
||||
: parseFloat(triggerPrice)
|
||||
|
||||
const stopLimitPrice =
|
||||
orderType !== 'trade:stop-market' ? parseFloat(limitPrice!) : 0
|
||||
|
||||
try {
|
||||
const tx = await client.tokenConditionalSwapStopLoss(
|
||||
group,
|
||||
mangoAccount,
|
||||
inputBank.mint,
|
||||
orderPrice,
|
||||
outputBank.mint,
|
||||
stopLimitPrice,
|
||||
amountInAsDecimal.toNumber(),
|
||||
null,
|
||||
null,
|
||||
)
|
||||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
type: 'success',
|
||||
txid: tx,
|
||||
noSound: true,
|
||||
})
|
||||
actions.fetchGroup()
|
||||
await actions.reloadMangoAccount()
|
||||
} catch (e) {
|
||||
console.error('onSwap error: ', e)
|
||||
sentry.captureException(e)
|
||||
if (isMangoError(e)) {
|
||||
notify({
|
||||
title: 'Transaction failed',
|
||||
description: e.message,
|
||||
txid: e?.txid,
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Swap error:', e)
|
||||
} finally {
|
||||
setSubmitting(false)
|
||||
}
|
||||
}, [orderType, limitPrice, triggerPrice, amountInAsDecimal])
|
||||
|
||||
const handleSwitchTokens = useCallback(() => {
|
||||
if (amountInAsDecimal?.gt(0) && limitPrice) {
|
||||
const amountOut =
|
||||
outputBank?.name !== quoteBank?.name
|
||||
? amountInAsDecimal.mul(limitPrice)
|
||||
: amountInAsDecimal.div(limitPrice)
|
||||
setAmountOutFormValue(amountOut.toString())
|
||||
}
|
||||
const inputBank = mangoStore.getState().swap.inputBank
|
||||
const outputBank = mangoStore.getState().swap.outputBank
|
||||
set((s) => {
|
||||
s.swap.inputBank = outputBank
|
||||
s.swap.outputBank = inputBank
|
||||
// s.swap.limitPrice = ''
|
||||
})
|
||||
setAnimateSwitchArrow(
|
||||
(prevanimateSwitchArrow) => prevanimateSwitchArrow + 1,
|
||||
)
|
||||
}, [setAmountInFormValue, amountOutAsDecimal, amountInAsDecimal])
|
||||
}, [
|
||||
setAmountInFormValue,
|
||||
amountOutAsDecimal,
|
||||
amountInAsDecimal,
|
||||
limitPrice,
|
||||
inputBank,
|
||||
outputBank,
|
||||
quoteBank,
|
||||
])
|
||||
|
||||
const limitOrderDisabled =
|
||||
!connected || !amountInFormValue || !amountOutFormValue
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -231,7 +361,13 @@ const LimitSwapForm = ({ setShowTokenSelect }: LimitSwapFormProps) => {
|
|||
) : null}
|
||||
{orderType !== 'trade:stop-market' ? (
|
||||
<div className="col-span-1">
|
||||
<p className="mb-2 text-th-fgd-2">{t('trade:limit-price')}</p>
|
||||
<p className="mb-2 text-th-fgd-2">
|
||||
{t('trade:limit-price')}
|
||||
<span className="text-xs text-th-fgd-3">
|
||||
{' '}
|
||||
({quoteBank?.name})
|
||||
</span>
|
||||
</p>
|
||||
<NumberFormat
|
||||
inputMode="decimal"
|
||||
thousandSeparator=","
|
||||
|
@ -283,6 +419,14 @@ const LimitSwapForm = ({ setShowTokenSelect }: LimitSwapFormProps) => {
|
|||
useMargin={useMargin}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
onClick={handleLimitSwap}
|
||||
className="mt-6 mb-4 flex w-full items-center justify-center text-base"
|
||||
disabled={limitOrderDisabled}
|
||||
size="large"
|
||||
>
|
||||
{submitting ? <Loading /> : t('swap:place-limit-order')}
|
||||
</Button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@ const SwapForm = () => {
|
|||
const bank = group.getFirstBankByMint(new PublicKey(mintAddress))
|
||||
set((s) => {
|
||||
s.swap.inputBank = bank
|
||||
s.swap.limitPrice = ''
|
||||
})
|
||||
}
|
||||
setShowTokenSelect(undefined)
|
||||
|
@ -105,6 +106,7 @@ const SwapForm = () => {
|
|||
const bank = group.getFirstBankByMint(new PublicKey(mintAddress))
|
||||
set((s) => {
|
||||
s.swap.outputBank = bank
|
||||
s.swap.limitPrice = ''
|
||||
})
|
||||
}
|
||||
setShowTokenSelect(undefined)
|
||||
|
@ -167,19 +169,10 @@ const SwapForm = () => {
|
|||
const handleSwapOrLimit = useCallback(
|
||||
(orderType: string) => {
|
||||
setSwapOrLimit(orderType)
|
||||
if (orderType === 'trade:limit' && outputBank) {
|
||||
set((s) => {
|
||||
s.swap.limitPrice = outputBank.uiPrice.toString()
|
||||
})
|
||||
}
|
||||
},
|
||||
[outputBank, set, setSwapOrLimit],
|
||||
)
|
||||
|
||||
const handlePlaceOrder = () => {
|
||||
console.log('place swap limit order')
|
||||
}
|
||||
|
||||
const handleSetMargin = () => {
|
||||
set((s) => {
|
||||
s.swap.margin = !s.swap.margin
|
||||
|
@ -190,9 +183,6 @@ const SwapForm = () => {
|
|||
setSavedSwapMargin(useMargin)
|
||||
}, [useMargin])
|
||||
|
||||
const limitOrderDisabled =
|
||||
!connected || !amountInFormValue || !amountOutFormValue
|
||||
|
||||
return (
|
||||
<ContentBox
|
||||
hidePadding
|
||||
|
@ -279,16 +269,7 @@ const SwapForm = () => {
|
|||
selectedRoute ? amountOutAsDecimal.toNumber() : undefined
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
onClick={handlePlaceOrder}
|
||||
className="mt-6 mb-4 flex w-full items-center justify-center text-base"
|
||||
disabled={limitOrderDisabled}
|
||||
size="large"
|
||||
>
|
||||
{t('swap:place-limit-order')}
|
||||
</Button>
|
||||
)
|
||||
) : null
|
||||
) : (
|
||||
<Button
|
||||
disabled
|
||||
|
|
|
@ -7,6 +7,7 @@ import useMangoAccount from 'hooks/useMangoAccount'
|
|||
import ManualRefresh from '@components/shared/ManualRefresh'
|
||||
import { useViewport } from 'hooks/useViewport'
|
||||
import { breakpoints } from 'utils/theme'
|
||||
import SwapOrders from './SwapOrders'
|
||||
|
||||
const SwapInfoTabs = () => {
|
||||
const [selectedTab, setSelectedTab] = useState('balances')
|
||||
|
@ -18,6 +19,7 @@ const SwapInfoTabs = () => {
|
|||
const tabsWithCount: [string, number][] = useMemo(() => {
|
||||
return [
|
||||
['balances', 0],
|
||||
['orders', 0],
|
||||
['swap:swap-history', 0],
|
||||
]
|
||||
}, [openOrders, mangoAccount])
|
||||
|
@ -38,6 +40,7 @@ const SwapInfoTabs = () => {
|
|||
/>
|
||||
</div>
|
||||
{selectedTab === 'balances' ? <SwapTradeBalances /> : null}
|
||||
{selectedTab === 'orders' ? <SwapOrders /> : null}
|
||||
{selectedTab === 'swap:swap-history' ? <SwapHistoryTable /> : null}
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
import { IconButton } from '@components/shared/Button'
|
||||
import ConnectEmptyState from '@components/shared/ConnectEmptyState'
|
||||
import {
|
||||
SortableColumnHeader,
|
||||
Table,
|
||||
Td,
|
||||
Th,
|
||||
TrBody,
|
||||
TrHead,
|
||||
} from '@components/shared/TableElements'
|
||||
import { NoSymbolIcon, TrashIcon } from '@heroicons/react/20/solid'
|
||||
import { BN } from '@project-serum/anchor'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import { useSortableData } from 'hooks/useSortableData'
|
||||
// import { useViewport } from 'hooks/useViewport'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { notify } from 'utils/notifications'
|
||||
import { floorToDecimal } from 'utils/numbers'
|
||||
// import { breakpoints } from 'utils/theme'
|
||||
import * as sentry from '@sentry/nextjs'
|
||||
import { isMangoError } from 'types'
|
||||
import Loading from '@components/shared/Loading'
|
||||
|
||||
const SwapOrders = () => {
|
||||
const { t } = useTranslation(['common', 'swap', 'trade'])
|
||||
// const { width } = useViewport()
|
||||
// const showTableView = width ? width > breakpoints.md : false
|
||||
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
|
||||
const { group } = useMangoGroup()
|
||||
const { connected } = useWallet()
|
||||
const [cancelId, setCancelId] = useState('')
|
||||
|
||||
const orders = useMemo(() => {
|
||||
if (!mangoAccount) return []
|
||||
return mangoAccount.tokenConditionalSwaps.filter((tcs) => tcs.hasData)
|
||||
}, [mangoAccount])
|
||||
|
||||
const formattedTableData = useCallback(() => {
|
||||
if (!group) return []
|
||||
const formatted = []
|
||||
for (const order of orders) {
|
||||
const buyBank = group.getFirstBankByTokenIndex(order.buyTokenIndex)
|
||||
const sellBank = group.getFirstBankByTokenIndex(order.sellTokenIndex)
|
||||
const market = `${sellBank.name}/${buyBank.name}`
|
||||
const size = floorToDecimal(
|
||||
order.getMaxSellUi(group),
|
||||
sellBank.mintDecimals,
|
||||
).toNumber()
|
||||
const triggerPrice = order.getPriceLowerLimitUi(group)
|
||||
const limitPrice = order.getPriceUpperLimitUi(group)
|
||||
const pricePremium = order.getPricePremium()
|
||||
|
||||
const orderType =
|
||||
limitPrice === 0
|
||||
? 'trade:stop-market'
|
||||
: triggerPrice === limitPrice
|
||||
? 'trade:limit'
|
||||
: 'trade:stop-limit'
|
||||
|
||||
const data = {
|
||||
...order,
|
||||
buyBank,
|
||||
sellBank,
|
||||
market,
|
||||
size,
|
||||
triggerPrice,
|
||||
limitPrice,
|
||||
orderType,
|
||||
fee: pricePremium,
|
||||
}
|
||||
formatted.push(data)
|
||||
}
|
||||
return formatted
|
||||
}, [group, orders])
|
||||
|
||||
const {
|
||||
items: tableData,
|
||||
requestSort,
|
||||
sortConfig,
|
||||
} = useSortableData(formattedTableData())
|
||||
|
||||
const handleCancel = async (id: BN) => {
|
||||
try {
|
||||
const client = mangoStore.getState().client
|
||||
const group = mangoStore.getState().group
|
||||
const actions = mangoStore.getState().actions
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
|
||||
if (!mangoAccount || !group) return
|
||||
setCancelId(id.toString())
|
||||
|
||||
try {
|
||||
const tx = await client.tokenConditionalSwapCancel(
|
||||
group,
|
||||
mangoAccount,
|
||||
id,
|
||||
)
|
||||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
type: 'success',
|
||||
txid: tx,
|
||||
noSound: true,
|
||||
})
|
||||
actions.fetchGroup()
|
||||
await actions.reloadMangoAccount()
|
||||
} catch (e) {
|
||||
console.error('failed to cancel swap order', e)
|
||||
sentry.captureException(e)
|
||||
if (isMangoError(e)) {
|
||||
notify({
|
||||
title: 'Transaction failed',
|
||||
description: e.message,
|
||||
txid: e?.txid,
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('failed to cancel swap order', e)
|
||||
} finally {
|
||||
setCancelId('')
|
||||
}
|
||||
}
|
||||
|
||||
return orders.length ? (
|
||||
<Table>
|
||||
<thead>
|
||||
<TrHead>
|
||||
<Th className="text-left">
|
||||
<SortableColumnHeader
|
||||
sortKey="market"
|
||||
sort={() => requestSort('market')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('market')}
|
||||
/>
|
||||
</Th>
|
||||
<Th>
|
||||
<div className="flex justify-end">
|
||||
<SortableColumnHeader
|
||||
sortKey="orderType"
|
||||
sort={() => requestSort('orderType')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('order-type')}
|
||||
/>
|
||||
</div>
|
||||
</Th>
|
||||
<Th>
|
||||
<div className="flex justify-end">
|
||||
<SortableColumnHeader
|
||||
sortKey="size"
|
||||
sort={() => requestSort('size')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('size')}
|
||||
/>
|
||||
</div>
|
||||
</Th>
|
||||
<Th>
|
||||
<div className="flex justify-end">
|
||||
<SortableColumnHeader
|
||||
sortKey="triggerPrice"
|
||||
sort={() => requestSort('triggerPrice')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('trigger-price')}
|
||||
/>
|
||||
</div>
|
||||
</Th>
|
||||
<Th>
|
||||
<div className="flex justify-end">
|
||||
<SortableColumnHeader
|
||||
sortKey="limitPrice"
|
||||
sort={() => requestSort('limitPrice')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('limit-price')}
|
||||
/>
|
||||
</div>
|
||||
</Th>
|
||||
<Th>
|
||||
<div className="flex justify-end">
|
||||
<SortableColumnHeader
|
||||
sortKey="fee"
|
||||
sort={() => requestSort('fee')}
|
||||
sortConfig={sortConfig}
|
||||
title={t('fee')}
|
||||
/>
|
||||
</div>
|
||||
</Th>
|
||||
<Th className="text-right">{t('cancel')}</Th>
|
||||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{tableData.map((data, i) => {
|
||||
const {
|
||||
buyBank,
|
||||
fee,
|
||||
market,
|
||||
orderType,
|
||||
limitPrice,
|
||||
sellBank,
|
||||
size,
|
||||
triggerPrice,
|
||||
} = data
|
||||
return (
|
||||
<TrBody key={i} className="text-sm">
|
||||
<Td>{market}</Td>
|
||||
<Td>
|
||||
<p className="text-right font-body">{t(orderType)}</p>
|
||||
</Td>
|
||||
<Td>
|
||||
<p className="text-right">
|
||||
{size}
|
||||
<span className="text-th-fgd-3 font-body">
|
||||
{' '}
|
||||
{sellBank.name}
|
||||
</span>
|
||||
</p>
|
||||
</Td>
|
||||
<Td>
|
||||
{triggerPrice !== limitPrice ? (
|
||||
<p className="text-right">
|
||||
{triggerPrice}
|
||||
<span className="text-th-fgd-3 font-body">
|
||||
{' '}
|
||||
{buyBank.name}
|
||||
</span>
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-right">–</p>
|
||||
)}
|
||||
</Td>
|
||||
<Td>
|
||||
{limitPrice ? (
|
||||
<p className="text-right">
|
||||
{limitPrice}
|
||||
<span className="text-th-fgd-3 font-body">
|
||||
{' '}
|
||||
{buyBank.name}
|
||||
</span>
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-right">–</p>
|
||||
)}
|
||||
</Td>
|
||||
<Td>
|
||||
<p className="text-right">{fee.toFixed(2)}%</p>
|
||||
</Td>
|
||||
<Td className="flex justify-end">
|
||||
<IconButton onClick={() => handleCancel(data.id)} size="small">
|
||||
{cancelId === data.id.toString() ? (
|
||||
<Loading />
|
||||
) : (
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
)}
|
||||
</IconButton>
|
||||
</Td>
|
||||
</TrBody>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</Table>
|
||||
) : mangoAccountAddress || connected ? (
|
||||
<div className="flex flex-col items-center p-8">
|
||||
<NoSymbolIcon className="mb-2 h-6 w-6 text-th-fgd-4" />
|
||||
<p>{t('trade:no-orders')}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="p-8">
|
||||
<ConnectEmptyState text={t('connect-orders')} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SwapOrders
|
Loading…
Reference in New Issue