Show transaction IDs, remove duplicate code

This commit is contained in:
Gary Wang 2020-09-27 22:03:12 -07:00
parent 6794d5494e
commit ce57e3c1e1
8 changed files with 127 additions and 174 deletions

View File

@ -11,6 +11,7 @@ export default function LinkAddress({ title, address }) {
icon={<LinkOutlined />} icon={<LinkOutlined />}
href={'https://explorer.solana.com/address/' + address} href={'https://explorer.solana.com/address/' + address}
target="_blank" target="_blank"
rel="noopener noreferrer"
> >
{address} {address}
</Button> </Button>

View File

@ -14,6 +14,7 @@ import { useWallet } from '../utils/wallet';
import Link from './Link'; import Link from './Link';
import { settleFunds } from '../utils/send'; import { settleFunds } from '../utils/send';
import { useSendConnection } from '../utils/connection'; import { useSendConnection } from '../utils/connection';
import { notify } from '../utils/notifications';
const RowBox = styled(Row)` const RowBox = styled(Row)`
padding-bottom: 20px; padding-bottom: 20px;
@ -45,7 +46,8 @@ export default function StandaloneBalancesDisplay() {
balances && balances.find((b) => b.coin === quoteCurrency); balances && balances.find((b) => b.coin === quoteCurrency);
async function onSettleFunds() { async function onSettleFunds() {
return await settleFunds({ try {
await settleFunds({
market, market,
openOrders: openOrdersAccount, openOrders: openOrdersAccount,
connection, connection,
@ -53,6 +55,13 @@ export default function StandaloneBalancesDisplay() {
baseCurrencyAccount, baseCurrencyAccount,
quoteCurrencyAccount, quoteCurrencyAccount,
}); });
} catch (e) {
notify({
message: 'Error settling funds',
description: e.message,
type: 'error',
});
}
} }
return ( return (

View File

@ -167,14 +167,16 @@ export default function TradeForm({ style, setChangeOrderRef }) {
wallet, wallet,
baseCurrencyAccount: baseCurrencyAccount?.pubkey, baseCurrencyAccount: baseCurrencyAccount?.pubkey,
quoteCurrencyAccount: quoteCurrencyAccount?.pubkey, quoteCurrencyAccount: quoteCurrencyAccount?.pubkey,
onConfirmCallBack: () => { });
setPrice(null); setPrice(null);
onSetBaseSize(null); onSetBaseSize(null);
},
});
} catch (e) { } catch (e) {
console.warn(e); console.warn(e);
notify({ message: 'Error placing order: ' + e.message, type: 'error' }); notify({
message: 'Error placing order',
description: e.message,
type: 'error',
});
} finally { } finally {
setSubmitting(false); setSubmitting(false);
} }

View File

