Helius getTransactionsForAddress
Backfill full transactions for an address in pages of 100 with Helius getTransactionsForAddress, filtered by slot, time, signature or status.
On this page
HeliusGtfaDatasource pages through Helius' getTransactionsForAddress, which returns full transactions with metadata in one call, and emits them as transaction updates. Compared with the RPC transaction crawler, it needs one request per 100 transactions instead of one per transaction, can go oldest-first, and filters by slot, block time, signature range or status on the server. Use it to backfill an address's history on Helius.
| Crate | carbon-helius-gtfa-datasource 2.0.0 |
| Install | cargo add carbon-helius-gtfa-datasource@2. |
| Emits | Transaction |
| Mode | Historical. Finishes after the last page. |
| Provider | A Helius RPC URL with API key, on a plan that includes getTransactionsForAddress. |
| API docs | docs.rs |
| Source | datasources/ |
Quick example#
This program backfills 1,000 slots of Orca Whirlpool transactions, oldest first, prints each swapV2, and exits. It compiles as shown; to run it, set HELIUS_ and START_SLOT.
cargo new helius-gtfa && cd helius-gtfa
cargo add carbon-core@2.0.0 carbon-log-metrics@2.0.0 carbon-orca-whirlpool-decoder@2.0.0 carbon-helius-gtfa-datasource@2.0.0
cargo add solana-commitment-config@3.1.1
cargo add tokio@1 --features full
cargo add env_logger@0.11 log@0.4use {
carbon_core::{
error::CarbonResult, instruction::InstructionProcessorInputType, pipeline::Pipeline,
processor::Processor,
},
carbon_helius_gtfa_datasource::{
HeliusGtfaConfig, HeliusGtfaDatasource, HeliusGtfaFilters, SlotFilter, SortOrder,
},
carbon_log_metrics::LogMetrics,
carbon_orca_whirlpool_decoder::{
instructions::OrcaWhirlpoolInstruction, OrcaWhirlpoolDecoder, PROGRAM_ID,
},
solana_commitment_config::CommitmentConfig,
std::{env, sync::Arc},
};
#[tokio::main]
async fn main() -> CarbonResult<()> {
env_logger::init();
let start_slot: u64 = env::var("START_SLOT").expect("START_SLOT must be set").parse().unwrap();
let config = HeliusGtfaConfig::new(
Some(SortOrder::Asc), // oldest first
Some(100), // transactions per page (max 100)
Some(CommitmentConfig::finalized()),
Some(HeliusGtfaFilters {
slot: Some(SlotFilter {
gte: Some(start_slot),
lt: Some(start_slot + 1_000),
gt: None,
lte: None,
}),
block_time: None,
signature: None,
status: None, // successful transactions only
}),
None, // min_context_slot
);
let datasource = HeliusGtfaDatasource::new_with_config(
format!(
"https://mainnet.helius-rpc.com/?api-key={}",
env::var("HELIUS_API_KEY").expect("HELIUS_API_KEY must be set")
),
PROGRAM_ID,
config,
);
Pipeline::builder()
.datasource(datasource)
.metrics(Arc::new(LogMetrics::new()))
.instruction(OrcaWhirlpoolDecoder, SwapLogger)
.build()?
.run()
.await
}
struct SwapLogger;
impl Processor<InstructionProcessorInputType<'_, OrcaWhirlpoolInstruction>> for SwapLogger {
async fn process(
&mut self,
input: &InstructionProcessorInputType<'_, OrcaWhirlpoolInstruction>,
) -> CarbonResult<()> {
let tx = &input.metadata.transaction_metadata;
if let OrcaWhirlpoolInstruction::SwapV2 { data, accounts, .. } = input.decoded_instruction {
println!("slot {} swapV2 pool={} amount={}", tx.slot, accounts.whirlpool, data.amount);
}
Ok(())
}
}HELIUS_API_KEY=your-helius-api-key START_SLOT=467000000 RUST_LOG=info cargo runSwaps print in slot order, followed by Reached end of pagination and pipeline shutdown. With an invalid key:
[ERROR carbon_helius_gtfa_datasource] RPC request failed with status 401 Unauthorized: Unauthorized
[ERROR carbon_core::pipeline] error consuming datasource: FailedToConsumeDatasource("HTTP error 401 Unauthorized: Unauthorized")Configuration#
Constructors#
pub fn new(helius_rpc_url: String, address: Pubkey) -> Self
pub fn new_with_config(helius_rpc_url: String, address: Pubkey, config: HeliusGtfaConfig) -> Selfhelius_ is the full URL including ?api-key=. address is the account whose transactions you want: a program, wallet, pool or mint.
HeliusGtfaConfig#
pub fn new(
sort_order: Option<SortOrder>,
limit: Option<u32>,
commitment: Option<CommitmentConfig>,
filters: Option<HeliusGtfaFilters>,
min_context_slot: Option<u64>,
) -> Self| Field | Type | Default | Meaning |
|---|---|---|---|
sort_order | Option< | Some(Asc) | SortOrder:: (oldest first) or Desc. None (possible with new) leaves it to Helius. |
limit | Option<u32> | Some(100) | Transactions per page. Capped at 100; None in new also means 100. |
commitment | Option< | confirmed | None (possible with new) leaves it to Helius. |
filters | Option< | None | Server-side filters. A filter with every field empty is not sent. |
min_ | Option<u64> | None | Reject the request if Helius is behind this slot. |
The datasource always requests transactionDetails: "full", Base64 encoding and maxSupportedTransactionVersion: 1.
HeliusGtfaFilters#
| Field | Type | Meaning |
|---|---|---|
slot | Option< | RangeFilter< with gte, gt, lte, lt. |
block_time | Option< | Unix seconds: gte, gt, lte, lt, eq. |
signature | Option< | RangeFilter< of base58 signatures. |
status | Option< | Succeeded, Failed or Any. Applied by Helius and again by the datasource. |
The datasource's own status check: None and Succeeded drop failed transactions, Failed keeps only failed ones, Any keeps both.
Behaviour#
- Paging. Pages are fetched one at a time, following
paginationTokenuntil Helius returns none. Order within and across pages followssort_order. - Updates.
slot,block_timeandindex(the transaction's position in its block, when Helius returns it) are set;block_hashisNoneandis_voteisfalse. - Backpressure. Updates are sent with
send().; nothing is dropped.await - Finishing.
consumereturns after the last page. A pipeline with only this datasource then shuts down. - Errors. There are no retries. A non-2xx status, a body that isn't JSON, an RPC error, or a transaction whose metadata can't be converted stops the datasource with
FailedToConsumeDatasource. Transactions that fail to decode are skipped withFailed to decode transaction. - Cancellation. Checked before each page and between transactions.
- Metrics.
helius_,gtfa_ pages_ fetched_ total helius_(counters),gtfa_ transactions_ processed_ total helius_(histogram).gtfa_ fetch_ duration_ milliseconds
Troubleshooting#
HTTP error 401 Unauthorized#
The API key is missing or invalid. The URL must end in ?api-key=<.
RPC error: … (code: …)#
Helius rejected the request: an unsupported method on your plan, a malformed filter, or a bad address. The message is Helius' own.
The backfill stops halfway with an error#
There are no retries. Restart with a slot filter (gte = the last slot you stored, with Asc) to resume, and make your writes idempotent so the overlap is harmless.
Failed transactions are missing#
By default the datasource drops them. Set status: Some(TransactionStatusFilter:: or Any.