mod.rs
Overview
This file defines the BlockchainQuery struct and implements its GraphQL query interface for accessing blockchain-related data such as accounts, blocks, messages, transactions, and their paginated collections. It provides asynchronous methods to fetch detailed blockchain entities, support cursor-based pagination, and resolve nested relationships between blockchain objects using DataLoader for efficient batching and caching.
The file organizes blockchain API queries in a GraphQL schema context, leveraging several submodules (account, blocks, transactions) that encapsulate domain-specific queries and types. It interacts heavily with the database layer (db module), GraphQL extensions, and asynchronous data loaders.
Modules
account: Handles account-specific blockchain queries and types.
blocks: Contains block-related queries, pagination edges, and connection types.
transactions: Manages transaction and message queries and related types.
Struct: BlockchainQuery<'a>
Represents the root GraphQL query object for blockchain-related data. It holds a reference to the GraphQL Context which provides access to dependencies such as database connection pools and DataLoader instances.
Fields:
Field | Type | Description |
|---|---|---|
|
| Reference to the GraphQL query context. |
Implementation of BlockchainQuery
The GraphQL query methods are implemented using the #[Object] macro from async_graphql. Each method corresponds to a GraphQL query node or connection, returning blockchain entities or paginated lists.
Method: account
async fn account(&self, address: String) -> Option<BlockchainAccountQuery<'_>>
Purpose: Fetches a single blockchain account by its address.
Parameters:
address: The blockchain account's address string.
Returns: An optional
BlockchainAccountQuerystruct that encapsulates the account query with preloaded data if available.Usage Example:
query {
blockchain {
account(address: "0x123...") {
// fields from BlockchainAccountQuery
}
}
}
Method: accounts
async fn accounts(
&self,
code_hash: Option<String>,
first: Option<i32>,
after: Option<String>,
last: Option<i32>,
before: Option<String>,
) -> Option<Connection<...>>
Purpose: Returns a paginated list of blockchain accounts, supporting cursor-based pagination.
Parameters:
code_hash: Optional filter to select accounts by their code hash.first: Number of items to fetch after theaftercursor (mutually exclusive withlast).after: Cursor to paginate after.last: Number of items to fetch before thebeforecursor (mutually exclusive withfirst).before: Cursor to paginate before.
Returns: A
Connectionobject containingBlockchainAccountQueryedges, supporting GraphQL Relay pagination.Implementation Details:
Utilizesasync_graphql::connection::queryhelper with a closure that constructs database query arguments and fetches accounts from thedb::account::Account::blockchain_accountsfunction. It calculates pagination boundaries and wraps results into aConnectionwith edges and cursors.Error Handling: Logs and returns
Noneon query failure.Usage Example:
query {
blockchain {
accounts(first: 10, after: "cursor") {
edges {
node {
address
// other account fields
}
}
pageInfo {
hasNextPage
hasPreviousPage
}
}
}
}
Method: block
async fn block(&self, hash: String) -> Option<BlockchainBlock>
Purpose: Retrieves a single blockchain block by its hash.
Parameters:
hash: The hash string of the block.
Returns: Optional
BlockchainBlockrepresenting the block data.Implementation Details:
UsesBlockLoaderDataLoader to asynchronously fetch the block. Optionally loads related out messages if requested in the GraphQL query lookahead. There is commented-out code hinting at future or conditional loading of inbound messages.Usage Example:
query {
blockchain {
block(hash: "blockhash") {
chainOrder
outMessages {
id
// other message fields
}
}
}
}
Method: blocks
async fn blocks(
&self,
_allow_latest_inconsistent_data: Option<bool>,
block_seq_no_range: Option<BlockchainMasterSeqNoFilter>,
min_tr_count: Option<i32>,
max_tr_count: Option<i32>,
first: Option<i32>,
after: Option<String>,
last: Option<i32>,
before: Option<String>,
) -> Option<Connection<...>>
Purpose: Provides paginated access to blockchain blocks, with optional filtering by sequence number range and transaction count.
Parameters:
_allow_latest_inconsistent_data: Flag to relax consistency guarantees on recent data for lower latency.block_seq_no_range: Optional filter specifying a range of block master sequence numbers.min_tr_count,max_tr_count: Optional filters for minimum or maximum number of transactions in a block.first,after,last,before: Standard Relay pagination parameters.
Returns: A paginated connection of
BlockchainBlocknodes.Implementation Details:
Constructs query arguments for the DB calldb::block::Block::blockchain_blocks. It derives pagination boundaries and converts DB blocks into GraphQL blocks. Uses thequeryhelper for cursor-based pagination.Usage Example:
query {
blockchain {
blocks(first: 5, after: "cursor") {
edges {
node {
chainOrder
trCount
}
}
pageInfo {
hasNextPage
}
}
}
}
Method: message
async fn message(&self, hash: String) -> Option<BlockchainMessage>
Purpose: Fetches a blockchain message by its hash.
Parameters:
hash: The message hash string.
Returns: Optional
BlockchainMessage.Implementation Details:
EmploysMessageLoaderDataLoader for fetching the message. Conditionally loads related source and destination transactions if requested in the GraphQL query. The destination transaction is queried from the DB by inbound message ID, and loaded viaTransactionLoader.Usage Example:
query {
blockchain {
message(hash: "msghash") {
body
srcTransaction {
id
}
dstTransaction {
id
}
}
}
}
Method: transaction
async fn transaction(&self, hash: String) -> Option<BlockchainTransaction>
Purpose: Retrieves a blockchain transaction by its hash.
Parameters:
hash: The transaction hash string.
Returns: Optional
BlockchainTransaction.Implementation Details:
Loads the transaction usingTransactionLoader. If requested by the query, loads the inbound message and outbound messages usingMessageLoader. Outbound messages are collected as an optional vector.Usage Example:
query {
blockchain {
transaction(hash: "txhash") {
id
inMessage {
id
}
outMessages {
id
}
}
}
}
Method: transactions
async fn transactions(
&self,
_allow_latest_inconsistent_data: Option<bool>,
min_balance_delta: Option<String>,
max_balance_delta: Option<String>,
code_hash: Option<String>,
first: Option<i32>,
after: Option<String>,
last: Option<i32>,
before: Option<String>,
) -> Option<Connection<...>>
Purpose: Provides cursor-based paginated access to blockchain transactions with optional filters.
Parameters:
_allow_latest_inconsistent_data: Controls consistency vs latency for recent data.min_balance_delta,max_balance_delta: Optional string filters on transaction balance delta.code_hash: Optional filter by the code hash of the account before execution.Pagination cursors:
first,after,last,before.
Returns: A Relay-style paginated connection of
BlockchainTransactionnodes.Implementation Details:
Queries transactions from the DB usingblockchain_transactionsmethod with filters. Uses DataLoader to batch-load inbound and outbound messages for each transaction if requested by the selection set. ConstructsConnectionedges with cursors from transaction chain order.Usage Example:
query {
blockchain {
transactions(first: 20) {
edges {
node {
id
inMessage {
id
}
outMessages {
id
}
}
}
pageInfo {
hasPreviousPage
hasNextPage
}
}
}
}
Important Implementation Details
Asynchronous Data Loading: Uses
async_graphql::dataloader::DataLoaderfor batch and cache optimized fetching of blocks, messages, and transactions.Cursor-based Pagination: All collection queries implement Relay-style cursor pagination using
async_graphql::connection::queryhelper, supportingfirst/lastwithafter/before.Conditional Field Loading: Uses GraphQL query lookahead (
self.ctx.look_ahead()) to determine if related nested fields (e.g., messages within transactions) need to be loaded, optimizing data fetching.Error Handling: Logs errors during database queries and returns
Noneto the client gracefully.Database Interaction: Calls into the
dbmodule (e.g.,db::account::Account::blockchain_accounts) to execute actual SQL queries usingsqlx::SqlitePool.
Interactions with Other System Components
Database Layer (
db): Queries blockchain data such as accounts, blocks, and transactions.GraphQL Schema Extensions (
graphql_ext): Provides extended GraphQL types for blockchain entities.DataLoaders: Custom loaders (
BlockLoader,MessageLoader,TransactionLoader) used to batch and cache database or API calls to optimize query execution.Submodules (
account,blocks,transactions): Provide specialized queries, types, and pagination edges for their respective blockchain entities.
Visual Diagram: Structure of BlockchainQuery and Relationships
classDiagram
class BlockchainQuery {
+ctx: Context
+account(address)
+accounts(filter, pagination)
+block(hash)
+blocks(filter, pagination)
+message(hash)
+transaction(hash)
+transactions(filter, pagination)
}
BlockchainQuery --> BlockchainAccountQuery : account()
BlockchainQuery --> BlockchainBlock : block()
BlockchainQuery --> BlockchainTransaction : transaction()
BlockchainQuery --> BlockchainMessage : message()
BlockchainQuery --> Connection : accounts(), blocks(), transactions()
BlockchainBlock --> MessageLoader : loads out_messages
BlockchainTransaction --> MessageLoader : loads in_message, out_messages
BlockchainMessage --> TransactionLoader : loads src_transaction, dst_transaction
This diagram presents the BlockchainQuery as the central query interface with methods returning blockchain entities or paginated connections. It shows the use of DataLoader instances to resolve nested relationships efficiently.