Transaction Filtering
此内容尚不支持你的语言。
Overview
Section titled “Overview”With the release of Indexer gRPC v2, we introduce the feature of transaction filtering. Transaction filtering enables you to selectively process transactions from the Aptos blockchain based on specific criteria. This is particularly useful when building indexers or services that only need to process a subset of all transactions, such as:
- Tracking specific smart contract interactions
- Monitoring wallet activity for certain addresses
- Indexing events from particular modules
- Processing only successful transactions
The source code can be found in aptos-core.
Protocol Buffers (Proto) Definitions
Section titled “Protocol Buffers (Proto) Definitions”Transaction filters are applied by including them in the gRPC request to the transaction stream.
Filter Proto Structure
Section titled “Filter Proto Structure”The filtering system is defined in aptos/indexer/v1/filter.proto:
message BooleanTransactionFilter { oneof filter { APIFilter api_filter = 1; LogicalAndFilters logical_and = 2; LogicalOrFilters logical_or = 3; BooleanTransactionFilter logical_not = 4; }}
message APIFilter { oneof filter { TransactionRootFilter transaction_root_filter = 1; UserTransactionFilter user_transaction_filter = 2; EventFilter event_filter = 3; }}gRPC Request Integration
Section titled “gRPC Request Integration”Filters are supplied as an optional parameter in the GetTransactionsRequest message:
message GetTransactionsRequest { // Required; start version of current stream. optional uint64 starting_version = 1;
// Optional; number of transactions to return in current stream. optional uint64 transactions_count = 2;
// Optional; number of transactions in each response batch. optional uint64 batch_size = 3;
// Optional; if provided, only transactions matching the filter are included. optional BooleanTransactionFilter transaction_filter = 4;}Example:
We can utilize the transaction filter to get all user transactions from Geomi’s gRPC endpoint:
grpcurl \ -d '{"transaction_filter":{"api_filter":{"transaction_root_filter":{"transaction_type":"TRANSACTION_TYPE_USER"}}}}' \ -max-msg-sz 30000000 \ -H "authorization:Bearer <api_key>" \ grpc.mainnet.aptoslabs.com:443 \ aptos.indexer.v1.RawData/GetTransactionsKey Points:
- The
transaction_filterfield is optional - you can stream all transactions by omitting it - When supplied, only transactions matching the filter criteria will be returned
- The filter is applied server-side, reducing bandwidth and processing overhead for clients
- Filters are validated before being applied; invalid filters will result in an error response
How It Works
Section titled “How It Works”The transaction filter system uses a declarative approach where you specify what you want to match using filters, and then combine them using boolean logic (AND, OR, NOT). Filters can be defined in:
- Rust code using builder patterns
- JSON for API-based configuration
- YAML for configuration files
Filter Types
Section titled “Filter Types”There are three main types of filters you can use:
1. Transaction Root Filter
Section titled “1. Transaction Root Filter”Filters transactions based on top-level transaction properties.
Available Fields:
success(boolean): Whether the transaction succeeded or failedtxn_type(enum): The type of transaction (User, Genesis, BlockMetadata, StateCheckpoint, Validator, BlockEpilogue)
Example:
{ "type": "TransactionRootFilter", "txn_type": "User", "success": true}2. User Transaction Filter
Section titled “2. User Transaction Filter”Filters user-submitted transactions based on sender and entry function details.
Available Fields:
sender(string): The account address that submitted the transactionpayload: Filter on the entry function being calledfunction: Entry function detailsaddress(string): Contract addressmodule(string): Module namefunction(string): Function name
Example:
{ "type": "UserTransactionFilter", "sender": "0x1", "payload": { "function": { "address": "0x1", "module": "coin", "function": "transfer" } }}3. Event Filter
Section titled “3. Event Filter”Filters transactions based on events they emit.
Available Fields:
struct_type: Filter on the event’s Move struct typeaddress(string): Contract addressmodule(string): Module namename(string): Struct name
data_substring_filter(string): Filter events by a substring in their data
Example 1 - Filter by struct type:
{ "type": "EventFilter", "struct_type": { "address": "0x1", "module": "coin", "name": "CoinDeposit" }}Example 2 - Filter by data substring:
{ "type": "EventFilter", "data_substring_filter": "transfer"}Example 3 - Combine struct type and data substring:
{ "type": "EventFilter", "struct_type": { "address": "0x1", "module": "coin" }, "data_substring_filter": "0xabc123"}Combining Filters with Boolean Logic
Section titled “Combining Filters with Boolean Logic”Filters can be combined using logical operators to create complex queries:
AND Operator
Section titled “AND Operator”Matches transactions that satisfy all of the specified filters.
{ "and": [ { "type": "TransactionRootFilter", "success": true }, { "type": "EventFilter", "struct_type": { "address": "0x1", "module": "coin", "name": "CoinDeposit" } } ]}OR Operator
Section titled “OR Operator”Matches transactions that satisfy any of the specified filters.
{ "or": [ { "type": "UserTransactionFilter", "sender": "0xabc..." }, { "type": "UserTransactionFilter", "sender": "0xdef..." } ]}NOT Operator
Section titled “NOT Operator”Matches transactions that do not satisfy the specified filter.
{ "not": { "type": "TransactionRootFilter", "success": false }}Common Use Cases
Section titled “Common Use Cases”Filter Coin Transfer Transactions
Section titled “Filter Coin Transfer Transactions”Match all successful coin transfer transactions:
{ "and": [ { "type": "TransactionRootFilter", "success": true }, { "type": "UserTransactionFilter", "payload": { "function": { "address": "0x1", "module": "coin", "function": "transfer" } } } ]}Filter by Specific Sender
Section titled “Filter by Specific Sender”Track all transactions from a specific wallet:
{ "type": "UserTransactionFilter", "sender": "0x806b27f3d7824a1d78c4291b6d0371aa693437f9eb3393c6440519c0ffaa627f"}Filter by Multiple Senders
Section titled “Filter by Multiple Senders”Track transactions from multiple wallets:
{ "or": [ { "type": "UserTransactionFilter", "sender": "0xabc..." }, { "type": "UserTransactionFilter", "sender": "0xdef..." } ]}Filter NFT Events
Section titled “Filter NFT Events”Track NFT minting events from a specific collection:
{ "type": "EventFilter", "struct_type": { "address": "0x4", "module": "aptos_token", "name": "MintTokenEvent" }}Filter Smart Contract Interactions
Section titled “Filter Smart Contract Interactions”Track all interactions with a specific smart contract module:
{ "type": "EventFilter", "struct_type": { "address": "0x123abc...", "module": "my_defi_module" }}Complex Filter: DEX Trading
Section titled “Complex Filter: DEX Trading”Track successful swap events from multiple DEX protocols:
{ "and": [ { "type": "TransactionRootFilter", "success": true }, { "or": [ { "type": "EventFilter", "struct_type": { "address": "0xdex1", "module": "swap", "name": "SwapEvent" } }, { "type": "EventFilter", "struct_type": { "address": "0xdex2", "module": "pool", "name": "TradeEvent" } } ] } ]}Exclude Failed Transactions
Section titled “Exclude Failed Transactions”Get all user transactions except failed ones:
{ "and": [ { "type": "UserTransactionFilter", "sender": "0xabc..." }, { "type": "TransactionRootFilter", "success": true } ]}YAML Format
Section titled “YAML Format”Filters can also be expressed in YAML format, which is often more readable for configuration files:
and: - or: - type: TransactionRootFilter success: true - type: UserTransactionFilter sender: '0x1' - type: EventFilter struct_type: address: '0x1' module: coin name: CoinDepositUsing Filters in Rust
Section titled “Using Filters in Rust”If you’re building with Rust, you can use the aptos-transaction-filter crate with builder patterns:
Basic Filter
Section titled “Basic Filter”use aptos_transaction_filter::{TransactionRootFilterBuilder, BooleanTransactionFilter};
// Create a filter for successful transactionslet filter = TransactionRootFilterBuilder::default() .success(true) .build() .unwrap();
let boolean_filter = BooleanTransactionFilter::from(filter);Event Filter
Section titled “Event Filter”use aptos_transaction_filter::{EventFilterBuilder, MoveStructTagFilterBuilder};
let filter = EventFilterBuilder::default() .struct_type( MoveStructTagFilterBuilder::default() .address("0x1") .module("coin") .name("CoinDeposit") .build() .unwrap() ) .build() .unwrap();User Transaction Filter
Section titled “User Transaction Filter”use aptos_transaction_filter::{UserTransactionFilterBuilder, EntryFunctionFilterBuilder, UserTransactionPayloadFilterBuilder};
let filter = UserTransactionFilterBuilder::default() .sender("0x1") .payload( UserTransactionPayloadFilterBuilder::default() .function( EntryFunctionFilterBuilder::default() .address("0x1") .module("coin") .function("transfer") .build() .unwrap() ) .build() .unwrap() ) .build() .unwrap();Combining Filters
Section titled “Combining Filters”use aptos_transaction_filter::BooleanTransactionFilter;
// Create individual filterslet success_filter = TransactionRootFilterBuilder::default() .success(true) .build() .unwrap();
let sender_filter = UserTransactionFilterBuilder::default() .sender("0x1") .build() .unwrap();
let event_filter = EventFilterBuilder::default() .struct_type( MoveStructTagFilterBuilder::default() .address("0x1") .module("coin") .build() .unwrap() ) .build() .unwrap();
// Combine with logical operatorslet combined = BooleanTransactionFilter::from(success_filter) .or(sender_filter) .and(event_filter);
// Use the filterif combined.matches(&transaction) { // Process transaction}Serialization
Section titled “Serialization”// Serialize to JSONlet json = serde_json::to_string_pretty(&filter).unwrap();
// Serialize to YAMLlet yaml = serde_yaml::to_string(&filter).unwrap();
// Deserialize from JSONlet filter: BooleanTransactionFilter = serde_json::from_str(&json).unwrap();Performance Considerations
Section titled “Performance Considerations”The transaction filter system is optimized for high-throughput processing:
- Single Pass: Filters process each transaction only once
- Minimal Allocations: Filters avoid clones and unnecessary copies
- Early Exit: Filters short-circuit as soon as a non-match is found
- Address Caching: Address standardization is cached for performance
For best performance:
- Use specific filters when possible (e.g., filter by address rather than all transactions)
- Place more restrictive filters first in AND operations
- Consider the transaction volume on mainnet when designing filters