Query

Struct Query 

Source
pub struct Query {
Show 13 fields pub from_block: u64, pub to_block: Option<u64>, pub logs: Vec<LogSelection>, pub transactions: Vec<TransactionSelection>, pub traces: Vec<TraceSelection>, pub blocks: Vec<BlockSelection>, pub include_all_blocks: bool, pub field_selection: FieldSelection, pub max_num_blocks: Option<usize>, pub max_num_transactions: Option<usize>, pub max_num_logs: Option<usize>, pub max_num_traces: Option<usize>, pub join_mode: JoinMode,
}
Expand description

A hypersync query that defines what blockchain data to retrieve.

The Query struct provides a fluent builder API for constructing complex blockchain queries using hypersync. It allows you to specify block ranges, filter by logs/transactions/traces/blocks, select which fields to return, and control query behavior like join modes.

§Core Concepts

  • Block Range: Define the range of blocks to query with from_block and optional to_block
  • Filters: Specify what data to match using LogFilter, TransactionFilter, BlockFilter, and TraceFilter
  • Field Selection: Choose which fields to include in the response to optimize performance
  • Join Modes: Control how different data types are related and joined

§Performance Tips

  • Specify the minimum FieldSelection to only request the data you need
  • Use specific filters rather than broad queries when possible
  • Be mindful of setting include_all_blocks: true as it can significantly increase response size
  • Traces are only available on select hypersync instances

§Basic Examples

use hypersync_net_types::{
    Query, FieldSelection, LogFilter, BlockFilter, TransactionFilter,
    block::BlockField, log::LogField, transaction::TransactionField
};

// Simple log query for USDT transfers
let usdt_transfers = Query::new()
    .from_block(18_000_000)
    .to_block_excl(18_001_000)
    .select_block_fields([BlockField::Number, BlockField::Timestamp])
    .select_log_fields([LogField::Address, LogField::Data, LogField::Topic0, LogField::Topic1, LogField::Topic2])
    .select_transaction_fields([TransactionField::Hash, TransactionField::From, TransactionField::To])
    .where_logs(
        LogFilter::all()
            .and_address(["0xdac17f958d2ee523a2206206994597c13d831ec7"])? // USDT contract
            .and_topic0(["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"])? // Transfer event
    );

§Advanced Examples

use hypersync_net_types::{
    Query, FieldSelection, JoinMode, LogFilter, TransactionFilter, Selection,
    block::BlockField, log::LogField, transaction::TransactionField
};

// Complex query with multiple different filter combinations and exclusions
let complex_query = Query::new()
    .from_block(18_000_000)
    .to_block_excl(18_010_000)
    .join_mode(JoinMode::JoinAll)
    .select_block_fields(BlockField::all())
    .select_transaction_fields(TransactionField::all())
    .select_log_fields(LogField::all())
    .where_logs(
        // Transfer events from USDT and USDC contracts (multiple addresses in one filter)
        LogFilter::all()
            .and_address([
                "0xdac17f958d2ee523a2206206994597c13d831ec7", // USDT
                "0xa0b86a33e6c11c8c0c5c0b5e6adee30d1a234567", // USDC
            ])?
            .and_topic0(["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"])? // Transfer event
        .or(
            // Approval events from any ERC20 contract (different topic combination)
            LogFilter::all()
                .and_topic0(["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"])? // Approval event
        )
        .or(
            // Swap events from Uniswap V2 pairs (another distinct filter combination)
            LogFilter::all()
                .and_topic0(["0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822"])? // Swap event
        )
    )
    .where_transactions(
        TransactionFilter::all()
            .and_sighash([
                "0xa9059cbb", // transfer(address,uint256)
                "0x095ea7b3", // approve(address,uint256)
            ])?
            .or(TransactionFilter::all().and_status(0)) // Failed transactions
    );

§Exclusion with and_not

use hypersync_net_types::{Query, FieldSelection, LogFilter, Selection, log::LogField};

