For the complete documentation index, see llms.txt. This page is also available as Markdown.

TxStream gRPC

RPC Fast's optimised protocol for real-time deshredded Solana transactions and transaction simulation.

TxStream is RPC Fast's purpose-built gRPC protocol for receiving decoded Solana transactions directly from the shred pipeline. It is a highly flexible protocol with transaction filtering, real-time transaction simulation, signatures-only responses, and batch transaction delivery.

We reinvented shred-level transaction streaming: RPC Fast reconstructs, recovers, deshreds, decodes, filters, and streams transactions through one optimised path, before normal validator replay metadata is available.

Why Use TxStream?

  • Faster transaction delivery. The protocol is optimised specifically for transaction streaming, with compact payload and batch delivery modes.

  • Lower client overhead. Transactions arrive decoded, with no raw shred or Solana Entry reconstruction required in your application.

  • Server-side filters. Filter by vote status, signature, included accounts, excluded accounts, or required accounts before data crosses the network.

  • Compact modes. Use signatures_only for timing and monitoring workloads, or batch transaction delivery to reduce per-message gRPC overhead.

  • Resolved Address Lookup Tables. RPC Fast was one of the first providers to resolve ALTs for deshredded transactions. Loaded writable and read-only addresses are included when available and participate in account filters.

  • Real-time transaction simulation. RPC Fast is the first provider to offer real-time simulation of deshredded transactions. Transaction-status simulation achieves approximately 95% accuracy compared with actual execution results.

Performance Comparisons

The latest gRPC stream speed report was generated on August 25, 2026 from a 3-minute run. It compared identical transaction signatures at the same observer using local receive timestamps. All three streams used the account-include filter pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA.

Pairwise results

Faster endpoint in the report
Compared with
Shared transactions
Arrived first
Median lead when first
p95 lead when first

TxStream

Yellowstone

103,073

99.8%

5.02 ms

17.08 ms

ShredStream

Yellowstone

58,688

99.9%

4.82 ms

16.04 ms

ShredStream

TxStream

58,688

50.9%

30 us

571 us

TxStream and ShredStream were effectively neck-and-neck on shared transactions: ShredStream arrived first in 50.9% of matched races and TxStream in the remaining 49.1%.

Both shred-derived streams delivered transactions before Yellowstone in more than 99.8% of their matched races.

Coverage observed in this run

Endpoint
Unique transactions
Coverage

TxStream

103,073

99.9%

ShredStream

58,688

56.9%

Yellowstone

103,177

100.0%

Coverage describes this specific run and filter; it is not a general availability or reliability guarantee. ShredStream coverage is lower here because the benchmark collector does not resolve Address Lookup Tables (ALTs), so transactions that reference the filter account only through an ALT are not matched. This is a filter-coverage difference, not evidence that those transactions were absent from the raw shred stream. Pairwise speed results are calculated only from signatures observed by both endpoints.

Protocol Reference

Full protocol reference can be found at https://github.com/dysnix/aperture-grpc-proto

TxStream uses the aperture.Aperture gRPC service and a single request format for both delivery modes.

Request Format

Both subscription methods accept SubscribeTransactionsRequest:

Field
Type
Default
Description

vote

VoteFilter

VOTE_FILTER_ALL

Stream all transactions, votes only, or non-votes only.

signature

bytes

empty

Match one 64-byte primary transaction signature.

account_include

repeated bytes

empty

Match when any listed 32-byte static or loaded account is present.

account_exclude

repeated bytes

empty

Reject when any listed 32-byte static or loaded account is present.

account_required

repeated bytes

empty

Match only when every listed 32-byte static or loaded account is present.

signatures_only

bool

false

Return only transaction identity and timing fields.

include_simulation

bool

false

Legacy. Prefer simulation_config.include.compute_units: true for lightweight simulation.

simulation_config

SimulationConfig

absent

Enable simulation and explicitly select logs, state deltas, CPI instructions, return data and compute units.

Different filter fields are combined with logical AND. Values inside account_include and account_exclude use OR, while every account_required value must match. With no filters, TxStream delivers all transactions.

Simulation Request Format

