Skip to main content

sol_parser_sdk/grpc/
subscribe_builder.rs

1//! Yellowstone [`SubscribeRequest`] 构造(DEX 订阅、钱包 mentions 转账监控等共用)。
2
3use std::collections::HashMap;
4
5use yellowstone_grpc_proto::prelude::{
6    CommitmentLevel, SubscribeRequest, SubscribeRequestFilterAccounts,
7    SubscribeRequestFilterTransactions,
8};
9
10use super::types::{AccountFilter, TransactionFilter};
11
12#[inline]
13fn tx_filter_to_proto(f: &TransactionFilter) -> SubscribeRequestFilterTransactions {
14    SubscribeRequestFilterTransactions {
15        vote: Some(false),
16        failed: Some(false),
17        signature: None,
18        account_include: f.account_include.clone(),
19        account_exclude: f.account_exclude.clone(),
20        account_required: f.account_required.clone(),
21    }
22}
23
24#[inline]
25fn acc_filter_to_proto(f: &AccountFilter) -> SubscribeRequestFilterAccounts {
26    SubscribeRequestFilterAccounts {
27        account: f.account.clone(),
28        owner: f.owner.clone(),
29        filters: f.filters.clone(),
30        nonempty_txn_signature: None,
31        cuckoo_accounts_filter: None,
32    }
33}
34
35fn finalize(
36    transactions: HashMap<String, SubscribeRequestFilterTransactions>,
37    accounts: HashMap<String, SubscribeRequestFilterAccounts>,
38    commitment: CommitmentLevel,
39) -> SubscribeRequest {
40    SubscribeRequest {
41        slots: HashMap::new(),
42        accounts,
43        transactions,
44        transactions_status: HashMap::new(),
45        blocks: HashMap::new(),
46        blocks_meta: HashMap::new(),
47        entry: HashMap::new(),
48        commitment: Some(commitment as i32),
49        accounts_data_slice: Vec::new(),
50        ping: None,
51        from_slot: None,
52    }
53}
54
55/// 构建订阅请求:`tx_0`…`tx_n`、`acc_0`…、**commitment = Processed**(与历史行为一致)。
56pub fn build_subscribe_request(
57    tx_filters: &[TransactionFilter],
58    acc_filters: &[AccountFilter],
59) -> SubscribeRequest {
60    build_subscribe_request_with_commitment(tx_filters, acc_filters, CommitmentLevel::Processed)
61}
62
63/// 与 [`build_subscribe_request`] 相同,可指定 commitment(例如 Confirmed)。
64pub fn build_subscribe_request_with_commitment(
65    tx_filters: &[TransactionFilter],
66    acc_filters: &[AccountFilter],
67    commitment: CommitmentLevel,
68) -> SubscribeRequest {
69    let transactions = tx_filters
70        .iter()
71        .enumerate()
72        .map(|(i, f)| (format!("tx_{}", i), tx_filter_to_proto(f)))
73        .collect();
74    let accounts = acc_filters
75        .iter()
76        .enumerate()
77        .map(|(i, f)| (format!("acc_{}", i), acc_filter_to_proto(f)))
78        .collect();
79    finalize(transactions, accounts, commitment)
80}
81
82/// 自定义交易订阅在 `SubscribeRequest.transactions` 中的 key(便于日志区分多条订阅)。
83pub fn build_subscribe_transaction_filters_named<N: AsRef<str>>(
84    named_tx_filters: &[(N, TransactionFilter)],
85    acc_filters: &[AccountFilter],
86    commitment: CommitmentLevel,
87) -> SubscribeRequest {
88    let transactions = named_tx_filters
89        .iter()
90        .map(|(name, f)| (name.as_ref().to_string(), tx_filter_to_proto(f)))
91        .collect();
92    let accounts = acc_filters
93        .iter()
94        .enumerate()
95        .map(|(i, f)| (format!("acc_{}", i), acc_filter_to_proto(f)))
96        .collect();
97    finalize(transactions, accounts, commitment)
98}