Split up balances page

This commit is contained in:
Philippe Maes 2020-08-29 19:40:37 +02:00 committed by Gary Wang
parent 286eeabf71
commit 787b5b1e05
5 changed files with 229 additions and 54 deletions

View File

@ -0,0 +1,73 @@
import { Button } from 'antd';
import React from 'react';
import {
useSelectedOpenOrdersAccount,
useMarket,
useSelectedBaseCurrencyAccount,
useSelectedQuoteCurrencyAccount,
} from '../../utils/markets';
import DataTable from '../layout/DataTable';
import { useConnection } from '../../utils/connection';
import { useWallet } from '../../utils/wallet';
import { settleFunds } from '../../utils/send';
export default function AccountsTable({ accountBalances }) {
const baseCurrencyAccount = useSelectedBaseCurrencyAccount();
const quoteCurrencyAccount = useSelectedQuoteCurrencyAccount();
const connection = useConnection();
const [, wallet] = useWallet();
const openOrdersAccount = useSelectedOpenOrdersAccount(true);
const { market } = useMarket();
async function onSettleFunds() {
return await settleFunds({
market,
openOrders: openOrdersAccount,
connection,
wallet,
baseCurrencyAccount,
quoteCurrencyAccount,
});
}
const columns = [
{
title: 'Key',
dataIndex: 'key',
key: 'key',
},
{
title: 'Coin',
dataIndex: 'coin',
key: 'coin',
},
{
title: 'Orders',
dataIndex: 'orders',
key: 'orders',
},
{
title: 'Unsettled',
dataIndex: 'unsettled',
key: 'unsettled',
},
{
key: 'action',
render: () => (
<div style={{ textAlign: 'right' }}>
<Button ghost style={{ marginRight: 12 }} onClick={onSettleFunds}>
Settle
</Button>
</div>
),
},
];
return (
<DataTable
emptyLabel="No balances"
dataSource={accountBalances}
columns={columns}
pagination={false}
/>
);
}

View File

@ -0,0 +1,34 @@
import React from 'react';
import DataTable from '../layout/DataTable';
export default function WalletBalancesTable({
loaded = false,
walletBalances,
}) {
const columns = [
{
title: 'Key',
dataIndex: 'key',
key: 'key',
},
{
title: 'Coin',
dataIndex: 'coin',
key: 'coin',
},
{
title: 'Wallet Balance',
dataIndex: 'wallet',
key: 'wallet',
},
];
return (
<DataTable
emptyLabel="No balances"
dataSource={walletBalances}
columns={columns}
pagination={false}
loading={!loaded}
/>
);
}

View File