// Query for ERC20 transfers but exclude specific problematic contracts
let filtered_query = Query::new()
    .from_block(18_000_000)
    .to_block_excl(18_001_000)
    .select_log_fields([LogField::Address, LogField::Data, LogField::Topic0, LogField::Topic1, LogField::Topic2])
    .where_logs(
        // Include Transfer events from all contracts, but exclude specific problematic contracts
        Selection::new(
            LogFilter::all()
                .and_topic0(["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"])? // Transfer event
        )
        // But exclude specific problematic contracts
        .and_not(
            LogFilter::all()
                .and_address([
                    "0x1234567890123456789012345678901234567890", // Problematic contract 1
                    "0x0987654321098765432109876543210987654321", // Problematic contract 2
                ])?
        )
    );

§Builder Pattern

The Query struct uses a fluent builder pattern where all methods return Self, allowing for easy chaining:

use hypersync_net_types::{Query, FieldSelection, JoinMode, block::BlockField};

let query = Query::new()
    .from_block(18_000_000)
    .to_block_excl(18_010_000)
    .join_mode(JoinMode::Default)
    .include_all_blocks()
    .select_block_fields(BlockField::all());

Fields§

§from_block: u64

The block to start the query from

§to_block: Option<u64>

The block to end the query at. If not specified, the query will go until the end of data. Exclusive, the returned range will be [from_block..to_block).

The query will return before it reaches this target block if it hits the time limit configured on the server. The user should continue their query by putting the next_block field in the response into from_block field of their next query. This implements pagination.

§logs: Vec<LogSelection>§transactions: Vec<TransactionSelection>

List of transaction selections, the query will return transactions that match any of these selections

§traces: Vec<TraceSelection>

List of trace selections, the query will return traces that match any of these selections

§blocks: Vec<BlockSelection>

List of block selections, the query will return blocks that match any of these selections

§include_all_blocks: bool

Whether to include all blocks regardless of if they are related to a returned transaction or log. Normally the server will return only the blocks that are related to the transaction or logs in the response. But if this is set to true, the server will return data for all blocks in the requested range [from_block, to_block).

§field_selection: FieldSelection

Field selection. The user can select which fields they are interested in, requesting less fields will improve query execution time and reduce the payload size so the user should always use a minimal number of fields.

§max_num_blocks: Option<usize>

Maximum number of blocks that should be returned, the server might return more blocks than this number but it won’t overshoot by too much.

§max_num_transactions: Option<usize>

Maximum number of transactions that should be returned, the server might return more transactions than this number but it won’t overshoot by too much.

§max_num_logs: Option<usize>

Maximum number of logs that should be returned, the server might return more logs than this number but it won’t overshoot by too much.

§max_num_traces: Option<usize>

Maximum number of traces that should be returned, the server might return more traces than this number but it won’t overshoot by too much.

§join_mode: JoinMode

Selects join mode for the query, Default: join in this order logs -> transactions -> traces -> blocks JoinAll: join everything to everything. For example if logSelection matches log0, we get the associated transaction of log0 and then we get associated logs of that transaction as well. Applies similarly to blocks, traces. JoinNothing: join nothing.

Implementations§

Source§

impl Query

Source

pub fn new() -> Self

Source

pub fn from_block(self, block_number: u64) -> Self

Set the starting block number the query should execute from. This is inclusive, meaning the query will include the given block number. If not specified, the query will start from the the genesis block.

Source

pub fn to_block_excl(self, block_number: u64) -> Self

Set the the ending block number the query should execute to. This is exclusive, meaning the query will execute up to but not including the given block number.

eg. the following will return blocks 0 to 99.

 use hypersync_net_types::Query;
 Query::new().to_block_excl(100);

If not specified, the query will end at the tip of the chain.

Source

pub fn where_logs<I, T>(self, logs: I) -> Self
where I: Into<AnyOf<T>>, T: Into<LogSelection>,

Set log filters that the query will match against.

This method accepts any iterable of items that can be converted to LogSelection. Common input types include LogFilter objects and LogSelection objects. The query will return logs that match any of the provided filters.

§Arguments
  • logs - An iterable of log filters/selections to match
§Examples
use hypersync_net_types::{Query, LogFilter};

