Skip to content

Commit ba7a09c

Browse files
committed
Rename to just sendTransaction()
- Its cleaner - Covered some potential edge cases if transaction already signed or has computeInstructions already
1 parent 1aec7bd commit ba7a09c

File tree

4 files changed

+75
-51
lines changed

4 files changed

+75
-51
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 2.7
2+
3+
- Added `sendTransaction()` to send transactions with compute unit optimization and automatic retries.
4+
- Removed `sendTransactionWithRetry()` as sendTransaction() is more convenient.
5+
16
## 2.6
27

38
- Added Transaction send helpers. `prepareTransactionWithCompute()` and `sendTransactionWithRetry()`

README.md

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -496,77 +496,73 @@ To just run tests matching the name `getCustomErrorMessage`.
496496

497497
### Transaction Utilities
498498

499-
#### `sendTransactionWithRetry`
499+
#### `sendTransaction`
500500

501-
Sends a transaction with automatic retries and status updates. This function implements a robust retry mechanism that:
501+
Sends a transaction with compute unit optimization and automatic retries. This function:
502502

503-
1. Signs the transaction (if signers are provided)
504-
2. Sends the transaction only once
505-
3. Monitors the transaction status until confirmation
506-
4. Retries on failure with a fixed delay
507-
5. Provides detailed status updates through a callback
503+
1. Automatically sets compute units based on simulation
504+
2. Adds priority fees for faster processing
505+
3. Handles retries and confirmation
506+
4. Provides detailed status updates
508507

509508
```typescript
510-
const signature = await sendTransactionWithRetry(
509+
const signature = await sendTransaction(connection, transaction, [payer]);
510+
```
511+
512+
The function is also customizable if you do not like the defaults:
513+
514+
```typescript
515+
const signature = await sendTransaction(
511516
connection,
512517
transaction,
513-
signers,
518+
[payer],
519+
10000, // priority fee in microLamports
514520
{
515-
commitment: "confirmed",
521+
computeUnitBuffer: { multiplier: 1.1 }, // add 10% buffer to compute units
516522
onStatusUpdate: (status) => console.log(status),
517-
maxRetries: 30,
523+
commitment: "confirmed",
524+
maxRetries: 10,
518525
initialDelayMs: 2000,
519526
},
520527
);
521528
```
522529

523-
Best combined with `prepareTransactionWithCompute` to ensure the transaction requests the minimum compute units and sets priority fees.
530+
The function will:
524531

