Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

Commit

Permalink
Merge pull request #54 from metaDAOproject/feature/order-table-ws
Browse files Browse the repository at this point in the history
User Open Orders update from websocket instead of manual fetching at page load
  • Loading branch information
R-K-H authored Mar 14, 2024
2 parents 096285a + a355f70 commit 83b9465
Show file tree
Hide file tree
Showing 11 changed files with 707 additions and 394 deletions.
13 changes: 9 additions & 4 deletions components/Markets/ConditionalMarketCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ export function ConditionalMarketCard({

const updateOrderValue = () => {
if (!Number.isNaN(amount) && !Number.isNaN(+price)) {
const _price = parseFloat((+price * amount).toString()).toFixed(2);
const formatter = new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
const _price = formatter.format(parseFloat((+price * amount).toString()));
setOrderValue(_price);
} else {
setOrderValue('0');
Expand Down Expand Up @@ -286,8 +290,9 @@ export function ConditionalMarketCard({
const relevantMint = isAskSide
? marketAccount.account.baseMint
: marketAccount.account.quoteMint;
const balanceChange = isAskSide ? amount : _orderPrice();
setBalanceByMint(relevantMint, (oldBalance) => {
const newAmount = (oldBalance.uiAmount ?? 0) - amount;
const newAmount = (oldBalance.uiAmount ?? 0) - balanceChange;
return {
...oldBalance,
amount: newAmount.toString(),
Expand All @@ -299,7 +304,7 @@ export function ConditionalMarketCard({
} finally {
setIsPlacingOrder(false);
}
}, [placeOrder, amount, isLimitOrder, isPassMarket, isAskSide]);
}, [placeOrder, amount, isLimitOrder, isPassMarket, isAskSide, price]);

const getObservableTwap = () => {
if (isPassMarket) {
Expand Down Expand Up @@ -599,7 +604,7 @@ export function ConditionalMarketCard({
<Text> </Text>
)}
<>
<Text size="xs">Total Order Value ${orderValue}</Text>
<Text size="xs">Total Order Value {orderValue}</Text>
</>
</Group>
<Grid>
Expand Down
21 changes: 13 additions & 8 deletions components/Orders/ProposalOpenOrderRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
IconPencilCancel,
IconCheck,
} from '@tabler/icons-react';
import { BN } from '@coral-xyz/anchor';
import { OpenOrdersAccountWithKey } from '@/lib/types';
import { useExplorerConfiguration } from '@/hooks/useExplorerConfiguration';
import { useOpenbookTwap } from '@/hooks/useOpenbookTwap';
Expand All @@ -35,7 +36,7 @@ export function ProposalOpenOrderRow({ order }: { order: OpenOrdersAccountWithKe
const wallet = useWallet();
const { generateExplorerLink } = useExplorerConfiguration();
const { proposal } = useProposal();
const { markets, fetchOpenOrders, cancelAndSettleOrder } = useProposalMarkets();
const { markets, cancelAndSettleOrder } = useProposalMarkets();
const { settleFundsTransactions, editOrderTransactions } = useOpenbookTwap();
const { setBalanceByMint } = useBalances();
const isBidSide = isBid(order);
Expand All @@ -61,11 +62,15 @@ export function ProposalOpenOrderRow({ order }: { order: OpenOrdersAccountWithKe
setIsCanceling(true);
const txsSent = await cancelAndSettleOrder(order, marketAccount.publicKey);
if (txsSent && txsSent.length > 0) {
const quoteLots = new BN(10 ** marketAccount.account.quoteDecimals);
const balanceChange = isBidSide
? (order.account.openOrders[0].lockedPrice / quoteLots) * 100
: balance;
const relevantMint = isBidSide
? marketAccount.account.quoteMint
: marketAccount.account.baseMint;
setBalanceByMint(relevantMint, (oldBalance) => {
const newAmount = oldBalance.uiAmount + balance.toNumber();
const newAmount = oldBalance.uiAmount + balanceChange.toNumber();
return {
...oldBalance,
amount: newAmount.toString(),
Expand All @@ -79,7 +84,7 @@ export function ProposalOpenOrderRow({ order }: { order: OpenOrdersAccountWithKe
} finally {
setIsCanceling(false);
}
}, [order, proposal, markets, wallet.publicKey, cancelAndSettleOrder, fetchOpenOrders, sender]);
}, [order, proposal, markets, wallet.publicKey, cancelAndSettleOrder, sender]);

const handleEdit = useCallback(async () => {
if (!proposal || !markets || !editingOrder) return;
Expand Down Expand Up @@ -127,7 +132,6 @@ export function ProposalOpenOrderRow({ order }: { order: OpenOrdersAccountWithKe
// };
// });
// }
await fetchOpenOrders(wallet.publicKey);
setEditingOrder(undefined);
} finally {
setIsEditing(false);
Expand All @@ -140,7 +144,6 @@ export function ProposalOpenOrderRow({ order }: { order: OpenOrdersAccountWithKe
editedSize,
editedPrice,
editOrderTransactions,
fetchOpenOrders,
sender,
]);

Expand All @@ -167,6 +170,10 @@ export function ProposalOpenOrderRow({ order }: { order: OpenOrdersAccountWithKe
}
}, [order, proposal, settleFundsTransactions]);

const price = numeral(order.account.openOrders[0].lockedPrice * QUOTE_LOTS).format(
NUMERAL_FORMAT,
);

return (
<Table.Tr key={order.publicKey.toString()}>
<Table.Td>
Expand Down Expand Up @@ -216,9 +223,7 @@ export function ProposalOpenOrderRow({ order }: { order: OpenOrdersAccountWithKe
<Input
w="5rem"
variant="filled"
defaultValue={numeral(order.account.openOrders[0].lockedPrice * QUOTE_LOTS).format(
NUMERAL_FORMAT,
)}
defaultValue={price}
onChange={(e) => setEditedPrice(Number(e.target.value))}
/>
) : (
Expand Down
8 changes: 3 additions & 5 deletions components/Orders/ProposalOpenOrdersTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import { useProposalMarkets } from '@/contexts/ProposalMarketsContext';

const headers = ['Order ID', 'Market', 'Status', 'Size', 'Price', 'Notional', 'Actions'];

export function ProposalOpenOrdersTab({ orders }: { orders: OpenOrdersAccountWithKey[]; }) {
export function ProposalOpenOrdersTab({ orders }: { orders: OpenOrdersAccountWithKey[] }) {
const { isCranking, crankMarkets, proposal } = useProposal();
const { markets, fetchOpenOrders } = useProposalMarkets();
const { markets } = useProposalMarkets();
const sender = useTransactionSender();
const wallet = useWallet();
const { cancelOrderTransactions, settleFundsTransactions } = useOpenbookTwap();
Expand Down Expand Up @@ -45,14 +45,12 @@ export function ProposalOpenOrdersTab({ orders }: { orders: OpenOrdersAccountWit
setIsCanceling(true);
// Filtered undefined already
await sender.send(txs);
// We already return above if the wallet doesn't have a public key
await fetchOpenOrders(wallet.publicKey!);
} catch (err) {
console.error(err);
} finally {
setIsCanceling(false);
}
}, [proposal, markets, wallet.publicKey, cancelOrderTransactions, fetchOpenOrders, sender]);
}, [proposal, markets, wallet.publicKey, cancelOrderTransactions, sender]);

const handleSettleAllFunds = useCallback(async () => {
if (!proposal || !markets) return;
Expand Down
53 changes: 27 additions & 26 deletions components/Orders/ProposalUnsettledOrderRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,60 +21,70 @@ import { useProposal } from '@/contexts/ProposalContext';
import { isBid, isPartiallyFilled, isPass } from '@/lib/openbook';
import { useBalances } from '../../contexts/BalancesContext';
import { useProposalMarkets } from '@/contexts/ProposalMarketsContext';
import { useOpenbook } from '@/hooks/useOpenbook';

export function ProposalUnsettledOrderRow({ order }: { order: OpenOrdersAccountWithKey }) {
const { markets, fetchOpenOrders } = useProposalMarkets();
const { markets, fetchNonOpenOrders } = useProposalMarkets();
const theme = useMantineTheme();
const sender = useTransactionSender();
const wallet = useWallet();
const { setBalanceByMint } = useBalances();
const { generateExplorerLink } = useExplorerConfiguration();
const { proposal, crankMarkets, isCranking } = useProposal();
const { settleFundsTransactions, closeOpenOrdersAccountTransactions } = useOpenbookTwap();
const { program: openbookClient } = useOpenbook();
const isBidSide = isBid(order);
const balance = isBidSide
? order.account.position.bidsBaseLots
: order.account.position.asksBaseLots;
const pass = proposal ? order.account.market.equals(proposal.account.openbookPassMarket) : null;

const [isSettling, setIsSettling] = useState<boolean>(false);
const [isClosing, setIsClosing] = useState<boolean>(false);

if (!markets || !proposal) {
return null;
}

const relevantMarket = pass ? markets.pass : markets.fail;
const marketAccount = pass
? { account: relevantMarket, publicKey: proposal.account.openbookPassMarket }
: { account: relevantMarket, publicKey: proposal.account.openbookFailMarket };
const [baseBalance, quoteBalance] = [
order.account.position.baseFreeNative.toNumber() / 10 ** relevantMarket.baseDecimals,
order.account.position.quoteFreeNative / 10 ** relevantMarket.quoteDecimals,
];

const handleSettleFunds = useCallback(async () => {
if (!proposal || !markets || !wallet?.publicKey) return;

setIsSettling(true);
try {
const pass = order.account.market.equals(proposal.account.openbookPassMarket);
const marketAccount = pass
? { account: markets.pass, publicKey: proposal.account.openbookPassMarket }
: { account: markets.fail, publicKey: proposal.account.openbookFailMarket };
const txs = await settleFundsTransactions(
order.account.accountNum,
pass,
pass ?? false,
proposal,
marketAccount,
);

if (!txs) return;

await sender.send(txs);
await fetchOpenOrders(wallet.publicKey);
const relevantMint = isBidSide
? marketAccount.account.quoteMint
: marketAccount.account.baseMint;
const [relevantMint, relevantBalance] = isBidSide
? [marketAccount.account.quoteMint, quoteBalance]
: [marketAccount.account.baseMint, baseBalance];
const balanceChange = isBidSide ? order.account.openOrders[0].lockedPrice : relevantBalance;
setBalanceByMint(relevantMint, (oldBalance) => {
const newAmount = oldBalance.uiAmount + balance.toNumber();
const newAmount = (oldBalance.uiAmount ?? 0) + balanceChange;
return {
...oldBalance,
amount: newAmount.toString(),
uiAmount: newAmount,
uiAmountString: newAmount.toString(),
};
});
await fetchNonOpenOrders(wallet.publicKey, openbookClient.program, proposal, markets);
} finally {
setIsSettling(false);
}
}, [order, proposal, settleFundsTransactions, wallet, fetchOpenOrders]);
}, [order, proposal, settleFundsTransactions, wallet]);

const handleCloseAccount = useCallback(async () => {
if (!proposal || !markets) return;
Expand All @@ -86,7 +96,6 @@ export function ProposalUnsettledOrderRow({ order }: { order: OpenOrdersAccountW
setIsClosing(true);
try {
await sender.send(txs);
fetchOpenOrders(wallet.publicKey);
} catch (err) {
console.error(err);
} finally {
Expand Down Expand Up @@ -121,16 +130,8 @@ export function ProposalUnsettledOrderRow({ order }: { order: OpenOrdersAccountW
</Table.Td>
<Table.Td>
<Stack gap={0}>
<Text>
{`${order.account.position.baseFreeNative.toNumber() / 1_000_000_000} ${
isPass(order, proposal) ? 'pMETA' : 'fMETA'
}`}
</Text>
<Text>
{`${order.account.position.quoteFreeNative / 1_000_000} ${
isPass(order, proposal) ? 'pUSDC' : 'fUSDC'
}`}
</Text>
<Text>{`${baseBalance} ${isPass(order, proposal) ? 'pMETA' : 'fMETA'}`}</Text>
<Text>{`${quoteBalance} ${isPass(order, proposal) ? 'pUSDC' : 'fUSDC'}`}</Text>
</Stack>
</Table.Td>
<Table.Td>
Expand Down
26 changes: 12 additions & 14 deletions components/Orders/ProposalUnsettledOrdersTab.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useMemo, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { Stack, Table, Button, Group, Text } from '@mantine/core';
import { Transaction } from '@solana/web3.js';
import { BN } from '@coral-xyz/anchor';
Expand All @@ -11,14 +11,16 @@ import { isClosableOrder, isPartiallyFilled } from '@/lib/openbook';
import { ProposalUnsettledOrderRow } from './ProposalUnsettledOrderRow';
import { useBalances } from '../../contexts/BalancesContext';
import { useProposalMarkets } from '@/contexts/ProposalMarketsContext';
import { useAutocrat } from '@/contexts/AutocratContext';

const headers = ['Order ID', 'Market', 'Claimable', 'Actions'];

export function ProposalUnsettledOrdersTab({ orders }: { orders: OpenOrdersAccountWithKey[] }) {
const sender = useTransactionSender();
const { openbook } = useAutocrat();
const wallet = useWallet();
const { proposal } = useProposal();
const { markets, fetchOpenOrders } = useProposalMarkets();
const { markets, fetchNonOpenOrders } = useProposalMarkets();
const { fetchBalanceByMint } = useBalances();
const { settleFundsTransactions, closeOpenOrdersAccountTransactions } = useOpenbookTwap();

Expand All @@ -31,6 +33,12 @@ export function ProposalUnsettledOrdersTab({ orders }: { orders: OpenOrdersAccou
);
const ordersToClose = useMemo(() => orders.filter((order) => isClosableOrder(order)), [orders]);

useEffect(() => {
if (wallet.publicKey) {
fetchNonOpenOrders(wallet.publicKey, openbook, proposal, markets);
}
}, [wallet.publicKey?.toString(), openbook, proposal, markets]);

const handleSettleAllFunds = useCallback(async () => {
if (!proposal || !markets || !wallet?.publicKey) return;

Expand All @@ -56,23 +64,14 @@ export function ProposalUnsettledOrdersTab({ orders }: { orders: OpenOrdersAccou

if (!txs) return;
await sender.send(txs as Transaction[]);
fetchOpenOrders(wallet.publicKey);
fetchBalanceByMint(markets.pass.baseMint);
fetchBalanceByMint(markets.pass.quoteMint);
fetchBalanceByMint(markets.fail.baseMint);
fetchBalanceByMint(markets.fail.quoteMint);
} finally {
setIsSettling(false);
}
}, [
ordersToSettle,
markets,
proposal,
sender,
settleFundsTransactions,
fetchOpenOrders,
fetchBalanceByMint,
]);
}, [ordersToSettle, markets, proposal, sender, settleFundsTransactions, fetchBalanceByMint]);

const handleCloseAllOrders = useCallback(async () => {
if (!proposal || !markets || !wallet?.publicKey) return;
Expand All @@ -93,10 +92,9 @@ export function ProposalUnsettledOrdersTab({ orders }: { orders: OpenOrdersAccou
if (!txs) return;
await sender.send(txs as Transaction[]);
} finally {
fetchOpenOrders(wallet.publicKey);
setIsClosing(false);
}
}, [ordersToClose, markets, proposal, sender, settleFundsTransactions, fetchOpenOrders]);
}, [ordersToClose, markets, proposal, sender, settleFundsTransactions]);

return (
<Stack py="md">
Expand Down
Loading

0 comments on commit 83b9465

Please sign in to comment.