1use {
2 base64::{Engine, engine::general_purpose::STANDARD as base64_engine},
3 richat_proto::geyser::{
4 CommitmentLevel as CommitmentLevelProto, SubscribeRequest,
5 SubscribeRequestAccountsDataSlice, SubscribeRequestFilterAccounts,
6 SubscribeRequestFilterAccountsFilter, SubscribeRequestFilterAccountsFilterLamports,
7 SubscribeRequestFilterAccountsFilterMemcmp, SubscribeRequestFilterBlocks,
8 SubscribeRequestFilterSlots, SubscribeRequestFilterTransactions,
9 subscribe_request_filter_accounts_filter::Filter as AccountsFilterDataOneof,
10 subscribe_request_filter_accounts_filter_lamports::Cmp as AccountsFilterLamports,
11 subscribe_request_filter_accounts_filter_memcmp::Data as AccountsFilterMemcmpOneof,
12 },
13 richat_shared::{
14 config::{
15 deserialize_maybe_signature, deserialize_num_str, deserialize_pubkey_set,
16 deserialize_pubkey_vec,
17 },
18 five8::{pubkey_decode, pubkey_encode, signature_decode, signature_encode},
19 },
20 serde::{
21 Deserialize, Serialize,
22 de::{self, Deserializer},
23 },
24 solana_commitment_config::CommitmentLevel,
25 solana_pubkey::{ParsePubkeyError, Pubkey},
26 solana_signature::{ParseSignatureError, Signature},
27 std::collections::{HashMap, HashSet},
28 thiserror::Error,
29};
30
31pub const MAX_FILTERS: usize = 4;
32pub const MAX_DATA_SIZE: usize = 128;
33pub const MAX_DATA_BASE58_SIZE: usize = 175;
34pub const MAX_DATA_BASE64_SIZE: usize = 172;
35
36#[derive(Debug, Error)]
37pub enum ConfigLimitsError {
38 #[error("Filter name exceeds limit, max {max}")]
39 FilterNameOverflow { max: usize },
40 #[error("Max amount of filters/data_slices reached, only {max} allowed")]
41 FiltersOverflow { max: usize },
42 #[error("Subscribe on full stream with `any` is not allowed, at least one filter required")]
43 EmptyNotAllowed,
44 #[error("Max amount of Pubkeys is reached, only {max} allowed")]
45 PubkeysOverflow { max: usize },
46 #[error("Pubkey {pubkey} in filters is not allowed")]
47 PubkeyNotAllowed { pubkey: Pubkey },
48 #[error("Too much filters provided; max: {max}")]
49 TooMuchFilters { max: usize },
50 #[error("Filter data is too large, max size: {MAX_DATA_SIZE}")]
51 FilterDataOverflow,
52 #[error("Datasize used more than once")]
53 DatasizeDuplicated,
54 #[error("Failed to create filter: data slices out of order")]
55 DataSliceOutOfOrder,
56 #[error("Failed to create filter: data slices overlapped")]
57 DataSliceOverlap,
58 #[error("`include_{0}` is not allowed")]
59 BlocksNotAllowed(&'static str),
60}
61
62#[derive(Debug, Clone, Deserialize, Serialize)]
63#[serde(deny_unknown_fields, default)]
64pub struct ConfigLimits {
65 pub name_max: usize,
66 pub slots: ConfigLimitsSlots,
67 pub accounts: ConfigLimitsAccounts,
68 pub transactions: ConfigLimitsTransactions,
69 pub transactions_status: ConfigLimitsTransactions,
70 pub entries: ConfigLimitsEntries,
71 pub blocks_meta: ConfigLimitsBlocksMeta,
72 pub blocks: ConfigLimitsBlocks,
73}
74
75impl Default for ConfigLimits {
76 fn default() -> Self {
77 Self {
78 name_max: 128,
79 slots: Default::default(),
80 accounts: Default::default(),
81 transactions: Default::default(),
82 transactions_status: Default::default(),
83 entries: Default::default(),
84 blocks_meta: Default::default(),
85 blocks: Default::default(),
86 }
87 }
88}
89
90impl ConfigLimits {
91 const fn check_name_max(len: usize, max: usize) -> Result<(), ConfigLimitsError> {
92 if len <= max {
93 Ok(())
94 } else {
95 Err(ConfigLimitsError::FilterNameOverflow { max })
96 }
97 }
98
99 fn check_names_max<'a>(
100 names: impl Iterator<Item = &'a String>,
101 max: usize,
102 ) -> Result<(), ConfigLimitsError> {
103 for key in names {
104 Self::check_name_max(key.len(), max)?;
105 }
106 Ok(())
107 }
108
109 const fn check_max(len: usize, max: usize) -> Result<(), ConfigLimitsError> {
110 if len <= max {
111 Ok(())
112 } else {
113 Err(ConfigLimitsError::FiltersOverflow { max })
114 }
115 }
116
117 const fn check_any(is_empty: bool, any: bool) -> Result<(), ConfigLimitsError> {
118 if !is_empty || any {
119 Ok(())
120 } else {
121 Err(ConfigLimitsError::EmptyNotAllowed)
122 }
123 }
124
125 const fn check_pubkey_max(len: usize, max: usize) -> Result<(), ConfigLimitsError> {
126 if len <= max {
127 Ok(())
128 } else {
129 Err(ConfigLimitsError::PubkeysOverflow { max })
130 }
131 }
132
133 fn check_pubkey_reject(
134 pubkey: &Pubkey,
135 set: &HashSet<Pubkey>,
136 ) -> Result<(), ConfigLimitsError> {
137 if !set.contains(pubkey) {
138 Ok(())
139 } else {
140 Err(ConfigLimitsError::PubkeyNotAllowed { pubkey: *pubkey })
141 }
142 }
143
144 pub fn check_filter(&self, filter: &ConfigFilter) -> Result<(), ConfigLimitsError> {
145 self.slots.check_filter(self.name_max, &filter.slots)?;
146 self.accounts
147 .check_filter(self.name_max, &filter.accounts, &filter.accounts_data_slice)?;
148 self.transactions
149 .check_filter(self.name_max, &filter.transactions)?;
150 self.transactions_status
151 .check_filter(self.name_max, &filter.transactions_status)?;
152 self.entries.check_filter(self.name_max, &filter.entries)?;
153 self.blocks_meta
154 .check_filter(self.name_max, &filter.blocks_meta)?;
155 self.blocks.check_filter(self.name_max, &filter.blocks)?;
156
157 Ok(())
158 }
159}
160
161#[derive(Debug, Clone, Deserialize, Serialize)]
162#[serde(deny_unknown_fields, default)]
163pub struct ConfigLimitsSlots {
164 #[serde(deserialize_with = "deserialize_num_str")]
165 pub max: usize,
166}
167
168impl Default for ConfigLimitsSlots {
169 fn default() -> Self {
170 Self { max: usize::MAX }
171 }
172}
173
174impl ConfigLimitsSlots {
175 pub fn check_filter(
176 &self,
177 name_max: usize,
178 filters: &HashMap<String, ConfigFilterSlots>,
179 ) -> Result<(), ConfigLimitsError> {
180 ConfigLimits::check_names_max(filters.keys(), name_max)?;
181 ConfigLimits::check_max(filters.len(), self.max)
182 }
183}
184
185#[derive(Debug, Clone, Deserialize, Serialize)]
186#[serde(deny_unknown_fields, default)]
187pub struct ConfigLimitsAccounts {
188 pub max: usize,
189 pub any: bool,
190 pub account_max: usize,
191 #[serde(deserialize_with = "deserialize_pubkey_set")]
192 pub account_reject: HashSet<Pubkey>,
193 pub owner_max: usize,
194 #[serde(deserialize_with = "deserialize_pubkey_set")]
195 pub owner_reject: HashSet<Pubkey>,
196 pub data_slice_max: usize,
197}
198
199impl Default for ConfigLimitsAccounts {
200 fn default() -> Self {
201 Self {
202 max: usize::MAX,
203 any: true,
204 account_max: usize::MAX,
205 account_reject: HashSet::new(),
206 owner_max: usize::MAX,
207 owner_reject: HashSet::new(),
208 data_slice_max: usize::MAX,
209 }
210 }
211}
212
213impl ConfigLimitsAccounts {
214 pub fn check_filter(
215 &self,
216 name_max: usize,
217 filters: &HashMap<String, ConfigFilterAccounts>,
218 data_slices: &[ConfigFilterAccountsDataSlice],
219 ) -> Result<(), ConfigLimitsError> {
220 ConfigLimits::check_names_max(filters.keys(), name_max)?;
221 ConfigLimits::check_max(filters.len(), self.max)?;
222
223 for filter in filters.values() {
224 ConfigLimits::check_any(
225 filter.account.is_empty() && filter.owner.is_empty(),
226 self.any,
227 )?;
228 ConfigLimits::check_pubkey_max(filter.account.len(), self.account_max)?;
229 ConfigLimits::check_pubkey_max(filter.owner.len(), self.owner_max)?;
230
231 for pubkey in filter.account.iter() {
232 ConfigLimits::check_pubkey_reject(pubkey, &self.account_reject)?;
233 }
234 for pubkey in filter.owner.iter() {
235 ConfigLimits::check_pubkey_reject(pubkey, &self.owner_reject)?;
236 }
237
238 if filter.filters.len() > MAX_FILTERS {
239 return Err(ConfigLimitsError::TooMuchFilters { max: MAX_FILTERS });
240 }
241 let mut datasize_defined = false;
242 for filter in filter.filters.iter() {
243 match filter {
244 ConfigFilterAccountsFilter::Memcmp {
245 offset: _offset,
246 data,
247 } => {
248 if data.len() > MAX_DATA_SIZE {
249 return Err(ConfigLimitsError::FilterDataOverflow);
250 }
251 }
252 ConfigFilterAccountsFilter::DataSize(_) => {
253 if datasize_defined {
254 return Err(ConfigLimitsError::DatasizeDuplicated);
255 }
256 datasize_defined = true;
257 }
258 ConfigFilterAccountsFilter::TokenAccountState => {}
259 ConfigFilterAccountsFilter::Lamports(_) => {}
260 }
261 }
262 }
263
264 ConfigLimits::check_max(data_slices.len(), self.data_slice_max)?;
265 for (i, ds_a) in data_slices.iter().enumerate() {
266 for ds_b in data_slices[i + 1..].iter() {
268 if ds_a.offset > ds_b.offset {
269 return Err(ConfigLimitsError::DataSliceOutOfOrder);
270 }
271 }
272
273 for slice_b in data_slices[0..i].iter() {
275 if ds_a.offset < slice_b.offset + slice_b.length {
276 return Err(ConfigLimitsError::DataSliceOverlap);
277 }
278 }
279 }
280
281 Ok(())
282 }
283}
284
285#[derive(Debug, Clone, Deserialize, Serialize)]
286#[serde(deny_unknown_fields, default)]
287pub struct ConfigLimitsTransactions {
288 #[serde(deserialize_with = "deserialize_num_str")]
289 pub max: usize,
290 pub any: bool,
291 #[serde(deserialize_with = "deserialize_num_str")]
292 pub account_include_max: usize,
293 #[serde(deserialize_with = "deserialize_pubkey_set")]
294 pub account_include_reject: HashSet<Pubkey>,
295 #[serde(deserialize_with = "deserialize_num_str")]
296 pub account_exclude_max: usize,
297 #[serde(deserialize_with = "deserialize_num_str")]
298 pub account_required_max: usize,
299}
300
301impl Default for ConfigLimitsTransactions {
302 fn default() -> Self {
303 Self {
304 max: usize::MAX,
305 any: true,
306 account_include_max: usize::MAX,
307 account_include_reject: HashSet::new(),
308 account_exclude_max: usize::MAX,
309 account_required_max: usize::MAX,
310 }
311 }
312}
313
314impl ConfigLimitsTransactions {
315 pub fn check_filter(
316 &self,
317 name_max: usize,
318 filters: &HashMap<String, ConfigFilterTransactions>,
319 ) -> Result<(), ConfigLimitsError> {
320 ConfigLimits::check_names_max(filters.keys(), name_max)?;
321 ConfigLimits::check_max(filters.len(), self.max)?;
322
323 for filter in filters.values() {
324 ConfigLimits::check_any(
325 filter.vote.is_none()
326 && filter.failed.is_none()
327 && filter.account_include.is_empty()
328 && filter.account_exclude.is_empty()
329 && filter.account_required.is_empty(),
330 self.any,
331 )?;
332 ConfigLimits::check_pubkey_max(filter.account_include.len(), self.account_include_max)?;
333 ConfigLimits::check_pubkey_max(filter.account_exclude.len(), self.account_exclude_max)?;
334 ConfigLimits::check_pubkey_max(
335 filter.account_required.len(),
336 self.account_required_max,
337 )?;
338
339 for pubkey in filter.account_include.iter() {
340 ConfigLimits::check_pubkey_reject(pubkey, &self.account_include_reject)?;
341 }
342 }
343
344 Ok(())
345 }
346}
347
348#[derive(Debug, Clone, Deserialize, Serialize)]
349#[serde(deny_unknown_fields, default)]
350pub struct ConfigLimitsEntries {
351 #[serde(deserialize_with = "deserialize_num_str")]
352 pub max: usize,
353}
354
355impl Default for ConfigLimitsEntries {
356 fn default() -> Self {
357 Self { max: usize::MAX }
358 }
359}
360
361impl ConfigLimitsEntries {
362 pub fn check_filter(
363 &self,
364 name_max: usize,
365 filters: &HashSet<String>,
366 ) -> Result<(), ConfigLimitsError> {
367 ConfigLimits::check_names_max(filters.iter(), name_max)?;
368 ConfigLimits::check_max(filters.len(), self.max)
369 }
370}
371
372#[derive(Debug, Clone, Deserialize, Serialize)]
373#[serde(deny_unknown_fields, default)]
374pub struct ConfigLimitsBlocksMeta {
375 #[serde(deserialize_with = "deserialize_num_str")]
376 pub max: usize,
377}
378
379impl Default for ConfigLimitsBlocksMeta {
380 fn default() -> Self {
381 Self { max: usize::MAX }
382 }
383}
384
385impl ConfigLimitsBlocksMeta {
386 pub fn check_filter(
387 &self,
388 name_max: usize,
389 filters: &HashSet<String>,
390 ) -> Result<(), ConfigLimitsError> {
391 ConfigLimits::check_names_max(filters.iter(), name_max)?;
392 ConfigLimits::check_max(filters.len(), self.max)
393 }
394}
395
396#[derive(Debug, Clone, Deserialize, Serialize)]
397#[serde(deny_unknown_fields, default)]
398pub struct ConfigLimitsBlocks {
399 #[serde(deserialize_with = "deserialize_num_str")]
400 pub max: usize,
401 #[serde(deserialize_with = "deserialize_num_str")]
402 pub account_include_max: usize,
403 pub account_include_any: bool,
404 #[serde(deserialize_with = "deserialize_pubkey_set")]
405 pub account_include_reject: HashSet<Pubkey>,
406 pub include_transactions: bool,
407 pub include_accounts: bool,
408 pub include_entries: bool,
409}
410
411impl Default for ConfigLimitsBlocks {
412 fn default() -> Self {
413 Self {
414 max: usize::MAX,
415 account_include_max: usize::MAX,
416 account_include_any: true,
417 account_include_reject: HashSet::new(),
418 include_transactions: true,
419 include_accounts: true,
420 include_entries: true,
421 }
422 }
423}
424
425impl ConfigLimitsBlocks {
426 pub fn check_filter(
427 &self,
428 name_max: usize,
429 filters: &HashMap<String, ConfigFilterBlocks>,
430 ) -> Result<(), ConfigLimitsError> {
431 ConfigLimits::check_names_max(filters.keys(), name_max)?;
432 ConfigLimits::check_max(filters.len(), self.max)?;
433
434 for filter in filters.values() {
435 ConfigLimits::check_any(filter.account_include.is_empty(), self.account_include_any)?;
436 ConfigLimits::check_pubkey_max(filter.account_include.len(), self.account_include_max)?;
437 if !(filter.include_transactions == Some(false) || self.include_transactions) {
438 return Err(ConfigLimitsError::BlocksNotAllowed("transactions"));
439 }
440 if !(matches!(filter.include_accounts, None | Some(false)) || self.include_accounts) {
441 return Err(ConfigLimitsError::BlocksNotAllowed("accounts"));
442 }
443 if !(matches!(filter.include_entries, None | Some(false)) || self.include_accounts) {
444 return Err(ConfigLimitsError::BlocksNotAllowed("entries"));
445 }
446 for pubkey in filter.account_include.iter() {
447 ConfigLimits::check_pubkey_reject(pubkey, &self.account_include_reject)?;
448 }
449 }
450
451 Ok(())
452 }
453}
454
455#[derive(Debug, Error)]
456pub enum ConfigFilterError {
457 #[error(transparent)]
458 Limits(#[from] ConfigLimitsError),
459 #[error("Field `{0}` should be defined")]
460 FieldNotDefined(&'static str),
461 #[error("Token account state value is invalid")]
462 TokenAccountStateInvalid,
463 #[error("Invalid base58 encoding")]
464 InvalidBase58,
465 #[error("Invalid base64 encoding")]
466 InvalidBase64,
467 #[error("Invalid pubkey `{0}`: {1}")]
468 Pubkey(String, ParsePubkeyError),
469 #[error("Invalid signature `{0}`: {1}")]
470 Signature(String, ParseSignatureError),
471 #[error("Unknown commitment level: {0}")]
472 UnknownCommitment(i32),
473}
474
475#[derive(Debug, Clone, Default, Deserialize, Serialize)]
476#[serde(deny_unknown_fields, default)]
477pub struct ConfigFilter {
478 pub slots: HashMap<String, ConfigFilterSlots>,
479 pub accounts: HashMap<String, ConfigFilterAccounts>,
480 pub accounts_data_slice: Vec<ConfigFilterAccountsDataSlice>,
481 pub transactions: HashMap<String, ConfigFilterTransactions>,
482 pub transactions_status: HashMap<String, ConfigFilterTransactions>,
483 pub entries: HashSet<String>,
484 pub blocks_meta: HashSet<String>,
485 pub blocks: HashMap<String, ConfigFilterBlocks>,
486 pub commitment: Option<ConfigFilterCommitment>,
487}
488
489impl ConfigFilter {
490 fn try_conv_map<T, C>(map: HashMap<String, T>) -> Result<HashMap<String, C>, ConfigFilterError>
491 where
492 C: TryFrom<T, Error = ConfigFilterError>,
493 {
494 map.into_iter()
495 .map(|(key, value)| value.try_into().map(|value| (key, value)))
496 .collect::<Result<_, _>>()
497 }
498
499 fn conv_map<C, T>(map: HashMap<String, C>) -> HashMap<String, T>
500 where
501 T: From<C>,
502 {
503 map.into_iter()
504 .map(|(key, value)| (key, value.into()))
505 .collect()
506 }
507
508 fn conv_set<T: Default>(set: HashSet<String>) -> HashMap<String, T> {
509 set.into_iter().map(|key| (key, T::default())).collect()
510 }
511
512 fn parse_vec_pubkeys(pubkeys: Vec<String>) -> Result<Vec<Pubkey>, ConfigFilterError> {
513 pubkeys
514 .into_iter()
515 .map(|pubkey| {
516 pubkey_decode(&pubkey).map_err(|error| ConfigFilterError::Pubkey(pubkey, error))
517 })
518 .collect::<Result<Vec<_>, _>>()
519 }
520
521 fn conv_vec_pubkeys(pubkeys: Vec<Pubkey>) -> Vec<String> {
522 pubkeys
523 .into_iter()
524 .map(|pk| pubkey_encode(&pk.to_bytes()))
525 .collect()
526 }
527}
528
529impl TryFrom<SubscribeRequest> for ConfigFilter {
530 type Error = ConfigFilterError;
531
532 fn try_from(value: SubscribeRequest) -> Result<Self, Self::Error> {
533 Ok(Self {
534 slots: Self::try_conv_map(value.slots)?,
535 accounts: Self::try_conv_map(value.accounts)?,
536 accounts_data_slice: value
537 .accounts_data_slice
538 .into_iter()
539 .map(|ds| ds.try_into())
540 .collect::<Result<_, _>>()?,
541 transactions: Self::try_conv_map(value.transactions)?,
542 transactions_status: Self::try_conv_map(value.transactions_status)?,
543 entries: value.entry.into_keys().collect(),
544 blocks_meta: value.blocks_meta.into_keys().collect(),
545 blocks: Self::try_conv_map(value.blocks)?,
546 commitment: value.commitment.map(|value| value.try_into()).transpose()?,
547 })
548 }
549}
550
551impl From<ConfigFilter> for SubscribeRequest {
552 fn from(value: ConfigFilter) -> Self {
553 SubscribeRequest {
554 slots: ConfigFilter::conv_map(value.slots),
555 accounts: ConfigFilter::conv_map(value.accounts),
556 accounts_data_slice: value
557 .accounts_data_slice
558 .into_iter()
559 .map(|ds| ds.into())
560 .collect(),
561 transactions: ConfigFilter::conv_map(value.transactions),
562 transactions_status: ConfigFilter::conv_map(value.transactions_status),
563 entry: ConfigFilter::conv_set(value.entries),
564 blocks_meta: ConfigFilter::conv_set(value.blocks_meta),
565 blocks: ConfigFilter::conv_map(value.blocks),
566 commitment: value.commitment.map(|c| c.into()),
567 ping: None,
568 from_slot: None,
569 }
570 }
571}
572
573#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize)]
574#[serde(deny_unknown_fields, default)]
575pub struct ConfigFilterSlots {
576 pub filter_by_commitment: Option<bool>,
577 pub interslot_updates: Option<bool>,
578}
579
580impl TryFrom<SubscribeRequestFilterSlots> for ConfigFilterSlots {
581 type Error = ConfigFilterError;
582
583 fn try_from(value: SubscribeRequestFilterSlots) -> Result<Self, Self::Error> {
584 Ok(Self {
585 filter_by_commitment: value.filter_by_commitment,
586 interslot_updates: value.interslot_updates,
587 })
588 }
589}
590
591impl From<ConfigFilterSlots> for SubscribeRequestFilterSlots {
592 fn from(value: ConfigFilterSlots) -> Self {
593 Self {
594 filter_by_commitment: value.filter_by_commitment,
595 interslot_updates: value.interslot_updates,
596 }
597 }
598}
599
600#[derive(Debug, Default, Clone, Deserialize, Serialize)]
601#[serde(deny_unknown_fields, default)]
602pub struct ConfigFilterAccounts {
603 #[serde(deserialize_with = "deserialize_pubkey_vec")]
604 pub account: Vec<Pubkey>,
605 #[serde(deserialize_with = "deserialize_pubkey_vec")]
606 pub owner: Vec<Pubkey>,
607 pub filters: Vec<ConfigFilterAccountsFilter>,
608 pub nonempty_txn_signature: Option<bool>,
609}
610
611impl TryFrom<SubscribeRequestFilterAccounts> for ConfigFilterAccounts {
612 type Error = ConfigFilterError;
613
614 fn try_from(value: SubscribeRequestFilterAccounts) -> Result<Self, Self::Error> {
615 let account = ConfigFilter::parse_vec_pubkeys(value.account)?;
616 let owner = ConfigFilter::parse_vec_pubkeys(value.owner)?;
617
618 if value.filters.len() > MAX_FILTERS {
619 return Err(ConfigLimitsError::TooMuchFilters { max: MAX_FILTERS }.into());
620 }
621
622 let filters = value
623 .filters
624 .into_iter()
625 .map(|filter| filter.try_into())
626 .collect::<Result<Vec<_>, _>>()?;
627
628 Ok(Self {
629 account,
630 owner,
631 filters,
632 nonempty_txn_signature: value.nonempty_txn_signature,
633 })
634 }
635}
636
637impl From<ConfigFilterAccounts> for SubscribeRequestFilterAccounts {
638 fn from(value: ConfigFilterAccounts) -> Self {
639 Self {
640 account: ConfigFilter::conv_vec_pubkeys(value.account),
641 owner: ConfigFilter::conv_vec_pubkeys(value.owner),
642 filters: value.filters.into_iter().map(Into::into).collect(),
643 nonempty_txn_signature: value.nonempty_txn_signature,
644 }
645 }
646}
647
648#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
649#[serde(deny_unknown_fields)]
650pub enum ConfigFilterAccountsFilter {
651 Memcmp { offset: usize, data: Vec<u8> },
652 DataSize(u64),
653 TokenAccountState,
654 Lamports(ConfigFilterAccountsFilterLamports),
655}
656
657impl<'de> Deserialize<'de> for ConfigFilterAccountsFilter {
658 fn deserialize<D>(deserializer: D) -> Result<ConfigFilterAccountsFilter, D::Error>
659 where
660 D: Deserializer<'de>,
661 {
662 #[derive(Debug, Deserialize)]
663 enum ConfigMemcmpData {
664 Str(String),
665 Bytes(Vec<u8>),
666 }
667
668 #[derive(Debug, Deserialize)]
669 enum Config {
670 Memcmp {
671 offset: usize,
672 data: ConfigMemcmpData,
673 },
674 DataSize(u64),
675 TokenAccountState,
676 Lamports(ConfigFilterAccountsFilterLamports),
677 }
678
679 Ok(match Config::deserialize(deserializer)? {
680 Config::Memcmp { offset, data } => {
681 let data = match data {
682 ConfigMemcmpData::Str(data) => match &data[0..7] {
683 "base64:" => base64_engine
684 .decode(&data[7..])
685 .map_err(de::Error::custom)?,
686 "base58:" => bs58::decode(&data[7..])
687 .into_vec()
688 .map_err(de::Error::custom)?,
689 _ => data.as_bytes().to_vec(),
690 },
691 ConfigMemcmpData::Bytes(data) => data,
692 };
693 Self::Memcmp { offset, data }
694 }
695 Config::DataSize(size) => Self::DataSize(size),
696 Config::TokenAccountState => Self::TokenAccountState,
697 Config::Lamports(value) => Self::Lamports(value),
698 })
699 }
700}
701
702impl TryFrom<SubscribeRequestFilterAccountsFilter> for ConfigFilterAccountsFilter {
703 type Error = ConfigFilterError;
704
705 fn try_from(value: SubscribeRequestFilterAccountsFilter) -> Result<Self, Self::Error> {
706 let value = value
707 .filter
708 .ok_or(ConfigFilterError::FieldNotDefined("filter"))?;
709
710 Ok(match value {
711 AccountsFilterDataOneof::Memcmp(memcmp) => {
712 let value = memcmp
713 .data
714 .ok_or(ConfigFilterError::FieldNotDefined("data"))?;
715 let data = match &value {
716 AccountsFilterMemcmpOneof::Bytes(data) => data.clone(),
717 AccountsFilterMemcmpOneof::Base58(data) => {
718 if data.len() > MAX_DATA_BASE58_SIZE {
719 return Err(ConfigLimitsError::FilterDataOverflow.into());
720 }
721 bs58::decode(data)
722 .into_vec()
723 .map_err(|_| ConfigFilterError::InvalidBase58)?
724 }
725 AccountsFilterMemcmpOneof::Base64(data) => {
726 if data.len() > MAX_DATA_BASE64_SIZE {
727 return Err(ConfigLimitsError::FilterDataOverflow.into());
728 }
729 base64_engine
730 .decode(data)
731 .map_err(|_| ConfigFilterError::InvalidBase64)?
732 }
733 };
734 if data.len() > MAX_DATA_SIZE {
735 return Err(ConfigLimitsError::FilterDataOverflow.into());
736 }
737
738 Self::Memcmp {
739 offset: memcmp.offset as usize,
740 data,
741 }
742 }
743 AccountsFilterDataOneof::Datasize(size) => Self::DataSize(size),
744 AccountsFilterDataOneof::TokenAccountState(value) => {
745 if !value {
746 return Err(ConfigFilterError::TokenAccountStateInvalid);
747 }
748 Self::TokenAccountState
749 }
750 AccountsFilterDataOneof::Lamports(lamports) => Self::Lamports(lamports.try_into()?),
751 })
752 }
753}
754
755impl From<ConfigFilterAccountsFilter> for SubscribeRequestFilterAccountsFilter {
756 fn from(value: ConfigFilterAccountsFilter) -> Self {
757 Self {
758 filter: Some(match value {
759 ConfigFilterAccountsFilter::Memcmp { offset, data } => {
760 AccountsFilterDataOneof::Memcmp(SubscribeRequestFilterAccountsFilterMemcmp {
761 offset: offset as u64,
762 data: Some(AccountsFilterMemcmpOneof::Bytes(data)),
763 })
764 }
765 ConfigFilterAccountsFilter::DataSize(size) => {
766 AccountsFilterDataOneof::Datasize(size)
767 }
768 ConfigFilterAccountsFilter::TokenAccountState => {
769 AccountsFilterDataOneof::TokenAccountState(true)
770 }
771 ConfigFilterAccountsFilter::Lamports(value) => {
772 AccountsFilterDataOneof::Lamports(value.into())
773 }
774 }),
775 }
776 }
777}
778
779#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
780#[serde(deny_unknown_fields)]
781pub enum ConfigFilterAccountsFilterLamports {
782 Eq(u64),
783 Ne(u64),
784 Lt(u64),
785 Gt(u64),
786}
787
788impl TryFrom<SubscribeRequestFilterAccountsFilterLamports> for ConfigFilterAccountsFilterLamports {
789 type Error = ConfigFilterError;
790
791 fn try_from(value: SubscribeRequestFilterAccountsFilterLamports) -> Result<Self, Self::Error> {
792 let value = value.cmp.ok_or(ConfigFilterError::FieldNotDefined("cmp"))?;
793
794 Ok(match value {
795 AccountsFilterLamports::Eq(value) => Self::Eq(value),
796 AccountsFilterLamports::Ne(value) => Self::Ne(value),
797 AccountsFilterLamports::Lt(value) => Self::Lt(value),
798 AccountsFilterLamports::Gt(value) => Self::Gt(value),
799 })
800 }
801}
802
803impl From<ConfigFilterAccountsFilterLamports> for SubscribeRequestFilterAccountsFilterLamports {
804 fn from(value: ConfigFilterAccountsFilterLamports) -> Self {
805 Self {
806 cmp: Some(match value {
807 ConfigFilterAccountsFilterLamports::Eq(value) => AccountsFilterLamports::Eq(value),
808 ConfigFilterAccountsFilterLamports::Ne(value) => AccountsFilterLamports::Ne(value),
809 ConfigFilterAccountsFilterLamports::Lt(value) => AccountsFilterLamports::Lt(value),
810 ConfigFilterAccountsFilterLamports::Gt(value) => AccountsFilterLamports::Gt(value),
811 }),
812 }
813 }
814}
815
816#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
817#[serde(deny_unknown_fields)]
818pub struct ConfigFilterAccountsDataSlice {
819 pub offset: u64,
820 pub length: u64,
821}
822
823impl TryFrom<SubscribeRequestAccountsDataSlice> for ConfigFilterAccountsDataSlice {
824 type Error = ConfigFilterError;
825
826 fn try_from(value: SubscribeRequestAccountsDataSlice) -> Result<Self, Self::Error> {
827 Ok(Self {
828 offset: value.offset,
829 length: value.length,
830 })
831 }
832}
833
834impl From<ConfigFilterAccountsDataSlice> for SubscribeRequestAccountsDataSlice {
835 fn from(value: ConfigFilterAccountsDataSlice) -> Self {
836 Self {
837 offset: value.offset,
838 length: value.length,
839 }
840 }
841}
842
843#[derive(Debug, Default, Clone, Deserialize, Serialize)]
844#[serde(deny_unknown_fields, default)]
845pub struct ConfigFilterTransactions {
846 pub vote: Option<bool>,
847 pub failed: Option<bool>,
848 #[serde(deserialize_with = "deserialize_maybe_signature")]
849 pub signature: Option<Signature>,
850 #[serde(deserialize_with = "deserialize_pubkey_vec")]
851 pub account_include: Vec<Pubkey>,
852 #[serde(deserialize_with = "deserialize_pubkey_vec")]
853 pub account_exclude: Vec<Pubkey>,
854 #[serde(deserialize_with = "deserialize_pubkey_vec")]
855 pub account_required: Vec<Pubkey>,
856}
857
858impl TryFrom<SubscribeRequestFilterTransactions> for ConfigFilterTransactions {
859 type Error = ConfigFilterError;
860
861 fn try_from(value: SubscribeRequestFilterTransactions) -> Result<Self, Self::Error> {
862 Ok(Self {
863 vote: value.vote,
864 failed: value.failed,
865 signature: value
866 .signature
867 .map(|sig| {
868 signature_decode(&sig).map_err(|error| ConfigFilterError::Signature(sig, error))
869 })
870 .transpose()?,
871 account_include: ConfigFilter::parse_vec_pubkeys(value.account_include)?,
872 account_exclude: ConfigFilter::parse_vec_pubkeys(value.account_exclude)?,
873 account_required: ConfigFilter::parse_vec_pubkeys(value.account_required)?,
874 })
875 }
876}
877
878impl From<ConfigFilterTransactions> for SubscribeRequestFilterTransactions {
879 fn from(value: ConfigFilterTransactions) -> Self {
880 Self {
881 vote: value.vote,
882 failed: value.failed,
883 signature: value.signature.map(|sig| signature_encode(&sig.into())),
884 account_include: ConfigFilter::conv_vec_pubkeys(value.account_include),
885 account_exclude: ConfigFilter::conv_vec_pubkeys(value.account_exclude),
886 account_required: ConfigFilter::conv_vec_pubkeys(value.account_required),
887 }
888 }
889}
890
891#[derive(Debug, Default, Clone, Deserialize, Serialize)]
892#[serde(deny_unknown_fields, default)]
893pub struct ConfigFilterBlocks {
894 #[serde(deserialize_with = "deserialize_pubkey_vec")]
895 pub account_include: Vec<Pubkey>,
896 pub include_transactions: Option<bool>,
897 pub include_accounts: Option<bool>,
898 pub include_entries: Option<bool>,
899}
900
901impl TryFrom<SubscribeRequestFilterBlocks> for ConfigFilterBlocks {
902 type Error = ConfigFilterError;
903
904 fn try_from(value: SubscribeRequestFilterBlocks) -> Result<Self, Self::Error> {
905 Ok(Self {
906 account_include: ConfigFilter::parse_vec_pubkeys(value.account_include)?,
907 include_transactions: value.include_transactions,
908 include_accounts: value.include_accounts,
909 include_entries: value.include_entries,
910 })
911 }
912}
913
914impl From<ConfigFilterBlocks> for SubscribeRequestFilterBlocks {
915 fn from(value: ConfigFilterBlocks) -> Self {
916 Self {
917 account_include: ConfigFilter::conv_vec_pubkeys(value.account_include),
918 include_transactions: value.include_transactions,
919 include_accounts: value.include_accounts,
920 include_entries: value.include_entries,
921 }
922 }
923}
924
925#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
926#[serde(deny_unknown_fields, rename_all = "lowercase")]
927pub enum ConfigFilterCommitment {
928 #[default]
929 Processed,
930 Confirmed,
931 Finalized,
932}
933
934impl TryFrom<i32> for ConfigFilterCommitment {
935 type Error = ConfigFilterError;
936
937 fn try_from(value: i32) -> Result<Self, Self::Error> {
938 CommitmentLevelProto::try_from(value)
939 .map(Into::into)
940 .map_err(|_error| ConfigFilterError::UnknownCommitment(value))
941 }
942}
943
944impl From<CommitmentLevelProto> for ConfigFilterCommitment {
945 fn from(value: CommitmentLevelProto) -> Self {
946 match value {
947 CommitmentLevelProto::Processed => Self::Processed,
948 CommitmentLevelProto::Confirmed => Self::Confirmed,
949 CommitmentLevelProto::Finalized => Self::Finalized,
950 }
951 }
952}
953
954impl From<ConfigFilterCommitment> for i32 {
955 fn from(value: ConfigFilterCommitment) -> Self {
956 (match value {
957 ConfigFilterCommitment::Processed => CommitmentLevelProto::Processed,
958 ConfigFilterCommitment::Confirmed => CommitmentLevelProto::Confirmed,
959 ConfigFilterCommitment::Finalized => CommitmentLevelProto::Finalized,
960 }) as i32
961 }
962}
963
964impl From<ConfigFilterCommitment> for CommitmentLevel {
965 fn from(value: ConfigFilterCommitment) -> Self {
966 match value {
967 ConfigFilterCommitment::Processed => Self::Processed,
968 ConfigFilterCommitment::Confirmed => Self::Confirmed,
969 ConfigFilterCommitment::Finalized => Self::Finalized,
970 }
971 }
972}