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    }
32}
33
34fn finalize(
35    transactions: HashMap<String, SubscribeRequestFilterTransactions>,
36    accounts: HashMap<String, SubscribeRequestFilterAccounts>,
37    commitment: CommitmentLevel,
38) -> SubscribeRequest {
39    SubscribeRequest {
40        slots: HashMap::new(),
41        accounts,
42        transactions,
43        transactions_status: HashMap::new(),
44        blocks: HashMap::new(),
45        blocks_meta: HashMap::new(),
46        entry: HashMap::new(),
47        commitment: Some(commitment as i32),
48        accounts_data_slice: Vec::new(),
49        ping: None,
50        from_slot: None,
51    }
52}
53
54/// 构建订阅请求:`tx_0`…`tx_n`、`acc_0`…、**commitment = Processed**(与历史行为一致)。
55pub fn build_subscribe_request(
56    tx_filters: &[TransactionFilter],
57    acc_filters: &[AccountFilter],
58) -> SubscribeRequest {
59    build_subscribe_request_with_commitment(tx_filters, acc_filters, CommitmentLevel::Processed)
60}
61
62/// 与 [`build_subscribe_request`] 相同,可指定 commitment(例如 Confirmed)。
63pub fn build_subscribe_request_with_commitment(
64    tx_filters: &[TransactionFilter],
65    acc_filters: &[AccountFilter],
66    commitment: CommitmentLevel,
67) -> SubscribeRequest {
68    let transactions = tx_filters
69        .iter()
70        .enumerate()
71        .map(|(i, f)| (format!("tx_{}", i), tx_filter_to_proto(f)))
72        .collect();
73    let accounts = acc_filters
74        .iter()
75        .enumerate()
76        .map(|(i, f)| (format!("acc_{}", i), acc_filter_to_proto(f)))
77        .collect();
78    finalize(transactions, accounts, commitment)
79}
80
81/// 自定义交易订阅在 `SubscribeRequest.transactions` 中的 key(便于日志区分多条订阅)。
82pub fn build_subscribe_transaction_filters_named<N: AsRef<str>>(
83    named_tx_filters: &[(N, TransactionFilter)],
84    acc_filters: &[AccountFilter],
85    commitment: CommitmentLevel,
86) -> SubscribeRequest {
87    let transactions = named_tx_filters
88        .iter()
89        .map(|(name, f)| (name.as_ref().to_string(), tx_filter_to_proto(f)))
90        .collect();
91    let accounts = acc_filters
92        .iter()
93        .enumerate()
94        .map(|(i, f)| (format!("acc_{}", i), acc_filter_to_proto(f)))
95        .collect();
96    finalize(transactions, accounts, commitment)
97}