noierrdev-antoine-tx-engine

Crates.ionoierrdev-antoine-tx-engine
lib.rsnoierrdev-antoine-tx-engine
version0.1.5
created_at2026-01-15 06:00:32.945526+00
updated_at2026-01-16 15:51:22.932518+00
descriptionA short description of my crate
homepage
repositoryhttps://github.com/noierrdev/noierrdev_antoine_tx_engine
max_upload_size
id2044677
size237,079
Vander Jin (noierrdev)

documentation

README

crate documentation

tx_engine

Tx engine for sending tx with optmized mechanism.

How to start

In cargo.toml:

[dependencies]

...

noierrdev-antoine-tx-engine="0.1.0"

In main.rs:


use noierrdev_antoine_tx_engine as tx_engine;

...

let mut tx_meta_pool : Arc<DashMap<[u8;64], Value>> = Arc::new(DashMap::new());
let tx_meta_pool_monitor=Arc::clone(&tx_pool);
let tx_meta_pool_engine = Arc::clone(&tx_pool);

let rpc_client = Arc::new(RpcClient::new_with_commitment(rpc_url.to_string(),commitment));
let http_client=Arc::new(HttpClient::new());

...

let tx_engine=tx_engine::TxEngine::new(
    &rpc_client,
    &http_client,
    tx_meta_pool_engine // this is useful for usage of sequential() method. this will be shred with grpc monitoring task
);

How to add ComputeBudget Program instructions for optimization and priority


let instruction_set_compute_unit_price : Instruction = tx_engine::general::build_compute_unit_price_instruction(
    microlamports // u64
);

let instruction_set_compute_unit_limit : Instruction = tx_engine::general::build_compute_unit_limit_instruction(
    compute_units // u32
);

Adding tip instruction

You can add tip instruction of any landing provider of astralane, jito, 0slot, temperal, blockrazor, flashblock, node1 and also helius!!

...

let tip_0slot_instruction = tx_engine::zero_slot::build_zero_slot_tip_instruction(
    &wallet, //&Pubkey
    tip_lamports // u64
);

let tip_astralane_instruction = tx_engine::astralane::build_astralane_tip_instruction(
    &wallet, //&Pubkey
    tip_lamports // u64
);

...

You can add any tip address of any landing provider with simple function.


...

let tip_instruction = tx_engine::tip::build_tip_instruction(
    &wallet, //&Pubkey
    &tip_account, //&Pubkey
    tip_amount //u64
);

let tip_tx = tx_engine::tip::build_tip_tx(
    &wallet,// &Keypair, 
    &tip_account, //&Pubkey,
    tip_lamports, //u64, 
    recent_blockhash //Hash
);
...

Refreshing recent_blockhash in background

After creation of tx_engine instance, it runs simple task in background to refresh recent_blockhash property. You can use that as recent_blockhash of tx so that you can save one rpc api call while building transaction.


let recent_blockhash : Hash= tx_engine::get_blockhash();

Building Transaction

You can build transaction as VersionedTransaction and sign from instructions.


let tx : VersionedTransaction = tx_engine::tx::build_tx_from_ix(
    wallets, //Vec<Arc<Keypair>>, 
    payer, // &Pubkey,  
    instructions, // &Vec<Instruction>, 
    recent_blockhash // Hash
);

You can add tip instruction with passing arguement into function.


let tx : VersionedTransaction =tx_engine::tx::build_tx(
    wallets,// Vec<Arc<Keypair>>
    payer, //&Pubkey
    mut instructions, //Vec<Instruction>
    tip_jito,// u64
    tip_0slot,// u64
    tip_astralane,// u64
    tip_helius,// u64
    tip_temperal,// u64
    tip_node1,// u64
    tip_blockrazor,// u64
    tip_flashblock,// u64
    recent_blockhash // Hash
);

Submitting tx or bundle

Transaction

You can submit transaction via tx_engine's rpc client or http client instance.


let tx_hash : String = tx_engine::send_rpc_versioned(
    &tx //VersionedTransaction
);

