From 61b87bb8e75a4b042c03e19f62a5360c45bb7c45 Mon Sep 17 00:00:00 2001 From: Michael Liu Date: Wed, 20 Nov 2024 07:14:10 -0500 Subject: [PATCH 1/3] Skip preflight for solana tx --- packages/huma-widget/src/components/SolanaTxSendModal.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/huma-widget/src/components/SolanaTxSendModal.tsx b/packages/huma-widget/src/components/SolanaTxSendModal.tsx index 16ad6b44..0275bfff 100644 --- a/packages/huma-widget/src/components/SolanaTxSendModal.tsx +++ b/packages/huma-widget/src/components/SolanaTxSendModal.tsx @@ -44,6 +44,7 @@ export function SolanaTxSendModal({ const signature = await sendTransaction(optimizedTx, connection, { maxRetries: 5, preflightCommitment: 'confirmed', + skipPreflight: true, }) setSignature(signature) dispatch(setSolanaSignature(signature)) From df16fa3a92c2eaeb441c6cbd418c02de2c76685e Mon Sep 17 00:00:00 2001 From: Michael Liu Date: Wed, 20 Nov 2024 08:04:50 -0500 Subject: [PATCH 2/3] Add optimizations --- .../utils/solana/buildOptimalTransaction.ts | 2 +- .../src/components/SolanaTxSendModal.tsx | 59 ++++++++++++++++--- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/packages/huma-sdk/src/utils/solana/buildOptimalTransaction.ts b/packages/huma-sdk/src/utils/solana/buildOptimalTransaction.ts index 88ffb900..9e64ad04 100644 --- a/packages/huma-sdk/src/utils/solana/buildOptimalTransaction.ts +++ b/packages/huma-sdk/src/utils/solana/buildOptimalTransaction.ts @@ -38,7 +38,7 @@ async function buildOptimalTransactionImpl( 0, ) averagePrioritizationFee = Math.ceil( - averagePrioritizationFee / recentPrioritizationFees.length, + (averagePrioritizationFee / recentPrioritizationFees.length) * 1.5, ) tx.instructions.unshift( diff --git a/packages/huma-widget/src/components/SolanaTxSendModal.tsx b/packages/huma-widget/src/components/SolanaTxSendModal.tsx index 0275bfff..111f3852 100644 --- a/packages/huma-widget/src/components/SolanaTxSendModal.tsx +++ b/packages/huma-widget/src/components/SolanaTxSendModal.tsx @@ -1,4 +1,4 @@ -import { SolanaChainEnum } from '@huma-finance/shared' +import { sleep, SolanaChainEnum } from '@huma-finance/shared' import React, { useEffect, useState } from 'react' import { buildOptimalTransactionFromConnection, @@ -24,28 +24,61 @@ export function SolanaTxSendModal({ handleSuccess, }: Props): React.ReactElement | null { const dispatch = useAppDispatch() - const { sendTransaction } = useWallet() + const { sendTransaction, signTransaction, publicKey } = useWallet() const { connection } = useConnection() const [signature, setSignature] = useState('') useEffect(() => { async function sendTx() { - if (!connection || !tx) { + if (!connection || !tx || !publicKey || !signTransaction) { return } try { + // Optimize transaction const lockedWritableAccounts = extractWritableAccounts(tx) const optimizedTx = await buildOptimalTransactionFromConnection( tx, lockedWritableAccounts, connection, ) - const signature = await sendTransaction(optimizedTx, connection, { - maxRetries: 5, - preflightCommitment: 'confirmed', - skipPreflight: true, - }) + optimizedTx.feePayer = publicKey + + // Sign and serialize transaction + const signedTx = await signTransaction(optimizedTx) + signedTx.recentBlockhash = optimizedTx.recentBlockhash + signedTx.lastValidBlockHeight = optimizedTx.lastValidBlockHeight + const rawTransaction = signedTx.serialize() + + // Try to send raw transaction multiple times through RPC + let blockheight = await connection.getBlockHeight() + let signature + let sendCount = 0 + while (blockheight < signedTx.lastValidBlockHeight! && sendCount < 10) { + console.log(blockheight) + signature = connection.sendRawTransaction(rawTransaction, { + preflightCommitment: 'confirmed', + skipPreflight: true, + }) + /* eslint-disable no-await-in-loop */ + await sleep(500) + /* eslint-disable no-await-in-loop */ + blockheight = await connection.getBlockHeight() + sendCount += 1 + } + + signature = await signature + if (!signature) { + dispatch( + setError({ + errorMessage: + 'Failed to send transaction due to transaction signature expiration (~1.5 minutes). Please try again.', + }), + ) + return + } + + // Confirm transaction setSignature(signature) dispatch(setSolanaSignature(signature)) await connection.confirmTransaction({ @@ -60,7 +93,15 @@ export function SolanaTxSendModal({ } } sendTx() - }, [connection, dispatch, handleSuccess, sendTransaction, tx]) + }, [ + connection, + dispatch, + handleSuccess, + sendTransaction, + tx, + publicKey, + signTransaction, + ]) return ( Date: Wed, 20 Nov 2024 08:15:40 -0500 Subject: [PATCH 3/3] Refactor --- .../src/components/SolanaTxSendModal.tsx | 58 +++---------------- 1 file changed, 9 insertions(+), 49 deletions(-) diff --git a/packages/huma-widget/src/components/SolanaTxSendModal.tsx b/packages/huma-widget/src/components/SolanaTxSendModal.tsx index 111f3852..48a19e29 100644 --- a/packages/huma-widget/src/components/SolanaTxSendModal.tsx +++ b/packages/huma-widget/src/components/SolanaTxSendModal.tsx @@ -1,4 +1,4 @@ -import { sleep, SolanaChainEnum } from '@huma-finance/shared' +import { SolanaChainEnum } from '@huma-finance/shared' import React, { useEffect, useState } from 'react' import { buildOptimalTransactionFromConnection, @@ -24,13 +24,13 @@ export function SolanaTxSendModal({ handleSuccess, }: Props): React.ReactElement | null { const dispatch = useAppDispatch() - const { sendTransaction, signTransaction, publicKey } = useWallet() + const { sendTransaction } = useWallet() const { connection } = useConnection() const [signature, setSignature] = useState('') useEffect(() => { async function sendTx() { - if (!connection || !tx || !publicKey || !signTransaction) { + if (!connection || !tx) { return } @@ -42,43 +42,11 @@ export function SolanaTxSendModal({ lockedWritableAccounts, connection, ) - optimizedTx.feePayer = publicKey - - // Sign and serialize transaction - const signedTx = await signTransaction(optimizedTx) - signedTx.recentBlockhash = optimizedTx.recentBlockhash - signedTx.lastValidBlockHeight = optimizedTx.lastValidBlockHeight - const rawTransaction = signedTx.serialize() - - // Try to send raw transaction multiple times through RPC - let blockheight = await connection.getBlockHeight() - let signature - let sendCount = 0 - while (blockheight < signedTx.lastValidBlockHeight! && sendCount < 10) { - console.log(blockheight) - signature = connection.sendRawTransaction(rawTransaction, { - preflightCommitment: 'confirmed', - skipPreflight: true, - }) - /* eslint-disable no-await-in-loop */ - await sleep(500) - /* eslint-disable no-await-in-loop */ - blockheight = await connection.getBlockHeight() - sendCount += 1 - } - - signature = await signature - if (!signature) { - dispatch( - setError({ - errorMessage: - 'Failed to send transaction due to transaction signature expiration (~1.5 minutes). Please try again.', - }), - ) - return - } - - // Confirm transaction + const signature = await sendTransaction(optimizedTx, connection, { + maxRetries: 5, + preflightCommitment: 'confirmed', + skipPreflight: true, + }) setSignature(signature) dispatch(setSolanaSignature(signature)) await connection.confirmTransaction({ @@ -93,15 +61,7 @@ export function SolanaTxSendModal({ } } sendTx() - }, [ - connection, - dispatch, - handleSuccess, - sendTransaction, - tx, - publicKey, - signTransaction, - ]) + }, [connection, dispatch, handleSuccess, sendTransaction, tx]) return (