// Single filter for logs from multiple contracts
let query = Query::new()
    .from_block(18_000_000)
    .where_logs(
        LogFilter::all()
            .and_address([
                "0xdac17f958d2ee523a2206206994597c13d831ec7", // USDT
                "0xa0b86a33e6c11c8c0c5c0b5e6adee30d1a234567", // USDC
            ])?
    );

// Multiple different filter combinations using .or()
let query = Query::new()
    .where_logs(
        // Transfer events from specific contracts
        LogFilter::all()
            .and_address(["0xdac17f958d2ee523a2206206994597c13d831ec7"])?
            .and_topic0(["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"])? // Transfer
        .or(
            // Approval events from any contract
            LogFilter::all()
                .and_topic0(["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"])? // Approval
        )
    );
Source

pub fn where_blocks<I, T>(self, blocks: I) -> Self
where I: Into<AnyOf<T>>, T: Into<BlockSelection>,

Set block filters that the query will match against.

This method accepts any iterable of items that can be converted to BlockSelection. Common input types include BlockFilter objects and BlockSelection objects. The query will return blocks that match any of the provided filters.

§Arguments
  • blocks - An iterable of block filters/selections to match
§Examples
use hypersync_net_types::{Query, BlockFilter};

// Single filter for blocks by specific hashes
let query = Query::new()
    .from_block(18_000_000)
    .where_blocks(
        BlockFilter::all()
            .and_hash(["0x40d008f2a1653f09b7b028d30c7fd1ba7c84900fcfb032040b3eb3d16f84d294"])?
    );

// Multiple filter combinations using .or()
let query = Query::new()
    .where_blocks(
        BlockFilter::all()
            .and_hash(["0x40d008f2a1653f09b7b028d30c7fd1ba7c84900fcfb032040b3eb3d16f84d294"])?
        .or(
            BlockFilter::all()
                .and_miner([
                    "0xdac17f958d2ee523a2206206994597c13d831ec7", // Mining pool 1
                    "0xa0b86a33e6c11c8c0c5c0b5e6adee30d1a234567", // Mining pool 2
                ])?
        )
    );
Source

pub fn where_transactions<I, T>(self, transactions: I) -> Self
where I: Into<AnyOf<T>>, T: Into<TransactionSelection>,

Set transaction filters that the query will match against.

This method accepts any iterable of items that can be converted to TransactionSelection. Common input types include TransactionFilter objects and TransactionSelection objects. The query will return transactions that match any of the provided filters.

§Arguments
  • transactions - An iterable of transaction filters/selections to match
§Examples
use hypersync_net_types::{Query, TransactionFilter};

// Single filter for transactions from specific addresses
let query = Query::new()
    .from_block(18_000_000)
    .where_transactions(
        TransactionFilter::all()
            .and_from(["0xa0b86a33e6c11c8c0c5c0b5e6adee30d1a234567"])?
    );

// Multiple filter combinations using .or()
let transfer_sig = "0xa9059cbb"; // transfer(address,uint256)
let query = Query::new()
    .where_transactions(
        TransactionFilter::all().and_sighash([transfer_sig])?
        .or(
            TransactionFilter::all().and_status(0) // Failed transactions
        )
    );
Source

pub fn where_traces<I, T>(self, traces: I) -> Self
where I: Into<AnyOf<T>>, T: Into<TraceSelection>,

Set trace filters that the query will match against.

This method accepts any iterable of items that can be converted to TraceSelection. Common input types include TraceFilter objects and TraceSelection objects. The query will return traces that match any of the provided filters.

§Availability

Note: Trace data is only available on select hypersync instances. Not all blockchain networks provide trace data, and it requires additional infrastructure to collect and serve. Check your hypersync instance documentation to confirm trace availability for your target network.

§Arguments
  • traces - An iterable of trace filters/selections to match
§Examples
use hypersync_net_types::{Query, TraceFilter};

// Single filter for traces from specific caller addresses
let query = Query::new()
    .from_block(18_000_000)
    .where_traces(
        TraceFilter::all()
            .and_from(["0xa0b86a33e6c11c8c0c5c0b5e6adee30d1a234567"])?
    );