Simulation is available on both subscription methods, including with signatures_only.

  • With neither include_simulation: true nor simulation_config, responses do not include simulation.

  • The presence of simulation_config enables simulation even when include_simulation is false. An explicit config takes precedence over the legacy flag.

  • Every include flag defaults to false. An empty config still requests simulation, but does not request compute units or any detailed output.

SimulationConfig contains:

Field
Type
Description

include

SimulationInclude

Select response details using the flags below.

account_include

repeated bytes

Restrict deltas to these 32-byte account addresses. Empty means unrestricted.

owner_include

repeated bytes

Restrict deltas to accounts owned by any of these 32-byte program IDs before or after simulation. Empty means unrestricted.

SimulationInclude flag

Response field

compute_units

simulation.compute_units_consumed

account_deltas

simulation.simulation_state_deltas.account_deltas

token_balance_deltas

simulation.simulation_state_deltas.token_balance_deltas

inner_instructions

simulation.inner_instructions

logs

simulation.logs

return_data

simulation.return_data

Delta filters versus transaction filters

Top-level account_include selects which transactions enter your stream. Nested simulation_config.account_include only selects accounts in the returned deltas; it does not select transactions or limit which instructions execute in simulation.

Within each nested list, matching is OR. When both nested lists are non-empty, the account address and its pre- or post-simulation owner program must match. owner_include matches the Solana account's owning program, not the token authority stored in TokenBalanceState.owner. For example, a token program ID selects its token accounts; a wallet address is not a token-owner-program filter.

These filters affect account and token balance deltas only. They do not filter logs, CPI instructions, return data or compute units.

All public keys use raw 32-byte values in protobuf and base64 strings in protobuf JSON, rather than base58 text. The examples below use protobuf JSON's lowerCamelCase field names; the reference tables use protobuf snake_case names.

Non-Batch and Batch Delivery

Non-batch mode
Batch transaction delivery

RPC

/aperture.Aperture/SubscribeTransactions

/aperture.Aperture/SubscribeTransactionBatches

Response stream

DecodedTransaction

DecodedTransactionBatch

Delivery behavior

Emits each matching transaction in its own gRPC message.

Immediately emits available matching transactions, up to 64 per batch, without waiting for the batch to fill.

Best suited for

Minimum transaction-by-transaction delivery delay.

High-throughput consumers that want fewer protobuf and gRPC messages.

Ordering without simulation

Transactions are delivered in stream order, with indexes 0, 1, 2, ….

Transactions remain ordered within each batch and across consecutive batches.

Ordering with simulation

Transactions are delivered as soon as their simulations complete. Delivery may therefore be out of order—for example, 1, 2, 0—while index preserves the original stream order.

Transaction order is preserved. A batch is delivered only after all simulations in that batch finish, so its latency is determined by the slowest simulation.

The same filters, signatures_only mode, and simulation option are available in both delivery modes.

Transaction Response Format

DecodedTransaction contains:

Field
Type
Description

slot

uint64

Solana slot containing the transaction.

index

uint64

Transaction index within the subscription.

is_vote

bool

Whether this is a vote transaction.

created_at_unix_nanos

uint64

Transaction stream timestamp in Unix nanoseconds.

signatures

repeated bytes

Transaction signatures; each signature is 64 bytes.

version

TransactionVersion

TRANSACTION_VERSION_LEGACY or TRANSACTION_VERSION_V0.

header

MessageHeader

Required-signature and read-only-account counts.

static_account_keys

repeated bytes

Static 32-byte account keys from the transaction message.

loaded_writable_addresses

repeated bytes

Resolved writable 32-byte ALT addresses.

loaded_readonly_addresses

repeated bytes

Resolved read-only 32-byte ALT addresses.

recent_blockhash

bytes

The transaction's 32-byte recent blockhash.

instructions

repeated CompiledInstruction

Compiled transaction instructions.

simulation

TransactionSimulation

Present when include_simulation is true or simulation_config is provided.

alt_resolution

optional string

FULL when every ALT lookup was resolved, PARTIAL when one or more could not be resolved, and absent when ALT resolution is unavailable.

MessageHeader contains num_required_signatures, num_readonly_signed_accounts, and num_readonly_unsigned_accounts. CompiledInstruction contains program_id_index, the instruction's account indexes, and its raw instruction data.

Instruction account indexes refer to the following concatenated key list:

static_account_keys + loaded_writable_addresses + loaded_readonly_addresses

