Add open orders page

This commit is contained in:
Nathaniel Parke 2020-10-15 18:47:53 +08:00
parent b3501b26cc
commit b48fe02510
5 changed files with 87 additions and 80 deletions

View File

@ -135,7 +135,8 @@ export default function TopBar() {
}} }}
> >
<Menu.Item key="/">TRADE</Menu.Item> <Menu.Item key="/">TRADE</Menu.Item>
<Menu.Item key="/balances">BALANCES</Menu.Item> {connected && <Menu.Item key="/balances">BALANCES</Menu.Item>}
{connected && <Menu.Item key="/orders">ORDERS</Menu.Item>}
<Menu.SubMenu title="LEARN" onTitleClick={() => window.open(EXTERNAL_LINKS['/learn'], '_blank')}> <Menu.SubMenu title="LEARN" onTitleClick={() => window.open(EXTERNAL_LINKS['/learn'], '_blank')}>
<Menu.Item key="/add-market"> <Menu.Item key="/add-market">
<a href={EXTERNAL_LINKS['/add-market']} target="_blank" rel="noopener noreferrer"> <a href={EXTERNAL_LINKS['/add-market']} target="_blank" rel="noopener noreferrer">

View File

@ -1,20 +1,27 @@
import React, { useState } from 'react'; import React, {useState} from 'react';
import DataTable from '../layout/DataTable'; import DataTable from '../layout/DataTable';
import styled from 'styled-components'; import styled from 'styled-components';
import { Button, Row, Col, Tag } from 'antd'; import {Button, Col, Row, Tag} from 'antd';
import { cancelOrder } from '../../utils/send'; import {cancelOrder} from '../../utils/send';
import { useWallet } from '../../utils/wallet'; import {useWallet} from '../../utils/wallet';
import { useSendConnection } from '../../utils/connection'; import {useSendConnection} from '../../utils/connection';
import { notify } from '../../utils/notifications'; import {notify} from '../../utils/notifications';
import { DeleteOutlined } from '@ant-design/icons'; import {DeleteOutlined} from '@ant-design/icons';
import {OrderWithMarketAndMarketName} from "../../utils/types";
const CancelButton = styled(Button)` const CancelButton = styled(Button)`
color: #f23b69; color: #f23b69;
border: 1px solid #f23b69; border: 1px solid #f23b69;
`; `;
export default function OpenOrderTable({ openOrders, onCancelSuccess }) { export default function OpenOrderTable({ openOrders, onCancelSuccess, pageSize, loading, marketFilter } : {
openOrders: OrderWithMarketAndMarketName[] | null | undefined;
onCancelSuccess?: () => void;
pageSize?: number;
loading?: boolean;
marketFilter?: boolean;
}) {
let { wallet } = useWallet(); let { wallet } = useWallet();
let connection = useSendConnection(); let connection = useSendConnection();
@ -42,11 +49,17 @@ export default function OpenOrderTable({ openOrders, onCancelSuccess }) {
onCancelSuccess && onCancelSuccess(); onCancelSuccess && onCancelSuccess();
} }
const marketFilters = [
...new Set((openOrders || []).map(orderInfos => orderInfos.marketName))
].map(marketName => {return {text: marketName, value: marketName}});
const columns = [ const columns = [
{ {
title: 'Market', title: 'Market',
dataIndex: 'marketName', dataIndex: 'marketName',
key: 'marketName', key: 'marketName',
filters: (marketFilter ? marketFilters : undefined),
onFilter: (value, record) => record.marketName.indexOf(value) === 0,
}, },
{ {
title: 'Side', title: 'Side',
@ -60,16 +73,27 @@ export default function OpenOrderTable({ openOrders, onCancelSuccess }) {
{side.charAt(0).toUpperCase() + side.slice(1)} {side.charAt(0).toUpperCase() + side.slice(1)}
</Tag> </Tag>
), ),
sorter: (a, b) => {
if (a.side === b.side) {
return 0.
} else if (a.side === 'buy') {
return 1.
} else {
return -1.
}
},
}, },
{ {
title: 'Size', title: 'Size',
dataIndex: 'size', dataIndex: 'size',
key: 'size', key: 'size',
sorter: (a, b) => b.size - a.size,
}, },
{ {
title: 'Price', title: 'Price',
dataIndex: 'price', dataIndex: 'price',
key: 'price', key: 'price',
sorter: (a, b) => b.price - a.price,
}, },
{ {
key: 'orderId', key: 'orderId',
@ -98,7 +122,8 @@ export default function OpenOrderTable({ openOrders, onCancelSuccess }) {
dataSource={dataSource} dataSource={dataSource}
columns={columns} columns={columns}
pagination={true} pagination={true}
pageSize={5} pageSize={pageSize ? pageSize : 5}
loading={loading !== undefined && loading}
/> />
</Col> </Col>
</Row> </Row>

View File

@ -1,10 +0,0 @@
import React from 'react';
import FloatingElement from '../components/layout/FloatingElement';
export default function OpenOrdersPage() {
return (
<FloatingElement style={{ flex: 1, paddingTop: 10 }}>
{/*<OpenOrderTable openOrders={openOrders} />*/}
</FloatingElement>
);
}

View File

@ -0,0 +1,45 @@
import React from 'react';
import FloatingElement from '../components/layout/FloatingElement';
import {getMarketInfos, useAllMarkets, useAllOpenOrders, useMarket} from "../utils/markets";
import OpenOrderTable from "../components/UserInfoTable/OpenOrderTable";
import {Button} from "antd";
import {OrderWithMarketAndMarketName} from "../utils/types";
export default function OpenOrdersPage() {
const {openOrders, loaded, refreshOpenOrders} = useAllOpenOrders();
let {customMarkets} = useMarket();
let marketInfos = getMarketInfos(customMarkets);
let marketAddressesToNames = Object.fromEntries(marketInfos.map(info => [info.address.toBase58(), info.name]));
let [allMarkets] = useAllMarkets(customMarkets);
const marketsByAddress = Object.fromEntries((allMarkets || []).map(
marketInfo => [marketInfo.market.address.toBase58(), marketInfo.market]
));
const dataSource: OrderWithMarketAndMarketName[] = (openOrders || []).map((orderInfos) =>
orderInfos.orders.map(order => {
return {
marketName: marketAddressesToNames[orderInfos.marketAddress],
market: marketsByAddress[orderInfos.marketAddress],
...order
};
})
).flat();
return (
<FloatingElement style={{ flex: 1, paddingTop: 10 }}>
<Button
onClick={refreshOpenOrders}
loading={!loaded}
>
Refresh
</Button>
<OpenOrderTable
openOrders={dataSource}
pageSize={25}
loading={!loaded}
onCancelSuccess={refreshOpenOrders}
marketFilter
/>
</FloatingElement>
);
}

View File

@ -30,6 +30,7 @@ import {
Trade, Trade,
} from "./types"; } from "./types";
import {WRAPPED_SOL_MINT} from "@project-serum/serum/lib/token-instructions"; import {WRAPPED_SOL_MINT} from "@project-serum/serum/lib/token-instructions";
import {Order} from "@project-serum/serum/lib/market";
// Used in debugging, should be false in production // Used in debugging, should be false in production
const _IGNORE_DEPRECATED = false; const _IGNORE_DEPRECATED = false;
@ -607,65 +608,6 @@ export function useFillsForAllMarkets(limit = 100) {
); );
} }
// TODO: Update to use websocket
export function useOpenOrdersForAllMarketsOld() {
return [[], true]
// const { connected, wallet } = useWallet();
//
// const connection = useConnection();
// // todo: use custom markets
// const allMarkets: {market: Market; marketName: string; programId: PublicKey;}[] = useAllMarkets([]);
//
// async function getOpenOrdersForAllMarkets() {
// let orders: OrderWithMarket[] = [];
// if (!connected) {
// return orders;
// }
//
// let marketData: {market: Market; marketName: string; programId: PublicKey;};
// for (marketData of allMarkets) {
// const { market, marketName } = marketData;
// if (!market) {
// return orders;
// }
// const openOrdersAccounts = await market.findOpenOrdersAccountsForOwner(
// connection,
// wallet.publicKey,
// );
// const openOrdersAccount = openOrdersAccounts && openOrdersAccounts[0];
// if (!openOrdersAccount) {
// return orders;
// }
// const [bids, asks] = await Promise.all([
// market.loadBids(connection),
// market.loadAsks(connection),
// ]);
// const ordersForMarket = [...bids, ...asks]
// .filter((order) => {
// return order.openOrdersAddress.equals(openOrdersAccount.publicKey);
// })
// .map((order) => {
// return { ...order, marketName };
// });
// orders = orders.concat(ordersForMarket);
// }
//
// return orders;
// }
//
// return useAsyncData(
// getOpenOrdersForAllMarkets,
// tuple(
// 'getOpenOrdersForAllMarkets',
// connected,
// connection,
// wallet,
// allMarkets,
// ),
// { refreshInterval: _SLOW_REFRESH_INTERVAL },
// );
}
export function useAllOpenOrdersAccounts() { export function useAllOpenOrdersAccounts() {
const {wallet, connected} = useWallet(); const {wallet, connected} = useWallet();
const connection = useConnection(); const connection = useConnection();
@ -755,7 +697,11 @@ export function useAllOpenOrdersBalances() {
return openOrdersBalances return openOrdersBalances
} }
export function useAllOpenOrders() { export function useAllOpenOrders(): {
openOrders: { orders: Order[]; marketAddress: string; }[] | null | undefined;
loaded: boolean,
refreshOpenOrders: () => void,
} {
const connection = useConnection(); const connection = useConnection();
const { connected } = useWallet(); const { connected } = useWallet();
const [openOrdersAccounts, openOrdersAccountsConnected] = useAllOpenOrdersAccounts(); const [openOrdersAccounts, openOrdersAccountsConnected] = useAllOpenOrdersAccounts();