import { PerpOrder, BookSide, BookSideLayout, getMarketByPublicKey, MarketConfig, PerpMarket, MangoAccount, } from '@blockworks-foundation/mango-client' import { Market, Orderbook } from '@project-serum/serum' import { Order } from '@project-serum/serum/lib/market' import { PerpTriggerOrder } from '../@types/types' import useMangoStore from '../stores/useMangoStore' type OrderInfo = { order: Order | PerpOrder | PerpTriggerOrder market: { account: Market | PerpMarket; config: MarketConfig } } function parseSpotOrders( market: Market, config: MarketConfig, mangoAccount: MangoAccount, accountInfos ) { const openOrders = mangoAccount.spotOpenOrdersAccounts[config.marketIndex] if (!openOrders) return [] const bidData = accountInfos[market['_decoded'].bids.toBase58()]?.data const askData = accountInfos[market['_decoded'].asks.toBase58()]?.data const bidOrderBook = market && bidData ? Orderbook.decode(market, bidData) : [] const askOrderBook = market && askData ? Orderbook.decode(market, askData) : [] const openOrdersForMarket = [...bidOrderBook, ...askOrderBook].filter((o) => o.openOrdersAddress.equals(openOrders.address) ) return openOrdersForMarket.map((order) => ({ order, market: { account: market, config: config }, })) } function parsePerpOpenOrders( market: PerpMarket, config: MarketConfig, mangoAccount: MangoAccount, accountInfos ) { const bidData = accountInfos[market.bids.toBase58()]?.data const askData = accountInfos[market.asks.toBase58()]?.data const bidOrderBook = market && bidData ? new BookSide(market.bids, market, BookSideLayout.decode(bidData)) : [] const askOrderBook = market && askData ? new BookSide(market.asks, market, BookSideLayout.decode(askData)) : [] const openOrdersForMarket = [...bidOrderBook, ...askOrderBook].filter((o) => o.owner.equals(mangoAccount.publicKey) ) const advancedOrdersForMarket = mangoAccount.advancedOrders .map((o, i) => { const pto = o.perpTrigger if (pto.isActive && pto.marketIndex == config.marketIndex) { return { ...o, orderId: i, marketIndex: pto.marketIndex, orderType: pto.orderType, side: pto.side, price: market.priceLotsToNumber(pto.price), size: market.baseLotsToNumber(pto.quantity), triggerCondition: pto.triggerCondition, triggerPrice: pto.triggerPrice.toNumber(), } } else { return undefined } }) .filter((o) => !!o) return openOrdersForMarket .concat(advancedOrdersForMarket) .map((order) => ({ order, market: { account: market, config: config }, })) } export function useOpenOrders() { const markets = useMangoStore((s) => s.selectedMangoGroup.markets) const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current) const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current) const groupConfig = useMangoStore((s) => s.selectedMangoGroup.config) const accountInfos = useMangoStore((s) => s.accountInfos) if (!mangoGroup || !mangoAccount || !accountInfos) return null const openOrders = Object.entries(markets).map(([address, market]) => { const marketConfig = getMarketByPublicKey(groupConfig, address) if (market instanceof Market) { return parseSpotOrders(market, marketConfig, mangoAccount, accountInfos) } else if (market instanceof PerpMarket) { return parsePerpOpenOrders( market, marketConfig, mangoAccount, accountInfos ) } }) return openOrders.flat() }