@ -4,12 +4,14 @@ import DataTable from '../layout/DataTable';
import { useConnection } from '../../utils/connection'; import { useConnection } from '../../utils/connection';
import { useWallet } from '../../utils/wallet'; import { useWallet } from '../../utils/wallet';
import { settleFunds } from '../../utils/send'; import { settleFunds } from '../../utils/send';
import { notify } from '../../utils/notifications';
export default function AccountsTable({ accountBalances }) { export default function AccountsTable({ accountBalances }) {
const connection = useConnection(); const connection = useConnection();
const { wallet } = useWallet(); const { wallet } = useWallet();
async function onSettleFunds(account) { async function onSettleFunds(account) {
try {
const { const {
market, market,
openOrdersAccount, openOrdersAccount,
@ -24,6 +26,13 @@ export default function AccountsTable({ accountBalances }) {
baseCurrencyAccount, baseCurrencyAccount,
quoteCurrencyAccount, quoteCurrencyAccount,
}); });
} catch (e) {
notify({
message: 'Error settling funds',
description: e.message,
type: 'error',
});
}
} }
const columns = [ const columns = [

View File

@ -8,6 +8,7 @@ import DataTable from '../layout/DataTable';
import { useSendConnection } from '../../utils/connection'; import { useSendConnection } from '../../utils/connection';
import { useWallet } from '../../utils/wallet'; import { useWallet } from '../../utils/wallet';
import { settleFunds } from '../../utils/send'; import { settleFunds } from '../../utils/send';
import { notify } from '../../utils/notifications';
export default function BalancesTable({ export default function BalancesTable({
balances, balances,
@ -20,7 +21,8 @@ export default function BalancesTable({
const { wallet } = useWallet(); const { wallet } = useWallet();
async function onSettleFunds(market, openOrders) { async function onSettleFunds(market, openOrders) {
return await settleFunds({ try {
await settleFunds({
market, market,
openOrders, openOrders,
connection, connection,
@ -33,8 +35,16 @@ export default function BalancesTable({
accounts, accounts,
market?.quoteMintAddress, market?.quoteMintAddress,
), ),
onSuccess: onSettleSuccess,
}); });
} catch (e) {
notify({
message: 'Error settling funds',
description: e.message,
type: 'error',
});
return;
}
onSettleSuccess && onSettleSuccess();
} }
const columns = [ const columns = [

View File

@ -21,25 +21,25 @@ export default function OpenOrderTable({ openOrders, onCancelSuccess }) {
const [cancelId, setCancelId] = useState(null); const [cancelId, setCancelId] = useState(null);
async function cancel(order) { async function cancel(order) {
setCancelId(order?.orderId);
try { try {
await cancelOrder({ await cancelOrder({
order, order,
market: order.market, market: order.market,
connection, connection,
wallet, wallet,
onBeforeSendCallBack: () => setCancelId(order?.orderId),
onConfirmCallBack: () => {
setCancelId(null);
onCancelSuccess && onCancelSuccess();
},
}); });
} catch (e) { } catch (e) {
notify({ notify({
message: 'Error cancelling order: ' + e.message, message: 'Error cancelling order',
description: e.message,
type: 'error', type: 'error',
}); });
return;
} finally {
setCancelId(null); setCancelId(null);
} }
onCancelSuccess && onCancelSuccess();
} }
const columns = [ const columns = [

View File

@ -1,12 +1,25 @@
import React from 'react'; import React from 'react';
import { notification } from 'antd'; import { notification } from 'antd';
import Link from '../components/Link';
export function notify({ export function notify({
message, message,
description, description,
txid,
type = 'info', type = 'info',
placement = 'bottomLeft', placement = 'bottomLeft',
}) { }) {
if (txid) {
description = (
<Link
external
to={'https://explorer.solana.com/tx/' + txid}
style={{ color: '#0000ff' }}
>
View transaction {txid.slice(0, 8)}...{txid.slice(txid.length - 8)}
</Link>
);
}
notification[type]({ notification[type]({
message: <span style={{ color: 'black' }}>{message}</span>, message: <span style={{ color: 'black' }}>{message}</span>,
description: ( description: (

View File

@ -42,7 +42,6 @@ export async function settleFunds({
wallet, wallet,
baseCurrencyAccount, baseCurrencyAccount,
quoteCurrencyAccount, quoteCurrencyAccount,
onSuccess,
}) { }) {
if ( if (
!market || !market ||
@ -121,32 +120,12 @@ export async function settleFunds({
? [...settleFundsSigners, createAccountSigner] ? [...settleFundsSigners, createAccountSigner]
: settleFundsSigners; : settleFundsSigners;
const onConfirm = (result) => {
if (result.timeout) {
notify({
message: 'Timed out',
type: 'error',
description: 'Timed out awaiting confirmation on transaction',
});
} else if (result.err) {
console.log(result.err);
notify({ message: 'Error settling funds', type: 'error' });
} else {
notify({ message: 'Fund settlement confirmed', type: 'success' });
onSuccess && onSuccess();
}
};
const onBeforeSend = () => notify({ message: 'Settling funds...' });
const onAfterSend = () =>
notify({ message: 'Funds settled', type: 'success' });
return await sendTransaction({ return await sendTransaction({
transaction, transaction,
signers, signers,
wallet, wallet,
connection, connection,
onBeforeSend, sendingMessage: 'Settling funds...',
onAfterSend,
onConfirm,
}); });
} }
@ -154,15 +133,7 @@ export async function cancelOrder(params) {
return cancelOrders({ ...params, orders: [params.order] }); return cancelOrders({ ...params, orders: [params.order] });
} }
export async function cancelOrders({ export async function cancelOrders({ market, wallet, connection, orders }) {
market,
wallet,
connection,
orders,
onBeforeSendCallBack,
onAfterSendCallBack,
onConfirmCallBack,
}) {
const transaction = market.makeMatchOrdersTransaction(5); const transaction = market.makeMatchOrdersTransaction(5);
orders.forEach((order) => { orders.forEach((order) => {
transaction.add( transaction.add(
@ -170,52 +141,11 @@ export async function cancelOrders({
); );
}); });
transaction.add(market.makeMatchOrdersTransaction(5)); transaction.add(market.makeMatchOrdersTransaction(5));
const onConfirm = (result) => {
if (result.timeout) {
notify({
message: 'Timed out',
type: 'error',
description: 'Timed out awaiting confirmation on transaction',
});
} else if (result.err) {
console.log(result.err);
notify({
message:
orders.length > 1
? 'Error cancelling orders'
: 'Error cancelling order',
type: 'error',
});
} else {
notify({
message:
orders.length > 1
? 'Order cancellations confirmed'
: 'Order cancellation confirmed',
type: 'success',
});
}
onConfirmCallBack && onConfirmCallBack();
};
const onBeforeSend = () => {
notify({ message: 'Sending cancel...' });
onBeforeSendCallBack && onBeforeSendCallBack();
};
const onAfterSend = () => {
notify({
message: orders.length > 1 ? 'Orders cancelled' : 'Order cancelled',
type: 'success',
});
onAfterSendCallBack && onAfterSendCallBack();
};
return await sendTransaction({ return await sendTransaction({
transaction, transaction,
wallet, wallet,
connection, connection,
onBeforeSend, sendingMessage: 'Sending cancel...',
onAfterSend,
onConfirm,
}); });
} }
@ -229,9 +159,6 @@ export async function placeOrder({
wallet, wallet,
baseCurrencyAccount, baseCurrencyAccount,
quoteCurrencyAccount, quoteCurrencyAccount,
onBeforeSendCallBack,
onAfterSendCallBack,
onConfirmCallBack,
}) { }) {
let formattedMinOrderSize = let formattedMinOrderSize =
market?.minOrderSize?.toFixed(getDecimalCount(market.minOrderSize)) || market?.minOrderSize?.toFixed(getDecimalCount(market.minOrderSize)) ||
@ -313,38 +240,12 @@ export async function placeOrder({
transaction.add(placeOrderTx); transaction.add(placeOrderTx);
transaction.add(market.makeMatchOrdersTransaction(5)); transaction.add(market.makeMatchOrdersTransaction(5));
const onConfirm = (result) => {
if (result.timeout) {
notify({
message: 'Timed out',
type: 'error',
description: 'Timed out awaiting confirmation on transaction',
});
} else if (result.err) {
console.log(result.err);
notify({ message: 'Error placing order', type: 'error' });
} else {
notify({ message: 'Order confirmed', type: 'success' });
}
onConfirmCallBack && onConfirmCallBack();
};
const onBeforeSend = () => {
notify({ message: 'Sending order...' });
onBeforeSendCallBack && onBeforeSendCallBack();
};
const onAfterSend = () => {
notify({ message: 'Order sent', type: 'success' });
onAfterSendCallBack && onAfterSendCallBack();
};
return await sendTransaction({ return await sendTransaction({
transaction, transaction,
wallet, wallet,
connection, connection,
onBeforeSend,
onAfterSend,
onConfirm,
signers, signers,
sendingMessage: 'Sending order...',
}); });
} }
@ -359,9 +260,9 @@ async function sendTransaction({
wallet, wallet,
signers = [wallet.publicKey], signers = [wallet.publicKey],
connection, connection,
onBeforeSend, sendingMessage = 'Sending transaction...',
onAfterSend, sentMessage = 'Transaction sent',
onConfirm, successMessage = 'Transaction confirmed',
timeout = DEFAULT_TIMEOUT, timeout = DEFAULT_TIMEOUT,
}) { }) {
transaction.recentBlockhash = ( transaction.recentBlockhash = (
@ -371,29 +272,36 @@ async function sendTransaction({
const rawTransaction = ( const rawTransaction = (
await wallet.signTransaction(transaction) await wallet.signTransaction(transaction)
).serialize(); ).serialize();
let done = false;
const startTime = getUnixTs(); const startTime = getUnixTs();
onBeforeSend(); notify({ message: sendingMessage });
const txid = await connection.sendRawTransaction(rawTransaction, { const txid = await connection.sendRawTransaction(rawTransaction, {
skipPreflight: true, skipPreflight: true,
}); });
onAfterSend(); notify({ message: sentMessage, type: 'success', txid });
console.log('Started sending transaction for', txid);
awaitTransactionSignatureConfirmation(txid, timeout, connection) console.log('Started awaiting confirmation for', txid);
.then((res) => {
done = true; let done = false;
onConfirm(res); (async () => {
})
.catch((res) => {
done = true;
onConfirm(res);
});
while (!done && getUnixTs() - startTime < timeout) { while (!done && getUnixTs() - startTime < timeout) {
connection.sendRawTransaction(rawTransaction, { connection.sendRawTransaction(rawTransaction, {
skipPreflight: true, skipPreflight: true,
}); });
await sleep(300); await sleep(300);
} }
})();
try {
await awaitTransactionSignatureConfirmation(txid, timeout, connection);
} catch (err) {
if (err.timeout) {
throw new Error('Timed out awaiting confirmation on transaction');
}
throw new Error('Transaction failed');
} finally {
done = true;
}
notify({ message: successMessage, type: 'success', txid });
console.log('Latency', txid, getUnixTs() - startTime); console.log('Latency', txid, getUnixTs() - startTime);
return txid; return txid;
} }
@ -421,7 +329,7 @@ async function awaitTransactionSignatureConfirmation(
console.log('WS confirmed', txid, result); console.log('WS confirmed', txid, result);
done = true; done = true;
if (result.err) { if (result.err) {
reject(result); reject(result.err);
} else { } else {
resolve(result); resolve(result);
} }
@ -434,6 +342,7 @@ async function awaitTransactionSignatureConfirmation(
console.log('WS error in setup', txid, e); console.log('WS error in setup', txid, e);
} }
while (!done) { while (!done) {
// eslint-disable-next-line no-loop-func
(async () => { (async () => {
try { try {
const signatureStatuses = await connection.getSignatureStatuses([ const signatureStatuses = await connection.getSignatureStatuses([
@ -446,7 +355,7 @@ async function awaitTransactionSignatureConfirmation(
} else if (result.err) { } else if (result.err) {
console.log('REST error for', txid, result); console.log('REST error for', txid, result);
done = true; done = true;
reject(result); reject(result.err);
} else if (!result.confirmations) { } else if (!result.confirmations) {
console.log('REST no confirmations for', txid, result); console.log('REST no confirmations for', txid, result);
} else { } else {