LogoLogo
Package RegistryThe Graph
  • Introduction
  • Getting Started
  • Tutorials
    • Develop Your First Substreams
      • on EVM
      • on Solana
        • Transactions & Instructions
        • Account Changes
      • on Cosmos
        • Injective
        • MANTRA
      • on Starknet
      • on Stellar
    • Publishing a Substreams Package
  • How-To Guides
    • Developing Substreams
      • on EVM
        • Exploring Ethereum
          • Mapping Blocks
          • Filter Transactions
          • Retrieve Events of a Smart Contract
      • on Solana
        • Explore Solana
          • Filter Instructions
          • Filter Transactions
        • SPL Token Tracker
        • NFT Trades
        • DEX Trades
      • on Cosmos
        • Injective
          • Simple Substreams Example
          • Foundational Modules
          • Dojo DEX USDT Volume Subgraph Example
    • Using a Substreams Sink
      • Substreams:SQL
      • Substreams:Subgraph
        • Triggers
        • Graph Out
      • Substreams:Stream
        • JavaScript
        • Go
      • Substreams:PubSub
      • Community Sinks
        • MongoDB
        • Files
        • Key-Value Store
        • Prometheus
    • EVM Extensions
      • Making eth_calls
    • Getting Started Using Rust and Protobuf
      • Rust
        • Option struct
        • Result struct
      • Protobuf Schemas
    • From Yellowstone to Substreams
  • Reference Material
    • Chains and endpoints
      • Ethereum Data Model
    • Never Miss Data
    • Development Container Reference
    • Substreams CLI
      • Install the CLI
      • Authentication
      • Substreams CLI reference
    • Substreams Components
      • Packages
      • Modules
        • Module types
        • Inputs
        • Output
        • Module handlers
        • Module handler creation
        • Indexes
        • Keys in stores
        • Dynamic data sources
        • Aggregation Windows
        • Parameterized Modules
      • Manifests Reference
    • Substreams Architecture
    • Graph-Node
      • Local Development
      • Publish to The Graph Network
    • Indexer Reference
      • Test Substreams Locally
    • Logging, Debugging & Testing
    • Change log
    • FAQ
  • Decentralized Indexing
    • What is The Graph?
Powered by GitBook
On this page
  • Run the Substreams
  • Inspect the Code

Was this helpful?

Edit on GitHub
  1. How-To Guides
  2. Developing Substreams
  3. on Solana
  4. Explore Solana

Filter Transactions

PreviousFilter InstructionsNextSPL Token Tracker

Last updated 5 months ago

Was this helpful?

The map_filter_transactions module of the Solana Substreams Explorer filters transactions given a signature hash. For example, let's consider that you want to retrieve transactions containing the 21ED2HBGuLUwgbaBb77cGwFR8MkVQfjR9KszzCb7jZkeSysJkHAVew6RaaBh3r1zTefpdq9Kf5geFp19P3nUXB3t.

Run the Substreams

Run From Source Code

In the substreams-explorer project, move to the solana-explorer folder, which contains the source of the Solana Substreams. Then, build the Rust code:

make build

Now, you can run the Substreams by using the substreams gui command. To avoid iterating over the whole blockchain, the following command extracts transactions including 21ED2HBGuLUwgbaBb77cGwFR8MkVQfjR9KszzCb7jZkeSysJkHAVew6RaaBh3r1zTefpdq9Kf5geFp19P3nUXB3t signatures.

substreams gui ./substreams.yaml \
    map_filter_transactions -e mainnet.sol.streamingfast.io:443 \
    --start-block 153000028 --stop-block +1

In the Output screen of the Substreams GUI you can see there is a transaction with the corresponding signature at block number 153000028.

You can change the signature hash in params section of the the Substreams Manifest (substreams.yaml):

params:
  map_filter_transactions: "signature=21ED2HBGuLUwgbaBb77cGwFR8MkVQfjR9KszzCb7jZkeSysJkHAVew6RaaBh3r1zTefpdq9Kf5geFp19P3nUXB3t"

Run the Package From the Substreams Registry

substreams gui https://spkg.io/streamingfast/solana-explorer-v0.2.0.spkg \
    map_filter_transactions -e mainnet.sol.streamingfast.io:443 \
    --start-block 153000028 --stop-block +1

Inspect the Code

The map_filter_transaction.rs file contains the source of the module. The output emitted by the module is defined as a Protobuf in the /proto/transactions.proto file of the project.


message Instructions {
  repeated Instruction instructions = 1;
}

message Instruction {
  string program_id = 1;
  repeated string accounts = 2;
  string data = 3;
}

message Transactions {
  repeated Transaction transactions = 1;
}

message Transaction {
  repeated string signatures = 1;

  repeated Instruction instructions = 2;
}

The output of the Substreams is the Transactions Protobuf object:

#[substreams::handlers::map]
fn map_filter_transactions(params: String, blk: Block) -> Result<Transactions, Vec<substreams::errors::Error>> {
    let filters = parse_filters_from_params(params)?; // 1.

    let mut transactions: Vec<Transaction> = Vec::new();

    blk.transactions // 2.
        .iter()
        .filter(|tx| apply_filter(tx, &filters)) // 3.
        .for_each(|tx| {
            let msg = tx.transaction.as_ref().unwrap().message.as_ref().unwrap();
            let acct_keys = tx.resolved_accounts(); // 4.

            let insts: Vec<Instruction> = msg
                .instructions // 5.
                .iter()
                .map(|inst| Instruction { // 6.
                    program_id: bs58::encode(acct_keys[inst.program_id_index as usize].to_vec()).into_string(),
                    accounts: inst
                        .accounts
                        .iter()
                        .map(|acct| bs58::encode(acct_keys[*acct as usize].to_vec()).into_string())
                        .collect(),
                    data: bs58::encode(&inst.data).into_string(),
                })
                .collect();

            let t = Transaction { // 7.
                signatures: tx
                    .transaction
                    .as_ref()
                    .unwrap()
                    .signatures
                    .iter()
                    .map(|sig| bs58::encode(sig).into_string())
                    .collect(),
                instructions: insts,
            };
            transactions.push(t);
        });

    Ok(Transactions { transactions })
}
  1. Parse the filters provided as a parameter to the module function. The signature to filter is defined as a parameter in the Substreams Manifest, and is then injected as a string in the Rust function.

  2. Iterate over the transactions of the block.

  3. Filter the transactions by invoking the apply_filters function. This function only keeps transactions containing the signature passed as a parameter.

  4. Iterate over the instructions of the transaction.

  5. Map every instruction to the Instruction output Protobuf data model of the Substreams, keeping only three fields: program_id, accounts and data.

  6. Map the transaction to the Transaction output Protobuf data model of the Substreams.

The Solana Explorer is also available as a Substreams package in the . You can simply run it:

Get the accounts of the transaction. The resolved_accounts() method includes accounts stored in the .

Substreams Registry
Address Lookup Tables