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