diff --git a/src/components/UserInfoTable/AccountsTable.jsx b/src/components/UserInfoTable/AccountsTable.jsx
new file mode 100644
index 0000000..905e3d6
--- /dev/null
+++ b/src/components/UserInfoTable/AccountsTable.jsx
@@ -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: () => (
+
+
+
+ ),
+ },
+ ];
+ return (
+
+ );
+}
diff --git a/src/components/UserInfoTable/WalletBalancesTable.jsx b/src/components/UserInfoTable/WalletBalancesTable.jsx
new file mode 100644
index 0000000..87a028d
--- /dev/null
+++ b/src/components/UserInfoTable/WalletBalancesTable.jsx
@@ -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 (
+
+ );
+}
diff --git a/src/components/layout/DataTable.jsx b/src/components/layout/DataTable.jsx
index 2c6af8c..5532a94 100644
--- a/src/components/layout/DataTable.jsx
+++ b/src/components/layout/DataTable.jsx
@@ -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}
/>
);
diff --git a/src/pages/BalancesPage.jsx b/src/pages/BalancesPage.jsx
index 0c8327c..c186cf5 100644
--- a/src/pages/BalancesPage.jsx
+++ b/src/pages/BalancesPage.jsx
@@ -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 (
-
+
+
+
+
+
+
+
+
);
}
diff --git a/src/utils/markets.js b/src/utils/markets.js
index 4dcbb29..00b8d9f 100644
--- a/src/utils/markets.js
+++ b/src/utils/markets.js
@@ -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 },
+ );
}