@ -6,6 +6,7 @@ export default function DataTable({
columns, columns,
emptyLabel = 'No data', emptyLabel = 'No data',
pagination = false, pagination = false,
loading = false,
pageSize = 10, pageSize = 10,
}) { }) {
const customizeRenderEmpty = () => ( const customizeRenderEmpty = () => (
@ -27,6 +28,7 @@ export default function DataTable({
dataSource={dataSource} dataSource={dataSource}
columns={columns} columns={columns}
pagination={pagination ? { pagination: true, pageSize } : false} pagination={pagination ? { pagination: true, pageSize } : false}
loading={loading}
/> />
</ConfigProvider> </ConfigProvider>
); );

View File

@ -1,14 +1,26 @@
import React from 'react'; import React from 'react';
import { useBalancesForAllMarkets } from '../utils/markets'; import { Tabs } from 'antd';
import { useWalletBalancesForAllMarkets, useOpenOrderAccountBalancesForAllMarkets } from '../utils/markets';
import FloatingElement from '../components/layout/FloatingElement'; import FloatingElement from '../components/layout/FloatingElement';
import BalancesTable from '../components/UserInfoTable/BalancesTable'; import WalletBalancesTable from '../components/UserInfoTable/WalletBalancesTable';
import AccountsTable from '../components/UserInfoTable/AccountsTable';
const { TabPane } = Tabs;
export default function BalancesPage() { export default function BalancesPage() {
const [balances] = useBalancesForAllMarkets(); const [walletBalances, loadedWalletBalances] = useWalletBalancesForAllMarkets();
console.log(JSON.stringify(balances)); const [accountBalances, accountBalancesLoaded] = useOpenOrderAccountBalancesForAllMarkets();
return ( return (
<FloatingElement style={{ flex: 1, paddingTop: 10 }}> <FloatingElement style={{ flex: 1, paddingTop: 10 }}>
<BalancesTable balances={balances} /> <Tabs defaultActiveKey="accounts">
<TabPane tab="Balances" key="balances">
<WalletBalancesTable loaded={loadedWalletBalances} walletBalances={walletBalances} />
</TabPane>
<TabPane tab="Accounts" key="accounts">
<AccountsTable loaded={accountBalancesLoaded} accountBalances={accountBalances} />
</TabPane>
</Tabs>
</FloatingElement> </FloatingElement>
); );
} }

View File

@ -592,13 +592,13 @@ export function useBalances() {
]; ];
} }
export function useBalancesForAllMarkets() { export function useWalletBalancesForAllMarkets() {
const [connected, wallet] = useWallet(); const [connected, wallet] = useWallet();
const connection = useConnection(); const connection = useConnection();
const allMarkets = useAllMarkets(); const allMarkets = useAllMarkets();
async function getBalancesForAllMarkets() { async function getWalletBalancesForAllMarkets() {
let balances = []; let balances = [];
if (!connected) { if (!connected) {
return balances; return balances;
@ -612,26 +612,32 @@ export function useBalancesForAllMarkets() {
} }
const baseCurrency = marketName.includes('/') && marketName.split('/')[0]; const baseCurrency = marketName.includes('/') && marketName.split('/')[0];
if (!balances.find((balance) => balance.coin === baseCurrency)) { if (!balances.find((balance) => balance.coin === baseCurrency)) {
const baseBalance = await getBalanceForMarket( const baseBalance = await getCurrencyBalance(
market, market,
connection, connection,
wallet, wallet,
baseCurrency,
true, true,
); );
balances.push(baseBalance); balances.push({
key: baseCurrency,
coin: baseCurrency,
wallet: baseBalance,
});
} }
const quoteCurrency = const quoteCurrency =
marketName.includes('/') && marketName.split('/')[1]; marketName.includes('/') && marketName.split('/')[1];
if (!balances.find((balance) => balance.coin === quoteCurrency)) { if (!balances.find((balance) => balance.coin === quoteCurrency)) {
const quoteBalance = await getBalanceForMarket( const quoteBalance = await getCurrencyBalance(
market, market,
connection, connection,
wallet, wallet,
quoteCurrency,
false, false,
); );
balances.push(quoteBalance); balances.push({
key: quoteCurrency,
coin: quoteCurrency,
wallet: quoteBalance,
});
} }
} }
@ -639,9 +645,9 @@ export function useBalancesForAllMarkets() {
} }
return useAsyncData( return useAsyncData(
getBalancesForAllMarkets, getWalletBalancesForAllMarkets,
tuple( tuple(
'getBalancesForAllMarkets', 'getWalletBalancesForAllMarkets',
connected, connected,
connection, connection,
wallet, wallet,
@ -651,16 +657,7 @@ export function useBalancesForAllMarkets() {
); );
} }
async function getBalanceForMarket( async function getCurrencyBalance(market, connection, wallet, base = true) {
market,
connection,
wallet,
currency,
base = true,
) {
if (!market) {
return;
}
const currencyAccounts = base const currencyAccounts = base
? await market.findBaseTokenAccountsForOwner(connection, wallet.publicKey) ? await market.findBaseTokenAccountsForOwner(connection, wallet.publicKey)
: await market.findQuoteTokenAccountsForOwner(connection, wallet.publicKey); : await market.findQuoteTokenAccountsForOwner(connection, wallet.publicKey);
@ -668,33 +665,90 @@ async function getBalanceForMarket(
const tokenAccountBalances = await connection.getTokenAccountBalance( const tokenAccountBalances = await connection.getTokenAccountBalance(
currencyAccount.pubkey, currencyAccount.pubkey,
); );
const currencyBalances = tokenAccountBalances?.value?.uiAmount; return tokenAccountBalances?.value?.uiAmount;
const openOrdersAccounts = await market.findOpenOrdersAccountsForOwner( }
connection,
wallet.publicKey, export function useOpenOrderAccountBalancesForAllMarkets() {
); const [connected, wallet] = useWallet();
const openOrdersAccount = openOrdersAccounts && openOrdersAccounts[0];
const inOrders = base const connection = useConnection();
? openOrdersAccount?.baseTokenTotal && const allMarkets = useAllMarkets();
openOrdersAccount?.baseTokenFree &&
market.baseSplSizeToNumber( async function getOpenOrderAccountsForAllMarkets() {
openOrdersAccount.baseTokenTotal.sub(openOrdersAccount.baseTokenFree), let accounts = [];
) if (!connected) {
: openOrdersAccount?.quoteTokenTotal && return accounts;
openOrdersAccount?.quoteTokenFree && }
market.quoteSplSizeToNumber(
openOrdersAccount.quoteTokenTotal.sub(openOrdersAccount.quoteTokenFree), let marketData;
); for (marketData of allMarkets) {
const unsettled = base const { market, marketName } = marketData;
? openOrdersAccount?.baseTokenFree && if (!market) {
market.baseSplSizeToNumber(openOrdersAccount.baseTokenFree) return accounts;
: openOrdersAccount?.quoteTokenFree && }
market.baseSplSizeToNumber(openOrdersAccount.baseTokenFree); const openOrderAccounts = await market.findOpenOrdersAccountsForOwner(
return { connection,
key: currency, wallet.publicKey,
coin: currency, );
wallet: currencyBalances, if (!openOrderAccounts) {
orders: inOrders, continue;
unsettled: unsettled, }
}; const baseCurrency = marketName.includes('/') && marketName.split('/')[0];
const quoteCurrency =
marketName.includes('/') && marketName.split('/')[1];
const openOrderAccountBalances = [];
openOrderAccounts.forEach((openOrdersAccount) => {
const inOrdersBase =
openOrdersAccount?.baseTokenTotal &&
openOrdersAccount?.baseTokenFree &&
market.baseSplSizeToNumber(
openOrdersAccount.baseTokenTotal.sub(
openOrdersAccount.baseTokenFree,
),
);
const inOrdersQuote =
openOrdersAccount?.quoteTokenTotal &&
openOrdersAccount?.quoteTokenFree &&
market.baseSplSizeToNumber(
openOrdersAccount.quoteTokenTotal.sub(
openOrdersAccount.quoteTokenFree,
),
);
const unsettledBase =
openOrdersAccount?.baseTokenFree &&
market.baseSplSizeToNumber(openOrdersAccount.baseTokenFree);
const unsettledQuote =
openOrdersAccount?.quoteTokenFree &&
market.baseSplSizeToNumber(openOrdersAccount.quoteTokenFree);
openOrderAccountBalances.push({
key: baseCurrency,
coin: baseCurrency,
orders: inOrdersBase,
unsettled: unsettledBase,
});
openOrderAccountBalances.push({
key: quoteCurrency,
coin: quoteCurrency,
orders: inOrdersQuote,
unsettled: unsettledQuote,
});
});
accounts = accounts.concat(openOrderAccountBalances);
}
return accounts;
}
return useAsyncData(
getOpenOrderAccountsForAllMarkets,
tuple(
'getOpenOrderAccountsForAllMarkets',
connected,
connection,
wallet,
allMarkets,
),
{ refreshInterval: _SLOW_REFRESH_INTERVAL },
);
} }