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

View File

@ -1,14 +1,26 @@
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 BalancesTable from '../components/UserInfoTable/BalancesTable';
import WalletBalancesTable from '../components/UserInfoTable/WalletBalancesTable';
import AccountsTable from '../components/UserInfoTable/AccountsTable';
const { TabPane } = Tabs;
export default function BalancesPage() {
const [balances] = useBalancesForAllMarkets();
console.log(JSON.stringify(balances));
const [walletBalances, loadedWalletBalances] = useWalletBalancesForAllMarkets();
const [accountBalances, accountBalancesLoaded] = useOpenOrderAccountBalancesForAllMarkets();
return (
<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>
);
}

View File

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