miden_client/rpc/domain/
limits.rs1use core::convert::TryFrom;
5
6use miden_tx::utils::serde::{
7 ByteReader,
8 ByteWriter,
9 Deserializable,
10 DeserializationError,
11 Serializable,
12};
13
14use crate::rpc::RpcEndpoint;
15use crate::rpc::errors::RpcConversionError;
16use crate::rpc::generated::rpc as proto;
17
18pub(crate) const RPC_LIMITS_STORE_SETTING: &str = "rpc_limits";
20
21const DEFAULT_NOTE_IDS_LIMIT: u32 = 100;
22const DEFAULT_NULLIFIERS_LIMIT: u32 = 1000;
23const DEFAULT_ACCOUNT_IDS_LIMIT: u32 = 1000;
24const DEFAULT_NOTE_TAGS_LIMIT: u32 = 1000;
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub struct RpcLimits {
32 pub note_ids_limit: u32,
34 pub nullifiers_limit: u32,
36 pub account_ids_limit: u32,
38 pub note_tags_limit: u32,
40}
41
42impl Default for RpcLimits {
43 fn default() -> Self {
44 Self {
45 note_ids_limit: DEFAULT_NOTE_IDS_LIMIT,
46 nullifiers_limit: DEFAULT_NULLIFIERS_LIMIT,
47 account_ids_limit: DEFAULT_ACCOUNT_IDS_LIMIT,
48 note_tags_limit: DEFAULT_NOTE_TAGS_LIMIT,
49 }
50 }
51}
52
53impl Serializable for RpcLimits {
54 fn write_into<W: ByteWriter>(&self, target: &mut W) {
55 self.note_ids_limit.write_into(target);
56 self.nullifiers_limit.write_into(target);
57 self.account_ids_limit.write_into(target);
58 self.note_tags_limit.write_into(target);
59 }
60}
61
62impl Deserializable for RpcLimits {
63 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
64 Ok(Self {
65 note_ids_limit: u32::read_from(source)?,
66 nullifiers_limit: u32::read_from(source)?,
67 account_ids_limit: u32::read_from(source)?,
68 note_tags_limit: u32::read_from(source)?,
69 })
70 }
71}
72
73fn get_param(
75 proto: &proto::RpcLimits,
76 endpoint: RpcEndpoint,
77 param: &'static str,
78) -> Result<u32, RpcConversionError> {
79 let ep = proto.endpoints.get(endpoint.proto_name()).ok_or(
80 RpcConversionError::MissingFieldInProtobufRepresentation {
81 entity: "RpcLimits",
82 field_name: param,
83 },
84 )?;
85 let limit = ep.parameters.get(param).ok_or(
86 RpcConversionError::MissingFieldInProtobufRepresentation {
87 entity: "RpcLimits",
88 field_name: param,
89 },
90 )?;
91 Ok(*limit)
92}
93
94impl TryFrom<proto::RpcLimits> for RpcLimits {
95 type Error = RpcConversionError;
96
97 fn try_from(proto: proto::RpcLimits) -> Result<Self, Self::Error> {
98 Ok(Self {
99 note_ids_limit: get_param(&proto, RpcEndpoint::GetNotesById, "note_id")?,
100 nullifiers_limit: get_param(&proto, RpcEndpoint::SyncNullifiers, "nullifier_prefix")?,
101 account_ids_limit: get_param(&proto, RpcEndpoint::SyncTransactions, "account_id")?,
102 note_tags_limit: get_param(&proto, RpcEndpoint::SyncNotes, "note_tag")?,
103 })
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn rpc_limits_serialization_roundtrip() {
113 let original = RpcLimits {
114 note_ids_limit: 100,
115 nullifiers_limit: 1000,
116 account_ids_limit: 1000,
117 note_tags_limit: 1000,
118 };
119
120 let bytes = original.to_bytes();
121 let deserialized = RpcLimits::read_from_bytes(&bytes).expect("deserialization failed");
122
123 assert_eq!(original, deserialized);
124 }
125}