When signatures_only is enabled, responses retain slot, index, is_vote, created_at_unix_nanos, signatures, version, and an optional simulation result. Transaction message fields are omitted.

Batch Response Format

DecodedTransactionBatch contains one field:

Field
Type
Description

transactions

repeated DecodedTransaction

One to 64 transactions matching the subscription request.

Each transaction has the same format as a non-batch response.

Simulation Response Format

When requested, TransactionSimulation contains the outcome and timing fields below, plus the selected details. Optional values may be absent when unavailable; repeated fields are empty when not requested or when there are no results. Missing compute units must not be interpreted as zero.

Field
Type
Description

bank_slot

optional uint64

Slot used for the simulation result.

status

SimulationStatus

Simulation outcome.

error

optional string

Error details when simulation is not successful.

simulated_at_unix_nanos

uint64

Simulation timestamp in Unix nanoseconds.

processing_time_nanos

uint64

Simulation processing duration in nanoseconds.

Additional field
Type
Availability and meaning

compute_units_consumed

optional uint64

CU used, when available. Enabled by legacy include_simulation, or explicitly by include.compute_units.

fee

optional uint64

Transaction fee in lamports, when supplied by the simulator. There is no include flag for this field.

logs

repeated string

Program logs from simulation when include.logs is true.

return_data

TransactionReturnData

Program return value when requested and available: program_id (bytes) and data (bytes).

simulation_state_deltas

SimulationStateDeltas

Selected account and/or token deltas when requested and available. Contains account_deltas and token_balance_deltas.

inner_instructions

repeated SimulationInnerInstructions

Simulated CPI instructions when include.inner_instructions is true.

Account deltas

Each AccountDelta contains:

Field
Type
Description

account

bytes

The 32-byte writable account address.

pre

SimulationAccountState

State before simulation, when present.

post

SimulationAccountState

Effective state after simulation, when present.

changed

bool

True for returned entries; includes changes to account data even if the returned metadata is identical.

SimulationAccountState contains lamports (uint64), owner (owning program, bytes), executable (bool) and rent_epoch (uint64). Raw account data is not returned.

Only changed writable accounts are included. A missing pre/post account state represents account creation or closure. For failed execution, deltas describe effective rollback state, including applicable fee and nonce changes, rather than intermediate writes from a failed instruction.

Token balance deltas

Each TokenBalanceDelta contains:

Field
Type
Description

account

bytes

The 32-byte token account address.

pre

TokenBalanceState

Parsed token state before simulation, when present.

post

TokenBalanceState

Parsed token state after simulation, when present.

pre_owner

bytes

Solana account's owning program before simulation, used by the owner filter.

post_owner

bytes

Solana account's owning program after simulation, used by the owner filter.

TokenBalanceState contains mint (bytes), owner (token authority, bytes), program_id (token program, bytes) and amount (uint64).

Only changed token states from writable accounts are returned. Missing pre/post token state can represent creation, closure or conversion to/from a token account. Amounts are raw integer token units: decimals and UI amounts are not included, and simulation does not fetch mint accounts to convert them. Token-2022 reports the base token balance without extension balances.

For an unchanged mint, calculate the signed token amount change as post.amount - pre.amount, treating a missing side as zero for creation/closure. Use signed or arbitrary-precision arithmetic to avoid unsigned underflow. If the mint changes, interpret the pre and post states separately.

Inner instructions

Each SimulationInnerInstructions group contains instruction_index (uint32, the outer instruction index) and repeated instructions.

Each SimulationInnerInstruction contains program_id (bytes), accounts (repeated bytes), data (bytes) and stack_height (uint32). Program and account keys are already resolved public keys, rather than indexes into the transaction's account list.

These logs, deltas, inner instructions and return values are predictions from simulation, not confirmed execution metadata.

SimulationStatus values:

Status
Meaning

SIMULATION_STATUS_SUCCEEDED

The simulation succeeded.

SIMULATION_STATUS_FAILED

The simulation failed.

SIMULATION_STATUS_INVALID_TRANSACTION

The transaction is invalid.

SIMULATION_STATUS_BANK_NOT_AVAILABLE

The required Bank state was unavailable. The transaction may still be valid, but no simulation outcome is available.

SIMULATION_STATUS_SERVER_OVERLOADED

