message.rs
Overview
This file defines the data structures and database query operations related to blockchain messages within the system. It provides models representing messages and related query arguments, along with asynchronous methods to retrieve message data from a SQLite database. The primary focus is on querying messages associated with blockchain accounts, blocks, and transactions, including support for pagination and filtering by message types and other criteria.
Data Structures and Classes
InBlockMessage
A lightweight struct representing a message included in a specific blockchain block.
Fields:
msg_id: String— Identifier of the message.transaction_id: String— Identifier of the transaction containing the message.
This struct is used primarily for listing messages tied to blocks.
AccountMessagesQueryArgs
Encapsulates filter and pagination parameters used when querying messages related to blockchain accounts.
Fields:
allow_latest_inconsistent_data: Option<bool>— Optional flag allowing queries to include possibly inconsistent latest data.master_seq_no_range: Option<BlockchainMasterSeqNoFilter>— Optional range filter on the master sequence number (see BlockchainMasterSeqNoFilter).counterparties: Option<Vec<String>>— Optional list of counterparty account addresses.msg_type: Option<Vec<BlockchainMessageTypeFilterEnum>>— Optional list of message types to filter by (see BlockchainMessageTypeFilterEnum).min_value: Option<String>— Optional minimum value filter.pagination: PaginationArgs— Pagination parameters (see PaginationArgs).
Methods:
new(...) -> Self
Constructor with parameters corresponding to the fields above.has_msg_type(value: BlockchainMessageTypeFilterEnum) -> bool
Checks if a specific message type is included in the filter list or if no filter is specified (defaults to true).Convenience methods to check for specific message type categories:
has_ext_in() -> boolhas_ext_out() -> boolhas_int_in() -> boolhas_int_out() -> bool
Message
Represents a blockchain message record with detailed fields mapped to a database row.
Fields:
rowid: Option<i64>— Internal database row ID (skipped in SQL operations).id: String— Unique message ID.boc: Option<Vec<u8>>— Bag of cells data blob.body: Option<Vec<u8>>— Message body blob.body_hash: Option<String>— Hash of the message body.status: Option<i64>— Status code of the message.transaction_id: Option<String>— ID of the associated transaction.msg_type: Option<i64>— Message type as a numeric code.src: Option<String>— Source account address.src_workchain_id: Option<i64>— Source workchain ID.dst: Option<String>— Destination account address.dst_workchain_id: Option<i64>— Destination workchain ID.import_fee: Option<String>— Fee paid for importing the message.fwd_fee: Option<String>— Forwarding fee.bounce: Option<i64>— Bounce flag.bounced: Option<i64>— Bounce result flag.value: Option<String>— Message value.value_other: Option<Vec<u8>>— Additional value data.created_lt: Option<String>— Created logical time.created_at: Option<i64>— Created timestamp.dst_chain_order: Option<String>— Chain order for destination.src_chain_order: Option<String>— Chain order for source.proof: Option<String>— Proof data.code: Option<Vec<u8>>— Code blob.code_hash: Option<String>— Hash of the code.data: Option<Vec<u8>>— Data blob.data_hash: Option<String>— Hash of the data.src_dapp_id: Option<String>— Source dapp identifier.msg_chain_order: Option<String>— Message chain order.
Methods:
listasync fn list( pool: &SqlitePool, filter: String, order_by: String, limit: Option<i32>, ) -> anyhow::Result<Vec<Message>>Retrieves a list of messages applying a raw SQL filter and ordering clause with an optional limit on the number of results.
Parameters:
pool— Database connection pool.filter— SQL filter string for the WHERE clause.order_by— SQL ORDER BY clause.limit— Optional maximum number of messages to retrieve.
Returns: A vector of
Messageinstances matching the query criteria.Usage Example:
let messages = Message::list(&db_pool, "src='some_account'", "ORDER BY created_at DESC", Some(100)).await?;Implementation Detail: Uses
sqlx::QueryBuilderto construct and execute the query, with a debug log of the SQL for traceability.
in_block_msgsasync fn in_block_msgs( pool: &SqlitePool, block_id: String, ) -> anyhow::Result<Vec<InBlockMessage>>Lists all messages included as inbound messages in transactions of a specified block.
Parameters:
pool— Database connection pool.block_id— Identifier of the block.
Returns: Vector of
InBlockMessagewith message and transaction IDs.Implementation Detail: Performs a join query across blocks, transactions, and messages tables to collect inbound messages for the block.
account_messagesasync fn account_messages( pool: &SqlitePool, account: String, args: &AccountMessagesQueryArgs, ) -> anyhow::Result<Vec<Message>>Retrieves messages associated with a specific account, applying detailed filtering based on message direction, type, pagination, and sequence number range.
Parameters:
pool— Database connection pool.account— Blockchain account address.args— Query argument struct with filters and pagination.
Returns: Vector of
Messageinstances matching the criteria.Implementation Details:
Determines whether to query inbound, outbound, or both types of messages based on message type filters.
Constructs SQL WHERE clauses dynamically for account involvement (
srcordst), message types, pagination cursors (after,before), and master sequence number ranges.Orders results based on pagination direction (
ASC/DESC).Reverses the result vector when paginating backward to present results in chronological order.
Usage Example:
let args = AccountMessagesQueryArgs::new( None, Some(seq_no_filter), None, Some(vec![BlockchainMessageTypeFilterEnum::ExtIn]), None, pagination_args, ); let messages = Message::account_messages(&db_pool, "account_id".to_string(), &args).await?;
account_eventsasync fn account_events( pool: &SqlitePool, account: String, pagination: &PaginationArgs, ) -> anyhow::Result<Vec<Message>>Retrieves messages classified as events originating from a specific account, supporting pagination.
Parameters:
pool— Database connection pool.account— Blockchain account address.pagination— Pagination arguments.
Returns: Vector of
Messageinstances that are events from the account.Implementation Details:
Filters messages with
srcmatching the account.Optionally restricts message type to
2(events) unless the featurestore_events_onlyis disabled.Applies pagination filters based on
msg_chain_order.Orders results according to pagination direction.
Returns results reversed when paginating backward.
Important Implementation Details and Algorithms
Dynamic SQL Query Building:
Query construction utilizessqlx::QueryBuilderto safely build SQL queries with dynamic WHERE clauses based on the filtering options provided inAccountMessagesQueryArgsand pagination arguments.Pagination Handling:
Messages are paginated using cursor-based pagination withbeforeandaftercursors and a limit. The ordering field (cursor_field) depends on the message direction and whether inbound/outbound messages are requested.Message Type Filtering:
Message types are filtered using integer codes derived from the enumBlockchainMessageTypeFilterEnum, allowing efficient SQL filtering withINclauses.Handling Inbound and Outbound Messages:
The code distinguishes inbound (dst) and outbound (src) messages and dynamically adjusts SQL WHERE clauses and ordering fields accordingly.Reversing Result Sets for Backward Pagination:
When paginating backward, the query fetches results in descending order but reverses the vector before returning to maintain chronological order from the API perspective.Use of
anyhow::Result:
All asynchronous functions returnanyhow::Resultto encapsulate potential database errors with context.
Interaction with Other Parts of the System
Database Layer:
The file depends onsqlxfor interacting with a SQLite database, mapping rows to Rust structs using theFromRowtrait.GraphQL Schema:
It imports types fromcrate::schema::graphql::queryandcrate::schema::graphql_ext::blockchain_api::account, indicating that these message queries are likely exposed via a GraphQL API (see PaginationArgs, BlockchainMessageTypeFilterEnum, and BlockchainMasterSeqNoFilter).Helpers and Defaults:
Utilizes helper functions such asu64_to_stringand default constants likedefaults::QUERY_BATCH_SIZEfor query limit defaults.
Mermaid Class Diagram
classDiagram
class InBlockMessage {
+msg_id: String
+transaction_id: String
}
class AccountMessagesQueryArgs {
-allow_latest_inconsistent_data: Option<bool>
-master_seq_no_range: Option<BlockchainMasterSeqNoFilter>
-counterparties: Option<Vec<String>>
-msg_type: Option<Vec<BlockchainMessageTypeFilterEnum>>
-min_value: Option<String>
+pagination: PaginationArgs
+new()
-has_msg_type()
-has_ext_in()
-has_ext_out()
-has_int_in()
-has_int_out()
}
class Message {
+rowid: Option<i64>
+id: String
+boc: Option<Vec<u8>>
+body: Option<Vec<u8>>
+body_hash: Option<String>
+status: Option<i64>
+transaction_id: Option<String>
+msg_type: Option<i64>
+src: Option<String>
+src_workchain_id: Option<i64>
+dst: Option<String>
+dst_workchain_id: Option<i64>
+import_fee: Option<String>
+fwd_fee: Option<String>
+bounce: Option<i64>
+bounced: Option<i64>
+value: Option<String>
+value_other: Option<Vec<u8>>
+created_lt: Option<String>
+created_at: Option<i64>
+dst_chain_order: Option<String>
+src_chain_order: Option<String>
+proof: Option<String>
+code: Option<Vec<u8>>
+code_hash: Option<String>
+data: Option<Vec<u8>>
+data_hash: Option<String>
+src_dapp_id: Option<String>
+msg_chain_order: Option<String>
+list()
+in_block_msgs()
+account_messages()
+account_events()
}