Skip to main content
This is the basic transaction-sending path — billed per send and best when reliability matters more than raw speed (payments, wallets, apps). If you’re trading and need the lowest latency, use Helius Sender instead.
Building your own transaction sending logic is the best way to ensure maximum performance, control, and reliability for your application. While the Helius SDK provides a convenient wrapper for getting started, understanding and implementing this manual workflow is highly recommended for production systems. This guide will walk you through the necessary steps to build your own solution.

The Manual Workflow

Manually sending a transaction involves the following steps:
1

Build the Initial Transaction

Assemble your instructions and sign the transaction so it can be simulated.
2

Optimize Compute Units

Simulate the transaction to determine the precise CUs needed and add a small buffer.
3

Add Priority Fees

Get a fee estimate from the Helius Priority Fee API and add it to your transaction.
4

Send and Re-broadcast

Send the final transaction and implement a robust polling strategy to handle confirmation.
The Helius SDKs are open-source. You can view the underlying code for the sendSmartTransaction method in our TypeScript SDK and Rust SDK to see a production-grade implementation of this workflow.

1. Build the Initial Transaction

First, gather all the instructions you want to include in your transaction. Then, create a Transaction or VersionedTransaction object. You will also need to fetch a recent blockhash. This example prepares a versioned transaction. At this stage, you must also sign it so that it can be simulated in the next step.

2. Optimize Compute Unit (CU) Usage

To avoid wasting fees or having your transaction fail, you should set the compute unit (CU) limit as precisely as possible. You can do this by simulating the transaction using the simulateTransaction RPC method. It’s a best practice to first simulate with a high CU limit to ensure the simulation itself succeeds, and then use the unitsConsumed from the response to set your actual limit.
Now you have an instruction that sets the compute limit precisely. You will add this to your final transaction.

3. Set the Right Priority Fee

Next, determine the optimal priority fee to add to your transaction. Using the Helius Priority Fee API is the best way to get a real-time estimate based on current network conditions. You’ll need to call the getPriorityFeeEstimate RPC method. For the highest chance of inclusion via Helius’s staked connections, use the recommended: true option.

4. Build, Send, and Confirm

Now, assemble the final transaction with the new compute budget instructions, send it, and implement a robust polling mechanism to confirm it has landed.
Do not rely on the RPC provider’s default retry logic (maxRetries in sendTransaction). While Helius’s staked connections forward your transaction directly to the leader, it can still be dropped. You must implement your own rebroadcasting logic for reliable confirmation.
A common pattern is to re-send the same transaction periodically until the blockhash expires. Only re-sign the transaction if you are also fetching a new blockhash. Re-signing with the same blockhash can lead to duplicate transactions being confirmed.
This example provides a basic polling loop. A production-grade application would require more sophisticated logic, including handling different confirmation statuses and potential timeouts.

Protect against sandwich attacks

To route your transaction away from validators statistically linked to sandwich attacks, add the mev-protect=true query parameter to your RPC URL — no changes to your transaction logic:

MEV Protect

See how MEV Protect works, which methods it supports, and its tradeoffs.

Earn rebates on your transactions

You can opt in to earn a share of the MEV your transactions create, paid automatically in SOL — no changes to your transaction logic.

Transaction Rebates

Add one parameter to your sendTransaction calls to start earning SOL rebates.

sendTransaction

Send a signed transaction to the network

simulateTransaction

Simulate a transaction to estimate compute units

getSignatureStatuses

Check confirmation status of transactions

getLatestBlockhash

Get a recent blockhash for transaction signing

getBlockHeight

Get current block height for expiry checks