Simulation capacity was exhausted or its time limit was exceeded. This is not evidence that the transaction itself failed.

SIMULATION_STATUS_INTERNAL_ERROR

An internal error occurred during simulation.

Use the Official Rust Client

As a best practice, use the official dysnix/aperture-grpc-client. It provides byte-safe filters, tuned HTTP/2 flow control, TLS native roots, keepalives, X-Token authentication, and automatic reconnection.

Set APERTURE_X_TOKEN to your RPC Fast token before running the example.

An empty filter streams all transactions. Apply the narrowest server-side filter that serves your workload to reduce bandwidth and client-side work.

Request Real-Time Simulation

Use aperture-grpc-client 0.6.1 or later for SimulationConfig and the detailed response types. Regenerate other clients from the current official proto.

Use the client's simulation_config with include.compute_units: true for lightweight predictions, and enable additional flags for details. The legacy include_simulation option remains supported for backward compatibility. The following example requests all supported details for every matching deshredded transaction:

Simulation results can include:

  • simulation status, error, Bank slot and timing

  • compute units consumed

  • program logs and return data

  • writable account metadata and token balance changes

  • CPI instructions with resolved accounts and stack heights

Clients that do not request simulation remain on the immediate pre-execution path. For a compact prediction feed, combine simulation_config with include.compute_units: true and signatures_only. Enable only the details you need: recording logs, CPI and state deltas adds work and payload.

Simulation Delivery Latency

The matched-signature comparison measured simulation-enabled TxStream against the equivalent non-simulation stream:

TxStream mode
Median added delivery time
p90 added delivery time

Signatures only

832 us

1.72 ms

Full transaction payload

791 us

1.62 ms

Receive Transaction Batches

Use the batch stream when throughput and lower protobuf/gRPC overhead matter more than emitting each transaction in its own message.

Important Semantics

TxStream is an early transaction feed, not a final source of execution truth.

  • A streamed transaction can fail, never confirm, or land on a fork that does not survive.

  • The normal pre-execution stream does not contain confirmed balances, inner instructions, rewards, execution status, or final program logs.

  • ALT addresses are emitted when resolved. You must tolerate unresolved addresses and must not treat the stream as authoritative replay state.

  • Reconnect after transport failures. The official client does this automatically with exponential backoff.

Use Yellowstone gRPC when you need confirmed execution metadata, account updates, blocks, or other replay-derived data.

Test TxStream with grpcurl

Download the official txstream.proto file to your current directory, set APERTURE_X_TOKEN, and start a non-vote transaction stream:

For lightweight simulation, add "simulationConfig": {"include": {"computeUnits": true}} to the request body. includeSimulation is a legacy field; prefer simulationConfig.include.computeUnits: true for new integrations.

To request detailed simulation, use:

Use the same request with aperture.Aperture/SubscribeTransactionBatches for batched delivery. In protobuf JSON responses, byte fields are base64 and uint64 values, including token amounts and timestamps, are decimal strings.

When to Use TxStream

The use cases can be split into two categories:

1/ Decoded, reconstructed transactions – better developer experience, less engineering work.

Key benefit: less custom infrastructure, faster integration, and no need to decode shreds or reconstruct transactions yourself.

Best for

  • HFT bot developers looking for the fastest path to production with minimal engineering effort.

  • Trading platforms that need transaction parsing without maintaining their own decoder.

  • Wallets tracking pending user transactions.

  • Analytics & monitoring platforms consuming structured real-time transaction data.

  • Copy trading platforms monitoring market activity before block confirmation.

  • Solana developers who need pre-confirmation data without building a shred reconstruction pipeline.

2/ Real-time execution simulation – decision-making edge for latency-sensitive applications).

Key benefit: fewer wasted transactions, fewer false positives, lower compute costs, and faster decision-making under tight latency constraints.

Best for

  • MEV searchers filtering profitable opportunities from transactions that will actually execute.

  • Arbitrage bots avoiding failed swaps and reducing false-positive signals.

  • Liquidation bots confirming liquidation candidates before committing capital.

  • High-frequency trading (HFT) systems making routing decisions with higher confidence.

  • Market makers reacting only to executable market events.

  • Copy-trading platforms replicating only transactions likely to succeed.

  • Risk engines estimating execution outcomes before block inclusion.

Last updated