let tx_hash : String = tx_engine::send_url_versioned(
    &sender_url, //&str
    &tx //VersionedTransaction
).await;

Or, you can submit using external rpc client or http client.


let tx_hash : String = tx_engine::send::send_rpc_versioned(
    &rpc_cleint, //RpcClient
    &tx //VersionedTransaction
);

let tx_hash : String = tx_engine::send::send_url_versioned(
    &http_client, //HttpClient
    &sender_url, //&str
    &tx //VersionedTransaction
).await;

Recently, 0slot or Astralane strated supporting optimized endpoint without JSON parsing(Please note that there is no returning value).


tx_engine::send_url_text(
    &sender_url, //&str
    &tx //VersionedTransaction
).await;

tx_engine::send::send_url_text(
    &http_client, //HttpClient
    &sender_url, //&str
    &tx //VersionedTransaction
).await;

If you configured batch_sender_url which supports sendTransactionBatch when initialize tx_engine instance, you can send batch txs via that.


tx_engine::send_batch(
    &txs //&Vec<VersionedTransaction>
).await;

Sending with durable nonce

You can send single tx using durable nonce account via several landing providers. Only first tx which is processed is valid and others will be failed.

Please note that you need to use binary sender url for astralane and 0slot.

Sending tx as binary on astralane

Sending tx as binary on 0slot

tx_engine::send_with_durable_nonce(
    wallets, // Vec<Arc<Keypair>>
    &payer, // &Pubkey
    ixs, // mut Vec<Instruction>
    &nonce_account, // &Pubkey
    &jito_sender_url, // &str
    &astralane_sender_url, // &str
    &zero_slot_sender_url, // &str
    tip_amount //u64
);

Sending with returning metadata

You can send tx and wait for tx metadata after processed with just running single method.

let tx_metadata : serde_json::Value = tx_engine::send_for_tx_meta(
    &sender_url, //&str,
    &tx //&VersionedTransaction
).await;

Sending to multiple endpoints without tip

tx_engine.send_tx_multiple_urls(
    urls,//Vec<&str>
    &test_tx //&VersionedTransaction
).await;

Sending Bundle

You can send bundle via jito or astralane endpoint which were configured when you initialize tx_engine instance.


tx_engine::send_jito_bundle(
    &txs //&Vec<VersionedTransaction>
).await;


tx_engine::send_astralane_bundle(
    &txs //&Vec<VersionedTransaction>
).await;

Sequential landing

That is the most amazing part of this engine.
You can send batch txs using this method and tx_engine will send txs one by one but if one is failed then stop sending immediately. Please note that this is not atomic processing and not bundles. Currently, it uses single_sender_url. But in the future, I will add more customizable function. It workes only when grpc monitor is working properly.


...
let mut tx_pool : Arc<DashSet<[u8;64]>> = Arc::new(DashSet::new());
let tx_pool_monitor=Arc::clone(&tx_pool);
let tx_pool_engine = Arc::clone(&tx_pool);
...
let monitor_task = tokio::spawn(async move {
    grpc_monitor::initialize_grpc_monitor(
        &http_client_monitor,
        &rpc_client_monitor,
        &mut grpc_client, 
        tx_pool_monitor
    ).await;
});
tasks.push(monitor_task);
...

tx_engine::send_sequential(
    &txs // &Vec<VersionedTransaction>
).await;

Using durable nonce

You can get instructions to create durable nonce account.


let create_nonce_instructions : Vec<Instruction> = tx_engine::nonce::build_create_nonce_account_instruction(
    &rpc_client,
    &wallet_pubkey, //&Pubkey,
    &nonce_keypair //&Keypair
);

Or, you can get signed tx to create durable nonce account.


let create_nonce_tx : VersionedTransaction = tx_engine::nonce::build_create_nonce_account_tx(
    &rpc_client, //&RpcClient 
    &wallet, //&Keypair 
    &nonce_keypair, //&Keypair 
    recent_blockhash// Hash
);

Also you can get nonce hash from address of nonce account.


let nonce_hash : Hash = tx_engine::get_nonce(
    &nonce_account //&Pubkey
);
Commit count: 0

cargo fmt