import { useState } from 'react' import { PencilIcon, TrashIcon, XIcon } from '@heroicons/react/outline' import Link from 'next/link' import { useRouter } from 'next/router' import { useOpenOrders } from '../hooks/useOpenOrders' import Button, { IconButton } from './Button' import Loading from './Loading' import useMangoStore from '../stores/useMangoStore' import { notify } from '../utils/notifications' import SideBadge from './SideBadge' import { Order, Market } from '@project-serum/serum/lib/market' import { PerpOrder, PerpMarket, MarketConfig, } from '@blockworks-foundation/mango-client' import { formatUsdValue, getDecimalCount, usdFormatter } from '../utils' import { Table, Td, Th, TrBody, TrHead } from './TableElements' import { useViewport } from '../hooks/useViewport' import { breakpoints } from './TradePageGrid' import { Row } from './TableElements' import { PerpTriggerOrder } from '../@types/types' import { useTranslation } from 'next-i18next' import Input from './Input' const DesktopTable = ({ cancelledOrderId, editOrderIndex, handleCancelOrder, handleModifyOrder, modifiedOrderId, openOrders, setEditOrderIndex, }) => { const { t } = useTranslation('common') const { asPath } = useRouter() const [modifiedOrderSize, setModifiedOrderSize] = useState('') const [modifiedOrderPrice, setModifiedOrderPrice] = useState('') const showEditOrderForm = (index, order) => { setEditOrderIndex(index) setModifiedOrderSize(order.size) setModifiedOrderPrice(order.price) } const renderMarketName = (market: MarketConfig) => { const location = market.kind === 'spot' ? `/market?name=${market.baseSymbol}%2FUSDC` : `/market?name=${market.name}` if (!asPath.includes(location)) { return ( {market.name} ) } else { return {market.name} } } return ( {openOrders.map(({ order, market }, index) => { const decimals = getDecimalCount(market.account.tickSize) const editThisOrder = editOrderIndex === index return ( {editOrderIndex !== index ? ( <> ) : ( <> )} ) })}
{t('market')} {t('size')} {t('size')} {t('price')} {t('value')} {t('condition')} {t('edit')}
{renderMarketName(market.config)}
{order.size} {usdFormatter(order.price, decimals)} setModifiedOrderSize(e.target.value)} /> setModifiedOrderPrice(e.target.value)} /> {editThisOrder ? '' : formatUsdValue(order.price * order.size)} {order.perpTrigger && `${t(order.orderType)} ${t( order.triggerCondition )} $${order.triggerPrice.toFixed(2)}`}
{editOrderIndex !== index ? ( <> {!order.perpTrigger ? ( ) : null} ) : ( <> )}
) } const MobileTable = ({ cancelledOrderId, editOrderIndex, handleCancelOrder, handleModifyOrder, modifiedOrderId, openOrders, setEditOrderIndex, }) => { const { t } = useTranslation('common') const [modifiedOrderSize, setModifiedOrderSize] = useState('') const [modifiedOrderPrice, setModifiedOrderPrice] = useState('') const showEditOrderForm = (index) => { setEditOrderIndex(index) setModifiedOrderSize('') setModifiedOrderPrice('') } return ( <> {openOrders.map(({ market, order }, index) => { const editThisOrder = editOrderIndex === index return (
{market.config.name}
{order.side.toUpperCase()} {order.perpTrigger ? `${order.size} ${ order.triggerCondition } ${formatUsdValue(order.triggerPrice)}` : `${order.size} at ${formatUsdValue(order.price)}`}
{!order.perpTrigger ? ( editThisOrder ? setEditOrderIndex(null) : showEditOrderForm(index) } > {editThisOrder ? ( ) : ( )} ) : null} handleCancelOrder(order, market.account)} > {cancelledOrderId + '' === order.orderId + '' ? ( ) : ( )}
{editThisOrder ? (
setModifiedOrderSize(e.target.value)} />
setModifiedOrderPrice(e.target.value)} />
) : null}
) })} ) } const OpenOrdersTable = () => { const { t } = useTranslation('common') const { asPath } = useRouter() const openOrders = useOpenOrders() const [cancelId, setCancelId] = useState(null) const [modifyId, setModifyId] = useState(null) const [editOrderIndex, setEditOrderIndex] = useState(null) const actions = useMangoStore((s) => s.actions) const { width } = useViewport() const isMobile = width ? width < breakpoints.md : false const handleCancelOrder = async ( order: Order | PerpOrder | PerpTriggerOrder, market: Market | PerpMarket ) => { const wallet = useMangoStore.getState().wallet.current const selectedMangoGroup = useMangoStore.getState().selectedMangoGroup.current const selectedMangoAccount = useMangoStore.getState().selectedMangoAccount.current const mangoClient = useMangoStore.getState().connection.client setCancelId(order.orderId) let txid try { if (!selectedMangoGroup || !selectedMangoAccount) return if (market instanceof Market) { txid = await mangoClient.cancelSpotOrder( selectedMangoGroup, selectedMangoAccount, wallet, market, order as Order ) actions.reloadOrders() } else if (market instanceof PerpMarket) { // TODO: this is not ideal if (order['triggerCondition']) { txid = await mangoClient.removeAdvancedOrder( selectedMangoGroup, selectedMangoAccount, wallet, (order as PerpTriggerOrder).orderId ) actions.reloadOrders() } else { txid = await mangoClient.cancelPerpOrder( selectedMangoGroup, selectedMangoAccount, wallet, market, order as PerpOrder, false ) } } notify({ title: t('cancel-success'), txid }) } catch (e) { notify({ title: t('cancel-error'), description: e.message, txid: e.txid, type: 'error', }) console.log('error', `${e}`) } finally { actions.reloadMangoAccount() actions.updateOpenOrders() setCancelId(null) } } const handleModifyOrder = async ( order: Order | PerpOrder, market: Market | PerpMarket, price: number, size: number ) => { const mangoAccount = useMangoStore.getState().selectedMangoAccount.current const mangoGroup = useMangoStore.getState().selectedMangoGroup.current const mangoClient = useMangoStore.getState().connection.client const { askInfo, bidInfo } = useMangoStore.getState().selectedMarket const wallet = useMangoStore.getState().wallet.current if (!wallet || !mangoGroup || !mangoAccount || !market) return setModifyId(order.orderId) try { const orderPrice = price if (!orderPrice) { notify({ title: t('price-unavailable'), description: t('try-again'), type: 'error', }) } const orderType = 'limit' let txid if (market instanceof Market) { txid = await mangoClient.modifySpotOrder( mangoGroup, mangoAccount, mangoGroup.mangoCache, market, wallet, order as Order, order.side, orderPrice, size, orderType ) } else { txid = await mangoClient.modifyPerpOrder( mangoGroup, mangoAccount, mangoGroup.mangoCache, market, wallet, order as PerpOrder, order.side, orderPrice, size, orderType, 0, order.side === 'buy' ? askInfo : bidInfo ) } notify({ title: t('successfully-placed'), txid }) } catch (e) { console.log('error: ', e.message, e.txid, e) notify({ title: t('order-error'), description: e.message, txid: e.txid, type: 'error', }) } finally { actions.reloadMangoAccount() actions.reloadOrders() actions.updateOpenOrders() setModifyId(null) setEditOrderIndex(null) } } const tableProps = { openOrders, cancelledOrderId: cancelId, editOrderIndex, handleCancelOrder, handleModifyOrder, modifiedOrderId: modifyId, setEditOrderIndex, } return (
{openOrders && openOrders.length > 0 ? ( !isMobile ? ( ) : ( ) ) : (
{t('no-orders')} {asPath === '/account' ? ( {t('make-trade')} ) : null}
)}
) } export default OpenOrdersTable