// Multiple filter combinations using .or()
let transfer_sig = "0xa9059cbb"; // transfer(address,uint256)
let query = Query::new()
    .where_traces(
        TraceFilter::all().and_call_type(["create", "suicide"])
        .or(
            TraceFilter::all().and_sighash([transfer_sig])?
        )
    );
Source

pub fn select_log_fields<I>(self, fields: I) -> Self
where I: IntoIterator, I::Item: Into<LogField>,

Select specific log fields to include in query results.

This method allows you to specify which log fields should be returned in the query response. Only the selected fields will be included, which can improve performance and reduce payload size. This replaces the previous select_fields(FieldSelection::new().log(...)) pattern.

§Arguments
  • fields - An iterable of LogField values to select
§Examples
use hypersync_net_types::{Query, log::LogField, transaction::TransactionField};

// Select essential log fields
let query = Query::new()
    .from_block(18_000_000)
    .select_log_fields([LogField::Address, LogField::Data, LogField::Topic0]);

// Select all log fields for comprehensive event data
let query = Query::new()
    .select_log_fields(LogField::all());

// Select all topic fields for event analysis
let query = Query::new()
    .select_log_fields([
        LogField::Topic0,
        LogField::Topic1,
        LogField::Topic2,
        LogField::Topic3,
    ]);

// Chain with other field selections
let query = Query::new()
    .select_log_fields([LogField::Address, LogField::Data])
    .select_transaction_fields([TransactionField::Hash]);
Source

pub fn select_transaction_fields<I>(self, fields: I) -> Self

Select specific transaction fields to include in query results.

This method allows you to specify which transaction fields should be returned in the query response. Only the selected fields will be included, which can improve performance and reduce payload size. This replaces the previous select_fields(FieldSelection::new().transaction(...)) pattern.

§Arguments
  • fields - An iterable of TransactionField values to select
§Examples
use hypersync_net_types::{Query, transaction::TransactionField, block::BlockField};

// Select specific transaction fields
let query = Query::new()
    .from_block(18_000_000)
    .select_transaction_fields([TransactionField::Hash, TransactionField::From, TransactionField::To]);

// Select all transaction fields for complete transaction data
let query = Query::new()
    .select_transaction_fields(TransactionField::all());

// Select fields related to gas and value
let query = Query::new()
    .select_transaction_fields([
        TransactionField::GasPrice,
        TransactionField::GasUsed,
        TransactionField::Value,
    ]);

// Chain with other field selections
let query = Query::new()
    .select_transaction_fields([TransactionField::Hash, TransactionField::Value])
    .select_block_fields([BlockField::Number]);
Source

pub fn select_trace_fields<I>(self, fields: I) -> Self

Select specific trace fields to include in query results.

This method allows you to specify which trace fields should be returned in the query response. Only the selected fields will be included, which can improve performance and reduce payload size. This replaces the previous select_fields(FieldSelection::new().trace(...)) pattern.

§Availability

Note: Trace data is only available on select hypersync instances. Not all blockchain networks provide trace data, and it requires additional infrastructure to collect and serve. Check your hypersync instance documentation to confirm trace availability for your target network.

§Arguments
  • fields - An iterable of TraceField values to select
§Examples
use hypersync_net_types::{Query, trace::TraceField, log::LogField};

// Select basic trace information
let query = Query::new()
    .from_block(18_000_000)
    .select_trace_fields([TraceField::From, TraceField::To, TraceField::Value]);

// Select all trace fields for comprehensive trace analysis
let query = Query::new()
    .select_trace_fields(TraceField::all());

// Select trace execution details
let query = Query::new()
    .select_trace_fields([
        TraceField::CallType,
        TraceField::Input,
        TraceField::Output,
        TraceField::Gas,
        TraceField::GasUsed,
    ]);

// Chain with other field selections
let query = Query::new()
    .select_trace_fields([TraceField::From, TraceField::To])
    .select_log_fields([LogField::Address]);
Source

pub fn select_block_fields<I>(self, fields: I) -> Self

Select specific block fields to include in query results.

