import { PerpMarket } from '@blockworks-foundation/mango-v4' import SideBadge from '@components/shared/SideBadge' import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements' import { LinkIcon, NoSymbolIcon } from '@heroicons/react/20/solid' import { useWallet } from '@solana/wallet-adapter-react' import { PublicKey } from '@solana/web3.js' import mangoStore from '@store/mangoStore' import useMangoAccount from 'hooks/useMangoAccount' import useSelectedMarket from 'hooks/useSelectedMarket' import { useTranslation } from 'next-i18next' import { useMemo } from 'react' import { formatDecimal } from 'utils/numbers' import TableMarketName from './TableMarketName' const byTimestamp = (a: any, b: any) => { return ( new Date(b.loadTimestamp || b.timestamp * 1000).getTime() - new Date(a.loadTimestamp || a.timestamp * 1000).getTime() ) } const reverseSide = (side: string) => (side === 'buy' ? 'sell' : 'buy') const parsedPerpEvent = (mangoAccountPk: PublicKey, event: any) => { console.log('event: ', event) const maker = event.maker.toString() === mangoAccountPk.toString() const orderId = maker ? event.makerOrderId : event.takerOrderId const value = event.quantity * event.price const feeRate = maker ? event.makerFee.val.toNumber() : event.takerFee.val.toNumber() const side = maker ? reverseSide(event.takerSide) : event.takerSide return { ...event, key: orderId?.toString(), liquidity: maker ? 'Maker' : 'Taker', size: event.size, price: event.price, value, feeCost: (feeRate * value).toFixed(4), side, marketName: event.marketName, } } const parsedSerumEvent = (event: any) => { let liquidity if (event.eventFlags) { liquidity = event?.eventFlags?.maker ? 'Maker' : 'Taker' } else { liquidity = event.maker ? 'Maker' : 'Taker' } return { ...event, liquidity, key: `${event.maker}-${event.price}`, value: event.price * event.size, side: event.side, marketName: event.marketName, } } const formatTradeHistory = (mangoAccountPk: PublicKey, tradeHistory: any[]) => { return tradeHistory .flat() .map((event) => { if (event.eventFlags || event.nativeQuantityPaid) { return parsedSerumEvent(event) } else if (event.maker) { return parsedPerpEvent(mangoAccountPk, event) } else { return event } }) .sort(byTimestamp) } const TradeHistory = () => { const { t } = useTranslation(['common', 'trade']) const { connected } = useWallet() const { selectedMarket } = useSelectedMarket() const { mangoAccount } = useMangoAccount() const fills = mangoStore((s) => s.selectedMarket.fills) const openOrderOwner = useMemo(() => { if (!mangoAccount || !selectedMarket) return if (selectedMarket instanceof PerpMarket) { return mangoAccount.publicKey } else { return mangoAccount.getSerum3OoAccount(selectedMarket.marketIndex).address } }, [mangoAccount, selectedMarket]) const tradeHistoryFromEventQueue = useMemo(() => { if (!mangoAccount || !selectedMarket) return [] const mangoAccountFills = fills .filter((fill: any) => { if (fill.openOrders) { // handles serum event queue for spot trades return openOrderOwner ? fill.openOrders.equals(openOrderOwner) : false } else { // handles mango event queue for perp trades return ( fill.taker.equals(openOrderOwner) || fill.maker.equals(openOrderOwner) ) } }) .map((fill: any) => ({ ...fill, marketName: selectedMarket.name })) return formatTradeHistory(mangoAccount.publicKey, mangoAccountFills) }, [selectedMarket, mangoAccount, openOrderOwner]) if (!selectedMarket) return null return connected ? ( tradeHistoryFromEventQueue.length ? (
{tradeHistoryFromEventQueue.map((trade: any) => { return ( ) })}
Market Side Size Price Value Fee
{trade.size} {formatDecimal(trade.price)} ${trade.value.toFixed(2)} {trade.feeCost}

During the Mango V4 alpha, only your most recent trades will be displayed. Full trade history will be available after the alpha phase is complete.

) : (

No trade history for {selectedMarket?.name}

During the Mango V4 alpha, only your recent trades will be displayed. Full trade history will be available after the alpha phase is complete.

) ) : (

{t('trade:connect-positions')}

) } export default TradeHistory