diff --git a/src/components/LinkAddress.jsx b/src/components/LinkAddress.jsx
index b273f39..ae0829c 100644
--- a/src/components/LinkAddress.jsx
+++ b/src/components/LinkAddress.jsx
@@ -11,6 +11,7 @@ export default function LinkAddress({ title, address }) {
icon={}
href={'https://explorer.solana.com/address/' + address}
target="_blank"
+ rel="noopener noreferrer"
>
{address}
diff --git a/src/components/StandaloneBalancesDisplay.jsx b/src/components/StandaloneBalancesDisplay.jsx
index 54c8188..4dc7ab9 100644
--- a/src/components/StandaloneBalancesDisplay.jsx
+++ b/src/components/StandaloneBalancesDisplay.jsx
@@ -14,6 +14,7 @@ import { useWallet } from '../utils/wallet';
import Link from './Link';
import { settleFunds } from '../utils/send';
import { useSendConnection } from '../utils/connection';
+import { notify } from '../utils/notifications';
const RowBox = styled(Row)`
padding-bottom: 20px;
@@ -45,14 +46,22 @@ export default function StandaloneBalancesDisplay() {
balances && balances.find((b) => b.coin === quoteCurrency);
async function onSettleFunds() {
- return await settleFunds({
- market,
- openOrders: openOrdersAccount,
- connection,
- wallet,
- baseCurrencyAccount,
- quoteCurrencyAccount,
- });
+ try {
+ await settleFunds({
+ market,
+ openOrders: openOrdersAccount,
+ connection,
+ wallet,
+ baseCurrencyAccount,
+ quoteCurrencyAccount,
+ });
+ } catch (e) {
+ notify({
+ message: 'Error settling funds',
+ description: e.message,
+ type: 'error',
+ });
+ }
}
return (
diff --git a/src/components/TradeForm.jsx b/src/components/TradeForm.jsx
index cf0fe77..ad6110a 100644
--- a/src/components/TradeForm.jsx
+++ b/src/components/TradeForm.jsx
@@ -167,14 +167,16 @@ export default function TradeForm({ style, setChangeOrderRef }) {
wallet,
baseCurrencyAccount: baseCurrencyAccount?.pubkey,
quoteCurrencyAccount: quoteCurrencyAccount?.pubkey,
- onConfirmCallBack: () => {
- setPrice(null);
- onSetBaseSize(null);
- },
});
+ setPrice(null);
+ onSetBaseSize(null);
} catch (e) {
console.warn(e);
- notify({ message: 'Error placing order: ' + e.message, type: 'error' });
+ notify({
+ message: 'Error placing order',
+ description: e.message,
+ type: 'error',
+ });
} finally {
setSubmitting(false);
}
diff --git a/src/components/UserInfoTable/AccountsTable.jsx b/src/components/UserInfoTable/AccountsTable.jsx
index 1751331..a140831 100644
--- a/src/components/UserInfoTable/AccountsTable.jsx
+++ b/src/components/UserInfoTable/AccountsTable.jsx
@@ -4,26 +4,35 @@ import DataTable from '../layout/DataTable';
import { useConnection } from '../../utils/connection';
import { useWallet } from '../../utils/wallet';
import { settleFunds } from '../../utils/send';
+import { notify } from '../../utils/notifications';
export default function AccountsTable({ accountBalances }) {
const connection = useConnection();
const { wallet } = useWallet();
async function onSettleFunds(account) {
- const {
- market,
- openOrdersAccount,
- baseCurrencyAccount,
- quoteCurrencyAccount,
- } = account;
- return await settleFunds({
- market,
- openOrders: openOrdersAccount,
- connection,
- wallet,
- baseCurrencyAccount,
- quoteCurrencyAccount,
- });
+ try {
+ const {
+ market,
+ openOrdersAccount,
+ baseCurrencyAccount,
+ quoteCurrencyAccount,
+ } = account;
+ return await settleFunds({
+ market,
+ openOrders: openOrdersAccount,
+ connection,
+ wallet,
+ baseCurrencyAccount,
+ quoteCurrencyAccount,
+ });
+ } catch (e) {
+ notify({
+ message: 'Error settling funds',
+ description: e.message,
+ type: 'error',
+ });
+ }
}
const columns = [
diff --git a/src/components/UserInfoTable/BalancesTable.jsx b/src/components/UserInfoTable/BalancesTable.jsx
index a65c757..0f63f81 100644
--- a/src/components/UserInfoTable/BalancesTable.jsx
+++ b/src/components/UserInfoTable/BalancesTable.jsx
@@ -8,6 +8,7 @@ import DataTable from '../layout/DataTable';
import { useSendConnection } from '../../utils/connection';
import { useWallet } from '../../utils/wallet';
import { settleFunds } from '../../utils/send';
+import { notify } from '../../utils/notifications';
export default function BalancesTable({
balances,
@@ -20,21 +21,30 @@ export default function BalancesTable({
const { wallet } = useWallet();
async function onSettleFunds(market, openOrders) {
- return await settleFunds({
- market,
- openOrders,
- connection,
- wallet,
- baseCurrencyAccount: getSelectedTokenAccountForMint(
- accounts,
- market?.baseMintAddress,
- ),
- quoteCurrencyAccount: getSelectedTokenAccountForMint(
- accounts,
- market?.quoteMintAddress,
- ),
- onSuccess: onSettleSuccess,
- });
+ try {
+ await settleFunds({
+ market,
+ openOrders,
+ connection,
+ wallet,
+ baseCurrencyAccount: getSelectedTokenAccountForMint(
+ accounts,
+ market?.baseMintAddress,
+ ),
+ quoteCurrencyAccount: getSelectedTokenAccountForMint(
+ accounts,
+ market?.quoteMintAddress,
+ ),
+ });
+ } catch (e) {
+ notify({
+ message: 'Error settling funds',
+ description: e.message,
+ type: 'error',
+ });
+ return;
+ }
+ onSettleSuccess && onSettleSuccess();
}
const columns = [
diff --git a/src/components/UserInfoTable/OpenOrderTable.jsx b/src/components/UserInfoTable/OpenOrderTable.jsx
index d49cae0..ca781f7 100644
--- a/src/components/UserInfoTable/OpenOrderTable.jsx
+++ b/src/components/UserInfoTable/OpenOrderTable.jsx
@@ -21,25 +21,25 @@ export default function OpenOrderTable({ openOrders, onCancelSuccess }) {
const [cancelId, setCancelId] = useState(null);
async function cancel(order) {
+ setCancelId(order?.orderId);
try {
await cancelOrder({
order,
market: order.market,
connection,
wallet,
- onBeforeSendCallBack: () => setCancelId(order?.orderId),
- onConfirmCallBack: () => {
- setCancelId(null);
- onCancelSuccess && onCancelSuccess();
- },
});
} catch (e) {
notify({
- message: 'Error cancelling order: ' + e.message,
+ message: 'Error cancelling order',
+ description: e.message,
type: 'error',
});
+ return;
+ } finally {
setCancelId(null);
}
+ onCancelSuccess && onCancelSuccess();
}
const columns = [
diff --git a/src/utils/notifications.js b/src/utils/notifications.js
index 91d2357..a7820eb 100644
--- a/src/utils/notifications.js
+++ b/src/utils/notifications.js
@@ -1,12 +1,25 @@
import React from 'react';
import { notification } from 'antd';
+import Link from '../components/Link';
export function notify({
message,
description,
+ txid,
type = 'info',
placement = 'bottomLeft',
}) {
+ if (txid) {
+ description = (
+
+ View transaction {txid.slice(0, 8)}...{txid.slice(txid.length - 8)}
+
+ );
+ }
notification[type]({
message: {message},
description: (
diff --git a/src/utils/send.js b/src/utils/send.js
index 2c427f7..5ea2369 100644
--- a/src/utils/send.js
+++ b/src/utils/send.js
@@ -42,7 +42,6 @@ export async function settleFunds({
wallet,
baseCurrencyAccount,
quoteCurrencyAccount,
- onSuccess,
}) {
if (
!market ||
@@ -121,32 +120,12 @@ export async function settleFunds({
? [...settleFundsSigners, createAccountSigner]
: 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({
transaction,
signers,
wallet,
connection,
- onBeforeSend,
- onAfterSend,
- onConfirm,
+ sendingMessage: 'Settling funds...',
});
}
@@ -154,15 +133,7 @@ export async function cancelOrder(params) {
return cancelOrders({ ...params, orders: [params.order] });
}
-export async function cancelOrders({
- market,
- wallet,
- connection,
- orders,
- onBeforeSendCallBack,
- onAfterSendCallBack,
- onConfirmCallBack,
-}) {
+export async function cancelOrders({ market, wallet, connection, orders }) {
const transaction = market.makeMatchOrdersTransaction(5);
orders.forEach((order) => {
transaction.add(
@@ -170,52 +141,11 @@ export async function cancelOrders({
);
});
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({
transaction,
wallet,
connection,
- onBeforeSend,
- onAfterSend,
- onConfirm,
+ sendingMessage: 'Sending cancel...',
});
}
@@ -229,9 +159,6 @@ export async function placeOrder({
wallet,
baseCurrencyAccount,
quoteCurrencyAccount,
- onBeforeSendCallBack,
- onAfterSendCallBack,
- onConfirmCallBack,
}) {
let formattedMinOrderSize =
market?.minOrderSize?.toFixed(getDecimalCount(market.minOrderSize)) ||
@@ -313,38 +240,12 @@ export async function placeOrder({
transaction.add(placeOrderTx);
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({
transaction,
wallet,
connection,
- onBeforeSend,
- onAfterSend,
- onConfirm,
signers,
+ sendingMessage: 'Sending order...',
});
}
@@ -359,9 +260,9 @@ async function sendTransaction({
wallet,
signers = [wallet.publicKey],
connection,
- onBeforeSend,
- onAfterSend,
- onConfirm,
+ sendingMessage = 'Sending transaction...',
+ sentMessage = 'Transaction sent',
+ successMessage = 'Transaction confirmed',
timeout = DEFAULT_TIMEOUT,
}) {
transaction.recentBlockhash = (
@@ -371,29 +272,36 @@ async function sendTransaction({
const rawTransaction = (
await wallet.signTransaction(transaction)
).serialize();
- let done = false;
const startTime = getUnixTs();
- onBeforeSend();
+ notify({ message: sendingMessage });
const txid = await connection.sendRawTransaction(rawTransaction, {
skipPreflight: true,
});
- onAfterSend();
- console.log('Started sending transaction for', txid);
- awaitTransactionSignatureConfirmation(txid, timeout, connection)
- .then((res) => {
- done = true;
- onConfirm(res);
- })
- .catch((res) => {
- done = true;
- onConfirm(res);
- });
- while (!done && getUnixTs() - startTime < timeout) {
- connection.sendRawTransaction(rawTransaction, {
- skipPreflight: true,
- });
- await sleep(300);
+ notify({ message: sentMessage, type: 'success', txid });
+
+ console.log('Started awaiting confirmation for', txid);
+
+ let done = false;
+ (async () => {
+ while (!done && getUnixTs() - startTime < timeout) {
+ connection.sendRawTransaction(rawTransaction, {
+ skipPreflight: true,
+ });
+ 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);
return txid;
}
@@ -421,7 +329,7 @@ async function awaitTransactionSignatureConfirmation(
console.log('WS confirmed', txid, result);
done = true;
if (result.err) {
- reject(result);
+ reject(result.err);
} else {
resolve(result);
}
@@ -434,6 +342,7 @@ async function awaitTransactionSignatureConfirmation(
console.log('WS error in setup', txid, e);
}
while (!done) {
+ // eslint-disable-next-line no-loop-func
(async () => {
try {
const signatureStatuses = await connection.getSignatureStatuses([
@@ -446,7 +355,7 @@ async function awaitTransactionSignatureConfirmation(
} else if (result.err) {
console.log('REST error for', txid, result);
done = true;
- reject(result);
+ reject(result.err);
} else if (!result.confirmations) {
console.log('REST no confirmations for', txid, result);
} else {