This method allows you to specify which block fields should be returned in the query response. Only the selected fields will be included, which can improve performance and reduce payload size. This replaces the previous select_fields(FieldSelection::new().block(...)) pattern.

§Arguments
  • fields - An iterable of BlockField values to select
§Examples
use hypersync_net_types::{Query, block::BlockField, transaction::TransactionField};

// Select specific block fields
let query = Query::new()
    .from_block(18_000_000)
    .select_block_fields([BlockField::Number, BlockField::Hash, BlockField::Timestamp]);

// Select all block fields for comprehensive data
let query = Query::new()
    .select_block_fields(BlockField::all());

// Select essential block metadata
let query = Query::new()
    .select_block_fields([
        BlockField::Number,
        BlockField::Hash,
        BlockField::ParentHash,
        BlockField::Timestamp,
    ]);

// Chain with other field selections
let query = Query::new()
    .select_block_fields([BlockField::Number, BlockField::Timestamp])
    .select_transaction_fields([TransactionField::Hash]);
Source

pub fn join_mode(self, join_mode: JoinMode) -> Self

Set the join mode for the query to control how different data types are related.

Join mode determines how hypersync correlates data between blocks, transactions, logs, and traces. This affects which additional related data is included in the response beyond what your filters directly match.

§Arguments
  • join_mode - The JoinMode to use for the query
§Join Modes:
  • JoinMode::Default: Join in order logs → transactions → traces → blocks
  • JoinMode::JoinAll: Join everything to everything (comprehensive but larger responses)
  • JoinMode::JoinNothing: No joins, return only directly matched data
§Examples
use hypersync_net_types::{Query, JoinMode, LogFilter};

// Default join mode - get transactions and blocks for matching logs
let query = Query::new()
    .from_block(18_000_000)
    .join_mode(JoinMode::Default)
    .where_logs(LogFilter::all());

// Join everything - comprehensive data for analysis
let query = Query::new()
    .from_block(18_000_000)
    .join_mode(JoinMode::JoinAll)
    .where_logs(LogFilter::all());

// No joins - only the exact logs that match the filter
let query = Query::new()
    .from_block(18_000_000)
    .join_mode(JoinMode::JoinNothing)
    .where_logs(LogFilter::all());
Source

pub fn include_all_blocks(self) -> Self

Set whether to include all blocks in the requested range, regardless of matches.

By default, hypersync only returns blocks that are related to matched transactions, logs, or traces. Setting this to true forces the server to return data for all blocks in the range [from_block, to_block), even if they don’t contain any matching transactions or logs.

§Use Cases:
  • Block-level analytics requiring complete block data
  • Ensuring no blocks are missed in sequential processing
  • Getting block headers for every block in a range
§Performance Note:

Setting this to true can significantly increase response size and processing time, especially for large block ranges. Use judiciously.

§Examples
use hypersync_net_types::{Query, LogFilter, FieldSelection, block::BlockField};

// Include all blocks for complete block header data
let query = Query::new()
    .from_block(18_000_000)
    .to_block_excl(18_000_100)
    .include_all_blocks()
    .select_block_fields([BlockField::Number, BlockField::Hash, BlockField::Timestamp]);

// Normal mode - only blocks with matching logs
let query = Query::new()
    .from_block(18_000_000)
    .where_logs(
        LogFilter::all()
            .and_address(["0xdac17f958d2ee523a2206206994597c13d831ec7"])?
    );
Source

pub fn from_capnp_query_body_reader( query_body_reader: &Reader<'_>, from_block: u64, to_block: Option<u64>, ) -> Result<Self, Error>

Trait Implementations§

Source§

impl CapnpReader<Owned> for Query

Source§

fn from_reader(query: Reader<'_>) -> Result<Self, Error>

Source§

impl Clone for Query

Source§

fn clone(&self) -> Query

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Query

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Query

Source§

fn default() -> Query

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Query

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for Query

Source§

fn eq(&self, other: &Query) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for Query

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for Query

Auto Trait Implementations§

§

impl Freeze for Query

§

impl !RefUnwindSafe for Query

§

impl Send for Query

§

impl Sync for Query

§

impl Unpin for Query

§

impl !UnwindSafe for Query

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,