From 3f21f90f7766f579ffc3e9e2e952be88069d017c Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Thu, 10 Dec 2020 04:10:13 +0800 Subject: [PATCH] Fetch logs with simulateTransaction when transactions fail --- package.json | 2 +- src/pages/ListNewMarketPage.jsx | 3 +- src/pages/pools/NewPoolPage.tsx | 5 +- src/pages/pools/PoolPage/PoolAdminPanel.tsx | 9 ++-- .../pools/PoolPage/PoolCreateRedeemPanel.tsx | 4 +- src/utils/send.tsx | 48 +++++++++++++++++++ 6 files changed, 62 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index db42a71..3f51e2c 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "build": "craco build", "test": "craco test", "eject": "react-scripts eject", - "prettier": "prettier --write ." + "prettier": "prettier --write src" }, "eslintConfig": { "extends": "react-app" diff --git a/src/pages/ListNewMarketPage.jsx b/src/pages/ListNewMarketPage.jsx index 0462201..acc31be 100644 --- a/src/pages/ListNewMarketPage.jsx +++ b/src/pages/ListNewMarketPage.jsx @@ -100,7 +100,8 @@ export default function ListNewMarketPage() { } catch (e) { console.warn(e); notify({ - message: 'Error listing new market: ' + e.message, + message: 'Error listing new market', + description: e.message, type: 'error', }); } finally { diff --git a/src/pages/pools/NewPoolPage.tsx b/src/pages/pools/NewPoolPage.tsx index b6ab69c..bb64672 100644 --- a/src/pages/pools/NewPoolPage.tsx +++ b/src/pages/pools/NewPoolPage.tsx @@ -28,7 +28,7 @@ const AddRemoveTokenButtons = styled.div` margin-bottom: 16px; `; -const DEFAULT_PROGRAM_ID = 'DL7L4cFHwmfNevZRg92rF5unbdUvFGoiuMrQ4aV7Nzsc'; +const DEFAULT_PROGRAM_ID = 'CkMC9rHPB6xu7pQ3L49KUEYL6rcLJ25aKLLPcrNe5wLv'; export default function NewPoolPage() { const connection = useConnection(); @@ -100,7 +100,8 @@ export default function NewPoolPage() { } catch (e) { console.warn(e); notify({ - message: 'Error creating new pool: ' + e.message, + message: 'Error creating new pool', + description: e.message, type: 'error', }); } finally { diff --git a/src/pages/pools/PoolPage/PoolAdminPanel.tsx b/src/pages/pools/PoolPage/PoolAdminPanel.tsx index 0e54cae..2a2fa8e 100644 --- a/src/pages/pools/PoolPage/PoolAdminPanel.tsx +++ b/src/pages/pools/PoolPage/PoolAdminPanel.tsx @@ -69,7 +69,8 @@ function PauseUnpauseTab({ poolInfo }: TabParams) { await sendTransaction({ connection, wallet, transaction }); } catch (e) { notify({ - message: 'Error pausing pool: ' + e.message, + message: 'Error pausing pool', + description: e.message, type: 'error', }); } finally { @@ -88,7 +89,8 @@ function PauseUnpauseTab({ poolInfo }: TabParams) { await sendTransaction({ connection, wallet, transaction }); } catch (e) { notify({ - message: 'Error unpausing pool: ' + e.message, + message: 'Error unpausing pool', + description: e.message, type: 'error', }); } finally { @@ -396,7 +398,8 @@ function useOnSubmitHandler( } } catch (e) { notify({ - message: `Error ${description}: ${e.message}`, + message: `Error ${description}`, + description: e.message, type: 'error', }); } finally { diff --git a/src/pages/pools/PoolPage/PoolCreateRedeemPanel.tsx b/src/pages/pools/PoolPage/PoolCreateRedeemPanel.tsx index 2efa908..9e79fb7 100644 --- a/src/pages/pools/PoolPage/PoolCreateRedeemPanel.tsx +++ b/src/pages/pools/PoolPage/PoolCreateRedeemPanel.tsx @@ -119,8 +119,8 @@ function CreateRedeemTab({ poolInfo, mintInfo, tab }: CreateRedeemInnerPanel) { message: 'Error ' + (tab === 'create' ? 'creating' : 'redeeming') + - ' pool tokens: ' + - e.message, + ' pool tokens', + description: e.message, type: 'error', }); } finally { diff --git a/src/utils/send.tsx b/src/utils/send.tsx index 2a0da4f..63835a0 100644 --- a/src/utils/send.tsx +++ b/src/utils/send.tsx @@ -4,9 +4,11 @@ import { getSelectedTokenAccountForMint } from './markets'; import { Account, AccountInfo, + Commitment, Connection, PublicKey, RpcResponseAndContext, + SimulatedTransactionResponse, SystemProgram, Transaction, TransactionSignature, @@ -720,6 +722,25 @@ export async function sendSignedTransaction({ if (err.timeout) { throw new Error('Timed out awaiting confirmation on transaction'); } + let simulateResult: SimulatedTransactionResponse | null = null; + try { + simulateResult = ( + await simulateTransaction(connection, signedTransaction, 'single') + ).value; + } catch (e) {} + if (simulateResult && simulateResult.err) { + if (simulateResult.logs) { + for (let i = simulateResult.logs.length - 1; i >= 0; --i) { + const line = simulateResult.logs[i]; + if (line.startsWith('Program log: ')) { + throw new Error( + 'Transaction failed: ' + line.slice('Program log: '.length), + ); + } + } + } + throw new Error(JSON.stringify(simulateResult.err)); + } throw new Error('Transaction failed'); } finally { done = true; @@ -903,3 +924,30 @@ export async function getMultipleSolanaAccounts( ), }; } + +/** Copy of Connection.simulateTransaction that takes a commitment parameter. */ +async function simulateTransaction( + connection: Connection, + transaction: Transaction, + commitment: Commitment, +): Promise> { + // @ts-ignore + transaction.recentBlockhash = await connection._recentBlockhash( + // @ts-ignore + connection._disableBlockhashCaching, + ); + + const signData = transaction.serializeMessage(); + // @ts-ignore + const wireTransaction = transaction._serialize(signData); + const encodedTransaction = wireTransaction.toString('base64'); + const config: any = { encoding: 'base64', commitment }; + const args = [encodedTransaction, config]; + + // @ts-ignore + const res = await connection._rpcRequest('simulateTransaction', args); + if (res.error) { + throw new Error('failed to simulate transaction: ' + res.error.message); + } + return res.result; +}