orders and balances pages

This commit is contained in:
Philippe Maes 2020-08-29 16:06:57 +02:00 committed by Gary Wang
parent 7e26c63ec3
commit d980ce7e05
8 changed files with 207 additions and 61 deletions

View File

@ -1,10 +1,11 @@
import { UserOutlined, InfoCircleOutlined } from '@ant-design/icons';
import { Button, Select, Popover } from 'antd';
import React from 'react';
import { InfoCircleOutlined, UserOutlined } from '@ant-design/icons';
import { Button, Menu, Popover, Select } from 'antd';
import React, { useCallback, useEffect, useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import logo from '../assets/logo.svg';
import styled from 'styled-components';
import { useWallet, WALLET_PROVIDERS } from '../utils/wallet';
import { useConnectionConfig, ENDPOINTS } from '../utils/connection';
import { ENDPOINTS, useConnectionConfig } from '../utils/connection';
import LinkAddress from './LinkAddress';
const Wrapper = styled.div`
@ -27,11 +28,26 @@ const LogoWrapper = styled.div`
`;
export default function TopBar() {
const [current, setCurrent] = useState('/');
const [connected, wallet, providerUrl, setProvider] = useWallet();
const { endpoint, setEndpoint } = useConnectionConfig();
const location = useLocation();
const history = useHistory();
const publicKey = wallet?.publicKey?.toBase58();
const handleClick = useCallback((e) => {
history.push(e.key);
}, []);
useEffect(() => {
if (location.pathname.includes('/orders')) {
setCurrent('/orders');
} else if (location.pathname.includes('/balances')) {
setCurrent('/balances');
}
}, [location]);
return (
<Wrapper>
<div>
@ -40,6 +56,22 @@ export default function TopBar() {
{'SERUM'}
</LogoWrapper>
</div>
<Menu
mode="horizontal"
onClick={handleClick}
selectedKeys={[current]}
style={{
borderBottom: 'none',
backgroundColor: 'transparent',
display: 'flex',
alignItems: 'flex-end',
flex: 1,
}}
>
<Menu.Item key="/">TRADE</Menu.Item>
<Menu.Item key="/orders">ORDERS</Menu.Item>
<Menu.Item key="/balances">BALANCES</Menu.Item>
</Menu>
<div style={{ display: 'block' }}>
<Select
onSelect={setEndpoint}

View File

@ -1,8 +1,6 @@
import { Button } from 'antd';
import React from 'react';
import {
useBaseCurrencyBalances,
useQuoteCurrencyBalances,
useSelectedOpenOrdersAccount,
useMarket,
useSelectedBaseCurrencyAccount,
@ -13,59 +11,13 @@ import { useConnection } from '../../utils/connection';
import { useWallet } from '../../utils/wallet';
import { settleFunds } from '../../utils/send';
export default function BalancesTable() {
const [baseCurrencyBalances] = useBaseCurrencyBalances();
const [quoteCurrencyBalances] = useQuoteCurrencyBalances();
export default function BalancesTable({ balances }) {
const baseCurrencyAccount = useSelectedBaseCurrencyAccount();
const quoteCurrencyAccount = useSelectedQuoteCurrencyAccount();
const connection = useConnection();
const [, wallet] = useWallet();
const openOrdersAccount = useSelectedOpenOrdersAccount(true);
const { baseCurrency, quoteCurrency, market } = useMarket();
const baseExists =
openOrdersAccount &&
openOrdersAccount.baseTokenTotal &&
openOrdersAccount.baseTokenFree;
const quoteExists =
openOrdersAccount &&
openOrdersAccount.quoteTokenTotal &&
openOrdersAccount.quoteTokenFree;
const dataSource = [
{
key: baseCurrency,
coin: baseCurrency,
wallet: baseCurrencyBalances,
orders:
baseExists && market
? market.baseSplSizeToNumber(
openOrdersAccount.baseTokenTotal.sub(
openOrdersAccount.baseTokenFree,
),
)
: null,
unsettled:
baseExists && market
? market.baseSplSizeToNumber(openOrdersAccount.baseTokenFree)
: null,
},
{
key: quoteCurrency,
coin: quoteCurrency,
wallet: quoteCurrencyBalances,
orders:
quoteExists && market
? market.quoteSplSizeToNumber(
openOrdersAccount.quoteTokenTotal.sub(
openOrdersAccount.quoteTokenFree,
),
)
: null,
unsettled:
quoteExists && market
? market.quoteSplSizeToNumber(openOrdersAccount.quoteTokenFree)
: null,
},
];
const { market } = useMarket();
async function onSettleFunds() {
return await settleFunds({
@ -113,7 +65,7 @@ export default function BalancesTable() {
return (
<DataTable
emptyLabel="No balances"
dataSource={dataSource}
dataSource={balances}
columns={columns}
pagination={false}
/>

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { useMarket, useOpenOrders } from '../../utils/markets';
import { useMarket } from '../../utils/markets';
import DataTable from '../layout/DataTable';
import styled from 'styled-components';
@ -15,15 +15,13 @@ const CancelButton = styled(Button)`
border: 1px solid #f23b69;
`;
export default function OpenOrderTable() {
export default function OpenOrderTable({ openOrders }) {
let { market } = useMarket();
let [, wallet] = useWallet();
let connection = useConnection();
const [cancelId, setCancelId] = useState(null);
const openOrders = useOpenOrders();
async function cancel(order) {
try {
await cancelOrder({

View File

@ -4,6 +4,7 @@ import React from 'react';
import { Tabs } from 'antd';
import FillsTable from './FillsTable';
import FloatingElement from '../layout/FloatingElement';
import { useOpenOrders, useBalances } from '../../utils/markets';
const { TabPane } = Tabs;
@ -12,15 +13,27 @@ export default function Index() {
<FloatingElement style={{ flex: 1, paddingTop: 10 }}>
<Tabs defaultActiveKey="orders">
<TabPane tab="Open Orders" key="orders">
<OpenOrderTable />
<OpenOrdersTab />
</TabPane>
<TabPane tab="Trade History" key="fills">
<FillsTable />
</TabPane>
<TabPane tab="Balances" key="balances">
<BalancesTable />
<BalancesTab />
</TabPane>
</Tabs>
</FloatingElement>
);
}
const OpenOrdersTab = () => {
const openOrders = useOpenOrders();
return <OpenOrderTable openOrders={openOrders} />;
};
const BalancesTab = () => {
const balances = useBalances();
return <BalancesTable balances={balances} />;
};

View File

@ -0,0 +1,13 @@
import React from 'react';
import { useBalances } from '../utils/markets';
import FloatingElement from '../components/layout/FloatingElement';
import BalancesTable from '../components/UserInfoTable/BalancesTable';
export default function BalancesPage() {
const balances = useBalances();
return (
<FloatingElement style={{ flex: 1, paddingTop: 10 }}>
<BalancesTable balances={balances} />
</FloatingElement>
);
}

View File

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

74
src/routes.js Normal file
View File

@ -0,0 +1,74 @@
import { HashRouter, Route } from 'react-router-dom';
import TradePage from './pages/TradePage';
import OpenOrdersPage from './pages/OpenOrdersPage';
import React from 'react';
import { Layout } from 'antd';
import TopBar from './components/TopBar';
import CustomFooter from './components/Footer';
import BalancesPage from './pages/BalancesPage';
const { Header, Content } = Layout;
export function Routes() {
return (
<HashRouter basename={'/'}>
<Route exact path="/" component={TradePageContents} />
<Route exact path="/orders" component={OpenOrdersPageContents} />
<Route exact path="/balances" component={BalancesPageContents} />
</HashRouter>
);
}
function TradePageContents() {
return (
<React.Fragment>
<Layout
style={{ display: 'flex', minHeight: '100vh', flexDirection: 'column' }}
>
<Header style={{ padding: 0 }}>
<TopBar />
</Header>
<Content style={{ flex: 1 }}>
<TradePage />
</Content>
<CustomFooter />
</Layout>
</React.Fragment>
);
}
function OpenOrdersPageContents() {
return (
<React.Fragment>
<Layout
style={{ display: 'flex', minHeight: '100vh', flexDirection: 'column' }}
>
<Header style={{ padding: 0 }}>
<TopBar />
</Header>
<Content style={{ flex: 1 }}>
<OpenOrdersPage />
</Content>
<CustomFooter />
</Layout>
</React.Fragment>
);
}
function BalancesPageContents() {
return (
<React.Fragment>
<Layout
style={{ display: 'flex', minHeight: '100vh', flexDirection: 'column' }}
>
<Header style={{ padding: 0 }}>
<TopBar />
</Header>
<Content style={{ flex: 1 }}>
<BalancesPage />
</Content>
<CustomFooter />
</Layout>
</React.Fragment>
);
}

View File

@ -524,3 +524,54 @@ export function useOpenOrdersForAllMarkets() {
{ refreshInterval: _SLOW_REFRESH_INTERVAL },
);
}
export function useBalances() {
const [baseCurrencyBalances] = useBaseCurrencyBalances();
const [quoteCurrencyBalances] = useQuoteCurrencyBalances();
const openOrdersAccount = useSelectedOpenOrdersAccount(true);
const { baseCurrency, quoteCurrency, market } = useMarket();
const baseExists =
openOrdersAccount &&
openOrdersAccount.baseTokenTotal &&
openOrdersAccount.baseTokenFree;
const quoteExists =
openOrdersAccount &&
openOrdersAccount.quoteTokenTotal &&
openOrdersAccount.quoteTokenFree;
return [
{
key: baseCurrency,
coin: baseCurrency,
wallet: baseCurrencyBalances,
orders:
baseExists && market
? market.baseSplSizeToNumber(
openOrdersAccount.baseTokenTotal.sub(
openOrdersAccount.baseTokenFree,
),
)
: null,
unsettled:
baseExists && market
? market.baseSplSizeToNumber(openOrdersAccount.baseTokenFree)
: null,
},
{
key: quoteCurrency,
coin: quoteCurrency,
wallet: quoteCurrencyBalances,
orders:
quoteExists && market
? market.quoteSplSizeToNumber(
openOrdersAccount.quoteTokenTotal.sub(
openOrdersAccount.quoteTokenFree,
),
)
: null,
unsettled:
quoteExists && market
? market.quoteSplSizeToNumber(openOrdersAccount.quoteTokenFree)
: null,
},
];
}