solana-transaction-optimizer
v1.0.0
Published
Optimize Solana transactions by chunking large transactions into smaller batches. Supports multiple signers, complex instructions, and adaptive sizing.
Maintainers
Readme
Solana Transaction Optimizer
Optimize Solana transactions by chunking large transactions into smaller batches. Supports multiple signers, complex instructions, and adaptive sizing.
Installation
npm install solana-transaction-optimizer
# or
yarn add solana-transaction-optimizer
# or
pnpm add solana-transaction-optimizerOverview
This library helps you optimize Solana transactions by splitting large transactions into smaller chunks. It's designed to handle Solana's transaction size limit (~1232 bytes) and optimize performance when dealing with many transactions.
Problems Solved
- Transaction Size: Solana has a maximum limit of ~1232 bytes per transaction
- Multiple Signers: Transactions with many signers require more space
- Many Instructions: Transactions with many instructions can exceed size limits
- Memory Efficiency: Avoid excessive memory usage when processing thousands of transactions
Features
- ✅ Multiple chunking strategies for different use cases
- ✅ Support for multiple signers
- ✅ Adaptive sizing with automatic chunk size adjustment
- ✅ Streaming support for memory-efficient processing
- ✅ Parallel transaction sending
- ✅ TypeScript support with full type definitions
Quick Start
import { buildTxChunkSmart, sendTxParallel } from 'solana-transaction-optimizer';
import { Connection, Keypair, SystemProgram, PublicKey } from '@solana/web3.js';
// Build transaction chunks
const txList = await buildTxChunkSmart(
10, // chunkSize
priorityFeeIx,
transferInstructions,
signers,
payerKeypair,
lookupTableAccount,
connection
);
// Send transactions in parallel
const signatures = await sendTxParallel({
txList,
connection
});API Reference
Chunking Functions
buildTxChunkManySigners
Split transactions with multiple signers into batches.
Use when:
- Bundle wallet sweeping
- Multi-wallet draining
- Transactions with multiple signers (> 1)
buildTxChunkManySigners(
chunkSize: number,
priorityFeeIx: TransactionInstruction[],
transferInstructions: TransactionInstruction[],
bundlerSigners: Keypair[],
payerKeypair: Keypair,
lookupTableAccount: AddressLookupTableAccount,
connection: Connection
): Promise<VersionedTransaction[]>buildTxChunkSingleSigner
Split transactions with many instructions but only 1 signer.
Use when:
- Sweeping many transfers from one wallet
- Large transactions with ALT
- Single wallet with many instructions
buildTxChunkSingleSigner(
chunkSize: number,
priorityFeeIx: TransactionInstruction[],
transferInstructions: TransactionInstruction[],
payerKeypair: Keypair,
lookupTableAccount: AddressLookupTableAccount,
connection: Connection
): Promise<VersionedTransaction[]>buildTxChunkByInstruction
Split transactions based on instruction count (can have multiple signers).
Use when:
- Batch token payments
- Multi-token transfers
- Complex SPL instructions
- Many CPI calls
buildTxChunkByInstruction(
chunkSize: number,
priorityFeeIx: TransactionInstruction[],
transferInstructions: TransactionInstruction[],
signers: Keypair[],
payerKeypair: Keypair,
lookupTableAccount: AddressLookupTableAccount,
connection: Connection
): Promise<VersionedTransaction[]>buildTxChunkSmart
Automatic builder that chooses chunking strategy based on signer count.
Use when:
- General purpose use cases
- Dynamic use cases with varying signer counts
- Quick implementation without thinking about strategy
buildTxChunkSmart(
chunkSize: number,
priorityFeeIx: TransactionInstruction[],
transferInstructions: TransactionInstruction[],
signers: Keypair[],
payerKeypair: Keypair,
lookupTableAccount: AddressLookupTableAccount,
connection: Connection
): Promise<VersionedTransaction[]>Logic:
- If
signers.length > 1→ usesbuildTxChunkManySigners - If
signers.length === 1→ usesbuildTxChunkSingleSigner
buildTxChunkDynamic
Builder with adaptive sizing that automatically adjusts chunk size based on transaction size.
Use when:
- Instruction sizes vary
- Unsure about optimal chunk size
- Need automatic optimization based on actual size
buildTxChunkDynamic({
instructions: TransactionInstruction[],
signers: Keypair[],
payer: Keypair,
alts?: AddressLookupTableAccount[],
priorityFeeIx?: TransactionInstruction[],
connection: Connection,
maxBytes?: number, // default: 1232
initialChunkSize?: number // default: 10
}): Promise<VersionedTransaction[]>streamTxChunksGenerator
Async generator for streaming transactions (lazy evaluation).
Use when:
- Processing thousands of transactions
- Memory-constrained environments
- Streaming processing pattern
- Don't need all transactions in memory at once
streamTxChunksGenerator({
chunkSize: number,
instructions: TransactionInstruction[],
signers: Keypair[],
payer: Keypair,
alts?: AddressLookupTableAccount[],
priorityFeeIx?: TransactionInstruction[],
connection: Connection
}): AsyncGenerator<VersionedTransaction, void, unknown>Utility Functions
sendTxParallel
Send multiple transactions in parallel.
sendTxParallel({
txList: VersionedTransaction[],
connection: Connection
}): Promise<string[]>estimateGasCost
Calculate fee based on compute units and price.
estimateGasCost({
computeUnitLimit: number,
computeUnitPriceMicroLamports: number
}): numbercalculateTxSize
Calculate transaction size in bytes.
calculateTxSize(tx: VersionedTransaction): numberExamples
Example 1: Bundle Wallet Sweeping
import { buildTxChunkManySigners, sendTxParallel } from 'solana-transaction-optimizer';
import { Connection, Keypair, SystemProgram, PublicKey, ComputeBudgetProgram } from '@solana/web3.js';
async function sweepBundleWallets(
bundleWallets: Keypair[],
payerKeypair: Keypair,
destinationAddress: string,
connection: Connection,
lookupTableAccount: AddressLookupTableAccount
) {
// Create transfer instructions for each wallet
const transferInstructions = bundleWallets.map(wallet =>
SystemProgram.transfer({
fromPubkey: wallet.publicKey,
toPubkey: new PublicKey(destinationAddress),
lamports: // calculate amount
})
);
// Priority fee instructions
const priorityFeeIx = [
ComputeBudgetProgram.setComputeUnitLimit({ units: 250_000 }),
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 4 })
];
// Build chunks with 10 signers per batch
const txList = await buildTxChunkManySigners(
10, // chunkSize
priorityFeeIx,
transferInstructions,
bundleWallets, // bundlerSigners
payerKeypair,
lookupTableAccount,
connection
);
// Send all transactions in parallel
const signatures = await sendTxParallel({
txList,
connection
});
console.log(`Sent ${signatures.length} transactions`);
return signatures;
}Example 2: Dynamic Chunking with Adaptive Sizing
import { buildTxChunkDynamic } from 'solana-transaction-optimizer';
async function adaptiveChunking(
instructions: TransactionInstruction[],
signers: Keypair[],
payer: Keypair,
connection: Connection,
alts: AddressLookupTableAccount[]
) {
// Automatically adjust chunk size
const txList = await buildTxChunkDynamic({
instructions,
signers,
payer,
alts,
connection,
maxBytes: 1232, // Maximum limit
initialChunkSize: 15 // Start with 15 instructions
});
// If chunk is too large, it will automatically reduce
// until it finds the right size
return txList;
}Example 3: Streaming for Large Batches
import { streamTxChunksGenerator } from 'solana-transaction-optimizer';
async function processLargeBatch(
instructions: TransactionInstruction[],
signers: Keypair[],
payer: Keypair,
connection: Connection
) {
// Generator for streaming (doesn't load all into memory)
const generator = streamTxChunksGenerator({
chunkSize: 10,
instructions,
signers,
payer,
connection
});
// Process one by one
for await (const tx of generator) {
try {
const signature = await connection.sendTransaction(tx);
console.log(`Sent: ${signature}`);
} catch (error) {
console.error('Failed to send transaction:', error);
}
}
}Chunking Strategy Guide
| Strategy | Signers | Instructions | Use Case |
|----------|---------|--------------|----------|
| buildTxChunkManySigners | > 1 | Medium | Bundle wallet sweeping |
| buildTxChunkSingleSigner | 1 | Many | Single wallet distribution |
| buildTxChunkByInstruction | 1 or more | Many & Complex | Token batch payments |
| buildTxChunkSmart | Dynamic | Dynamic | General purpose |
| buildTxChunkDynamic | Dynamic | Dynamic & Varied | Adaptive sizing |
| streamTxChunksGenerator | Dynamic | Very Many | Memory-efficient streaming |
Recommended Chunk Sizes
- SOL Transfer: 15-25 instructions per batch
- SPL Token Transfer: 5-10 instructions per batch
- Multiple Signers: 5-10 signers per batch
- Complex Instructions: 3-5 instructions per batch
Performance Tips
- Use ALT (Address Lookup Table): ALT can significantly reduce transaction size
- Batch Blockhash Requests: Reuse blockhash for multiple transactions when possible
- Parallel Sending: Use
sendTxParallelto send multiple transactions at once - Streaming for Large Batches: Use
streamTxChunksGeneratorfor thousands of transactions - Monitor Transaction Size: Use
calculateTxSizeto monitor transaction sizes
Requirements
- Node.js >= 16.0.0
@solana/web3.js^1.95.0
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and questions, please open an issue on GitHub.
