Skip to main content

hiero_sdk/
prng_transaction.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use hiero_sdk_proto::services;
4use hiero_sdk_proto::services::util_service_client::UtilServiceClient;
5
6use crate::entity_id::ValidateChecksums;
7use crate::protobuf::{
8    FromProtobuf,
9    ToProtobuf,
10};
11use crate::transaction::{
12    AnyTransactionData,
13    ChunkInfo,
14    ToSchedulableTransactionDataProtobuf,
15    ToTransactionDataProtobuf,
16    TransactionData,
17    TransactionExecute,
18};
19use crate::Transaction;
20
21/// Random Number Generator Transaction.
22pub type PrngTransaction = Transaction<PrngTransactionData>;
23
24#[derive(Debug, Clone, Default)]
25#[cfg_attr(test, derive(Eq, PartialEq))]
26pub struct PrngTransactionData {
27    range: Option<u32>,
28}
29
30impl PrngTransaction {
31    /// Returns the upper-bound for the random number.
32    pub fn get_range(&self) -> Option<u32> {
33        self.data().range
34    }
35
36    /// Sets the upper-bound for the random number.
37    ///
38    /// If the value is zero, instead of returning a 32-bit number, a 384-bit number will be returned.
39    pub fn range(&mut self, range: u32) -> &mut Self {
40        self.data_mut().range = Some(range);
41
42        self
43    }
44}
45
46impl FromProtobuf<services::UtilPrngTransactionBody> for PrngTransactionData {
47    fn from_protobuf(pb: services::UtilPrngTransactionBody) -> crate::Result<Self> {
48        Ok(Self { range: (pb.range != 0).then_some(pb.range as u32) })
49    }
50}
51
52impl ToProtobuf for PrngTransactionData {
53    type Protobuf = services::UtilPrngTransactionBody;
54    fn to_protobuf(&self) -> Self::Protobuf {
55        services::UtilPrngTransactionBody { range: self.range.unwrap_or_default() as i32 }
56    }
57}
58
59impl TransactionData for PrngTransactionData {}
60
61impl From<PrngTransactionData> for AnyTransactionData {
62    fn from(value: PrngTransactionData) -> Self {
63        Self::Prng(value)
64    }
65}
66
67impl ValidateChecksums for PrngTransactionData {
68    fn validate_checksums(&self, _ledger_id: &crate::ledger_id::RefLedgerId) -> crate::Result<()> {
69        Ok(())
70    }
71}
72
73impl ToSchedulableTransactionDataProtobuf for PrngTransactionData {
74    fn to_schedulable_transaction_data_protobuf(
75        &self,
76    ) -> services::schedulable_transaction_body::Data {
77        services::schedulable_transaction_body::Data::UtilPrng(self.to_protobuf())
78    }
79}
80
81impl ToTransactionDataProtobuf for PrngTransactionData {
82    fn to_transaction_data_protobuf(
83        &self,
84        chunk_info: &ChunkInfo,
85    ) -> services::transaction_body::Data {
86        let _ = chunk_info.assert_single_transaction();
87
88        services::transaction_body::Data::UtilPrng(self.to_protobuf())
89    }
90}
91
92impl TransactionExecute for PrngTransactionData {
93    fn execute(
94        &self,
95        channel: tonic::transport::Channel,
96        request: services::Transaction,
97    ) -> crate::BoxGrpcFuture<'_, services::TransactionResponse> {
98        Box::pin(async { UtilServiceClient::new(channel).prng(request).await })
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use expect_test::expect;
105
106    use crate::transaction::test_helpers::{
107        check_body,
108        transaction_body,
109    };
110    use crate::{
111        AnyTransaction,
112        PrngTransaction,
113    };
114
115    fn make_transaction() -> PrngTransaction {
116        let mut tx = PrngTransaction::new_for_tests();
117
118        tx.freeze().unwrap();
119
120        tx
121    }
122
123    fn make_transaction2() -> PrngTransaction {
124        let mut tx = PrngTransaction::new_for_tests();
125
126        tx.range(100).freeze().unwrap();
127
128        tx
129    }
130
131    #[test]
132    fn serialize() {
133        let tx = make_transaction();
134
135        let tx = transaction_body(tx);
136
137        let tx = check_body(tx);
138
139        expect![[r#"
140            UtilPrng(
141                UtilPrngTransactionBody {
142                    range: 0,
143                },
144            )
145        "#]]
146        .assert_debug_eq(&tx)
147    }
148
149    #[test]
150    fn to_from_bytes() {
151        let tx = make_transaction();
152
153        let tx2 = AnyTransaction::from_bytes(&tx.to_bytes().unwrap()).unwrap();
154
155        let tx = transaction_body(tx);
156
157        let tx2 = transaction_body(tx2);
158
159        assert_eq!(tx, tx2);
160    }
161
162    #[test]
163    fn serialize2() {
164        let tx = make_transaction2();
165
166        let tx = transaction_body(tx);
167
168        let tx = check_body(tx);
169
170        expect![[r#"
171            UtilPrng(
172                UtilPrngTransactionBody {
173                    range: 100,
174                },
175            )
176        "#]]
177        .assert_debug_eq(&tx)
178    }
179
180    #[test]
181    fn to_from_bytes2() {
182        let tx = make_transaction2();
183
184        let tx2 = AnyTransaction::from_bytes(&tx.to_bytes().unwrap()).unwrap();
185
186        let tx = transaction_body(tx);
187
188        let tx2 = transaction_body(tx2);
189
190        assert_eq!(tx, tx2);
191    }
192}