525-
```typescript
526-
// This could be really nice if RPC providers would all have the same API...
527-
// Please fall back to the fee api of your favourite RPC provider to get a good value.
528-
const priorityFee = 1000;
532+
- Skip compute preparation if transaction is already signed
533+
- Skip compute preparation if transaction already has compute budget instructions
534+
- Add compute budget instructions if needed
535+
- Handle retries and confirmation automatically
536+
- Provide status updates: "created" → "signed" → "sent" → "confirmed"
529537

530-
await prepareTransactionWithCompute(
531-
connection,
532-
tx,
533-
keyPair.publicKey,
534-
priorityFee
535-
);
536-
537-
// can either sign the transaction here, or in the sendTransactionWithRetry function
538-
tx.sign(keyPair);
539-
540-
var signature = await sendTransactionWithRetry(connection, tx, [], {
541-
onStatusUpdate: (status) => {
542-
console.log("Transaction status:", status);
543-
},
544-
});
538+
For RPC providers that support priority fees:
545539

546-
```
540+
- Helius: minimum 10000 microLamports
541+
- Triton: see their [priority fee API](https://docs.triton.one/chains/solana/improved-priority-fees-api)
542+
- Quicknode: see their [priority fee estimation](https://www.quicknode.com/docs/solana/qn_estimatePriorityFees)
547543

548544
#### `prepareTransactionWithCompute`
549545

550-
Prepares a transaction with compute unit calculations and limits. This function:
551-
552-
1. Simulates the transaction to determine required compute units
553-
2. Adds compute budget instructions for both price and unit limit
554-
3. Supports buffer settings to add safety margins (This is useful when inteacting with defi for examples where the price or route may change during the transaction)
546+
If you need more control, you can prepare compute units separately:
555547

556548
```typescript
557549
await prepareTransactionWithCompute(
558550
connection,
559551
transaction,
560552
payer.publicKey,
561-
1000, // priority fee in microLamports
553+
10000, // priority fee
562554
{
563555
multiplier: 1.1, // add 10% buffer
564556
fixed: 100, // add fixed amount of CUs
565557
},
566558
);
567559
```
568560

569-
Both functions help with common transaction handling tasks in Solana, making it easier to send reliable transactions with appropriate compute unit settings.
561+
This will:
562+
563+
1. Simulate the transaction to determine required compute units
564+
2. Add compute budget instructions for both price and unit limit
565+
3. Apply any specified compute unit buffers
570566

571567
## Anchor IDL Utilities
572568

src/lib/transaction.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ export const getSimulationComputeUnits = async (
8282

8383
if (rpcResponse?.value?.err) {
8484
const logs = rpcResponse.value.logs?.join("\n • ") || "No logs available";
85-
throw new Error(`Transaction simulation failed:\n •${logs}`);
85+
throw new Error(
86+
`Transaction simulation failed:\n •${logs}` +
87+
JSON.stringify(rpcResponse?.value?.err),
88+
);
8689
}
8790

8891
return rpcResponse.value.unitsConsumed || null;
@@ -188,7 +191,7 @@ export const DEFAULT_SEND_OPTIONS: Required<
188191
* );
189192
* ```
190193
*/
191-
export async function sendTransactionWithRetry(
194+
async function sendTransactionWithRetry(
192195
connection: Connection,
193196
transaction: Transaction,
194197
signers: Keypair[],
@@ -643,25 +646,25 @@ function formatData(data: any): any {
643646
* @param connection - The Solana connection object
644647
* @param transaction - The transaction to send
645648
* @param signers - Array of signers needed for the transaction
646-
* @param priorityFee - Priority fee in microLamports
649+
* @param priorityFee - Priority fee in microLamports (default: 10000 which is the minimum required for helius to see a transaction as priority)
647650
* @param options - Optional configuration for retry mechanism and compute units
648651
* @returns Promise that resolves to the transaction signature
649652
*
650653
* @example
651654
* ```typescript
652-
* const signature = await sendTransactionWithRetryAndPriorityFees(
655+
* const signature = await sendTransaction(
653656
* connection,
654657
* transaction,
655658
* [payer],
656-
* 1000,
659+
* 10000,
657660
* {
658661
* computeUnitBuffer: { multiplier: 1.1 },
659662
* onStatusUpdate: (status) => console.log(status),
660663
* }
661664
* );
662665
* ```
663666
*/
664-
export async function sendTransactionWithRetryAndPriorityFees(
667+
export async function sendTransaction(
665668
connection: Connection,
666669
transaction: Transaction,
667670
signers: Keypair[],
@@ -691,6 +694,26 @@ export async function sendTransactionWithRetryAndPriorityFees(
691694
transaction.feePayer = signers[0].publicKey;
692695
}
693696

697+
// Skip compute preparation if transaction is already signed or has compute instructions
698+
if (transaction.signatures.length > 0) {
699+
console.log("Transaction already signed, skipping compute preparation");
700+
return sendTransactionWithRetry(connection, transaction, signers, {
701+
commitment,
702+
...sendOptions,
703+
});
704+
}
705+
706+
const hasComputeInstructions = transaction.instructions.some(ix =>
707+
ix.programId.equals(ComputeBudgetProgram.programId)
708+
);
709+
710+
if (hasComputeInstructions) {
711+
console.log("Transaction already has compute instructions, skipping compute preparation");
712+
return sendTransactionWithRetry(connection, transaction, signers, {
713+
commitment,
714+
...sendOptions,
715+
});
716+
}
694717
await prepareTransactionWithCompute(
695718
connection,
696719
transaction,

tests/src/transaction.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ import {
1414
confirmTransaction,
1515
getSimulationComputeUnits,
1616
prepareTransactionWithCompute,
17-
sendTransactionWithRetry,
18-
sendTransactionWithRetryAndPriorityFees,
17+
sendTransaction,
1918
} from "../../src";
2019
import { sendAndConfirmTransaction } from "@solana/web3.js";
2120
import assert from "node:assert";
@@ -101,7 +100,7 @@ describe("getSimulationComputeUnits", () => {
101100
});
102101

103102
describe("Transaction utilities", () => {
104-
test("sendTransactionWithRetry should send and confirm a transaction", async () => {
103+
test("sendTransaction without priority fee should send and confirm a transaction", async () => {
105104
const connection = new Connection(LOCALHOST);
106105
const sender = Keypair.generate();
107106
await airdropIfRequired(
@@ -126,10 +125,11 @@ describe("Transaction utilities", () => {
126125
transaction.feePayer = sender.publicKey;
127126

128127
const statusUpdates: any[] = [];
129-
const signature = await sendTransactionWithRetry(
128+
const signature = await sendTransaction(
130129
connection,
131130
transaction,
132131
[sender],
132+
0,
133133
{
134134
onStatusUpdate: (status) => {
135135
statusUpdates.push(status);
@@ -195,7 +195,7 @@ describe("Transaction utilities", () => {
195195
});
196196
});
197197

198-
test("sendTransactionWithRetryAndPriorityFees should prepare and send a transaction", async () => {
198+
test("sendTransaction should prepare and send a transaction and add priority fee instructions", async () => {
199199
const connection = new Connection(LOCALHOST);
200200
const sender = Keypair.generate();
201201
await airdropIfRequired(
@@ -215,7 +215,7 @@ describe("Transaction utilities", () => {
215215
);
216216

217217
const statusUpdates: any[] = [];
218-
const signature = await sendTransactionWithRetryAndPriorityFees(
218+
const signature = await sendTransaction(
219219
connection,
220220
transaction,
221221
[sender],

0 commit comments

Comments
 (0)