account.rs
Overview
This file defines the Account data structure and related asynchronous functions to manage blockchain account data stored in a SQLite database and fetched from an external blockchain client. It provides mechanisms to query accounts with pagination and filtering, retrieve a single account by its blockchain address, and convert blockchain account data into a local model suitable for persistence and further processing.
The functionality centers around interaction with a blockchain client (tvm_client) and a SQLite connection pool (sqlx::SqlitePool), enabling synchronization and querying of account states from the blockchain and local cache.
Structs and Their Details
Account
Represents a blockchain account with fields mapped to a SQL table accounts. It derives Clone and FromRow for easy cloning and database row conversion.
Fields:
rowid: i64- Primary key in the database (not persisted).id: String- Unique blockchain account address.acc_type: u8- Encoded account status.balance: String- Account balance as a hex string.balance_other: Option<Vec<u8>>- Serialized other balance information.bits: String- Number of bits (exact meaning context-specific).boc: Option<Vec<u8>>- Serialized account data in BOC (Bag of Cells) format.cells: String- Number of cells (context-specific).code: Option<Vec<u8>>- Serialized smart contract code.code_hash: String- Hash of the smart contract code.data: Option<Vec<u8>>- Serialized smart contract data.data_hash: String- Hash of the data.dapp_id: Option<String>- Optional dApp identifier.due_payment: Option<String>- Optional due payment field.init_code_hash: String- Hash of the initial code.last_paid: u64- Timestamp or block number of last payment.last_trans_chain_order: String- Chain order of last transaction.last_trans_lt: String- Logical time of last transaction.last_trans_hash: String- Hash of the last transaction.prev_code_hash: Option<String>- Previous code hash.proof: Option<Vec<u8>>- Optional proof data.public_cells: String- Number of public cells.split_depth: Option<i64>- Optional split depth.state_hash: Option<String>- Optional state hash.workchain_id: i32- Workchain identifier.
BlockchainAccountsQueryArgs
Encapsulates arguments used to query multiple blockchain accounts with optional filtering and pagination.
Fields:
code_hash: Option<String>- Optional filter by code hash.pagination: PaginationArgs- Pagination parameters, includes cursor and limit.
Impl Account - Methods
list
pub async fn list(
pool: &SqlitePool,
where_clause: String,
order_by: String,
limit: Option<i32>,
) -> anyhow::Result<Vec<Account>>
Fetches a list of accounts from the database with a customizable SQL WHERE clause, ordering, and limit.
Parameters:
pool: Reference to a SQLite connection pool.where_clause: SQL condition string (e.g.,"WHERE acc_type = 1").order_by: SQL order clause (e.g.,"ORDER BY balance DESC").limit: Optional maximum number of results; defaults to a batch size defined indefaults::QUERY_BATCH_SIZE.
Returns: A vector of
Accountinstances matching the query.Usage Example:
let accounts = Account::list(&pool, "WHERE acc_type = 1".to_string(), "ORDER BY balance DESC".to_string(), Some(10)).await?;Implementation Details: Constructs raw SQL using the provided clauses, executes the query asynchronously, and collects results into a vector using SQLx.
by_address
pub async fn by_address(
_pool: &SqlitePool,
client: &Arc<ClientContext>,
address: Option<String>,
) -> anyhow::Result<Option<Account>>
Retrieves a single account by its blockchain address by querying the blockchain client, then converts and deserializes the blockchain account data into the local Account structure.
Parameters:
_pool: SQLite pool, unused here but reserved for future use or consistency.client: Shared reference to the blockchain client context.address: Optional blockchain account address string.
Returns:
Ok(Some(Account))if found,Ok(None)if not found or address isNone, or an error on failure.Usage Example:
let account = Account::by_address(&pool, &client, Some("0:abcdef...".to_string())).await?;Implementation Details:
Validates presence of address.
Uses
tvm_client::account::get_accountasynchronously to fetch the account.Decodes the returned base64 BOC data into a
tvm_block::Account.Extracts balance, code, data, and hashes from the blockchain account.
Serializes balance and other fields to match database schema.
Returns an
Accountstruct with many fields initialized; some fields are left as default or empty due to lack of blockchain data or context.Handles
NotFounderror by returningNone.
blockchain_accounts
pub(crate) async fn blockchain_accounts(
pool: &SqlitePool,
args: &BlockchainAccountsQueryArgs,
) -> anyhow::Result<Vec<Account>>
Retrieves a list of accounts from the local database filtered by optional code_hash and paginated using cursor-based pagination.
Parameters:
pool: SQLite connection pool.args:BlockchainAccountsQueryArgsstruct with filter and pagination.
Returns: Vector of
Accountobjects matching the filter and pagination criteria.Implementation Details:
Builds complex SQL queries with optional CTEs (
WITHclauses) to handle cursor pagination (afterandbefore).Applies filters for
code_hash.Uses pagination arguments to determine ordering (
ASCorDESC) and limit.Binds cursor and filter values to the query.
Fetches all matching accounts asynchronously.
Reverses the result set if pagination direction is backward.
Uses tracing for SQL query debugging and error reporting.
Usage Example:
let args = BlockchainAccountsQueryArgs { code_hash: Some("abc123...".to_string()), pagination: PaginationArgs { after: Some("cursor123".to_string()), before: None, limit: Some(20), ..Default::default() }, }; let accounts = Account::blockchain_accounts(&pool, &args).await?;
Helper Functions
serialize_account_status
fn serialize_account_status(status: &AccountStatus) -> u8
Converts a blockchain AccountStatus enum into a compact u8 representation for storage in the database.
Mappings:
AccStateUninit->0b00AccStateFrozen->0b10AccStateActive->0b01AccStateNonexist->0b11
Usage: Used internally when converting blockchain account status into
acc_typefield.
Important Implementation Details and Algorithms
Database Interaction:
Uses SQLx's
QueryBuilderand asynchronous fetching.Supports dynamic query construction with cursor-based pagination.
Uses CTEs (Common Table Expressions) to handle pagination cursors by referencing
rowidassociated withafterandbeforecursors.
Blockchain Data Handling:
Decodes BOC (Bag of Cells) format from base64 strings into
tvm_block::Account.Extracts balance and serializes other balance components using TVM serialization utilities.
Handles different account statuses (
AccStateActive, etc.) to decide whether to extract code and data cells.Some fields in the
Accountstruct are left empty or default when blockchain data is incomplete or irrelevant for the current context.
Error Handling:
Uses
anyhow::Resultfor error propagation.Specially handles the blockchain client's
NotFounderror code by returningNoneinstead of an error.
Logging:
Uses
tracingmacros for debug and trace level logging of SQL queries and results.
Interaction with Other Parts of the Application
Integrates with:
Blockchain client (
tvm_client::ClientContext) for live account data retrieval.Database layer via
sqlx::SqlitePoolfor cached/persisted account data.GraphQL schema/pagination utilities (e.g.,
PaginationArgsandPaginateDirection) imported fromcrate::schema::graphql::queryto support API-level pagination.Helper modules
tvm_block,tvm_typesfor serialization/deserialization of blockchain data structures.defaultsmodule for constants such as default query batch size.
The file acts as a bridge between the blockchain client data and the local database representation, enabling querying and synchronization workflows.
Diagram: Structure of account.rs
classDiagram
class Account {
+rowid: i64
+id: String
+acc_type: u8
+balance: String
+balance_other: Option<Vec<u8>>
+bits: String
+boc: Option<Vec<u8>>
+cells: String
+code: Option<Vec<u8>>
+code_hash: String
+data: Option<Vec<u8>>
+data_hash: String
+dapp_id: Option<String>
+due_payment: Option<String>
+init_code_hash: String
+last_paid: u64
+last_trans_chain_order: String
+last_trans_lt: String
+last_trans_hash: String
+prev_code_hash: Option<String>
+proof: Option<Vec<u8>>
+public_cells: String
+split_depth: Option<i64>
+state_hash: Option<String>
+workchain_id: i32
+list()
+by_address()
+blockchain_accounts()
}
class BlockchainAccountsQueryArgs {
+code_hash: Option<String>
+pagination: PaginationArgs
}
Account ..> BlockchainAccountsQueryArgs : uses
Account ..> ClientContext : calls
Account ..> SqlitePool : queries
This diagram illustrates the primary struct Account with its fields and asynchronous methods, its interaction with the BlockchainAccountsQueryArgs struct for query inputs, and dependencies on ClientContext and SqlitePool for blockchain and database interactions respectively.