Skip to main content

hiero_sdk/topic/
topic_update_transaction.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use hiero_sdk_proto::services;
4use hiero_sdk_proto::services::consensus_service_client::ConsensusServiceClient;
5use time::{
6    Duration,
7    OffsetDateTime,
8};
9use tonic::transport::Channel;
10
11use crate::custom_fixed_fee::CustomFixedFee;
12use crate::ledger_id::RefLedgerId;
13use crate::protobuf::{
14    FromProtobuf,
15    ToProtobuf,
16};
17use crate::transaction::{
18    AnyTransactionData,
19    ChunkInfo,
20    ToSchedulableTransactionDataProtobuf,
21    ToTransactionDataProtobuf,
22    TransactionData,
23    TransactionExecute,
24};
25use crate::{
26    AccountId,
27    BoxGrpcFuture,
28    Error,
29    Key,
30    TopicId,
31    Transaction,
32    ValidateChecksums,
33};
34
35/// Change properties for the given topic.
36///
37/// Any null field is ignored (left unchanged).
38///
39pub type TopicUpdateTransaction = Transaction<TopicUpdateTransactionData>;
40
41#[derive(Debug, Clone, Default)]
42pub struct TopicUpdateTransactionData {
43    /// The topic ID which is being updated in this transaction.
44    topic_id: Option<TopicId>,
45
46    /// The new expiration time to extend to (ignored if equal to or before the current one).
47    expiration_time: Option<OffsetDateTime>,
48
49    /// Short publicly visible memo about the topic. No guarantee of uniqueness.
50    topic_memo: Option<String>,
51
52    /// Access control for `TopicUpdateTransaction` and `TopicDeleteTransaction`.
53    admin_key: Option<Key>,
54
55    /// Access control for `TopicMessageSubmitTransaction`.
56    submit_key: Option<Key>,
57
58    /// The initial lifetime of the topic and the amount of time to attempt to
59    /// extend the topic's lifetime by automatically at the topic's expiration time, if
60    /// the `auto_renew_account_id` is configured.
61    auto_renew_period: Option<Duration>,
62
63    /// Optional account to be used at the topic's expiration time to extend the life of the topic.
64    auto_renew_account_id: Option<AccountId>,
65
66    /// Access control for update/delete of custom fees.
67    /// None if the key should not be updated.
68    fee_schedule_key: Option<Key>,
69
70    /// If the transaction contains a signer from this list, no custom fees are applied.
71    /// None means the field will not be updated.
72    /// Some(vec![]) means the field will be cleared.
73    fee_exempt_keys: Option<Vec<Key>>,
74
75    /// The custom fee to be assessed during a message submission to this topic.
76    /// None means the field will not be updated.
77    /// Some(vec![]) means the field will be cleared.
78    custom_fees: Option<Vec<CustomFixedFee>>,
79}
80
81impl TopicUpdateTransaction {
82    /// Returns the topic ID which is being updated.
83    #[must_use]
84    pub fn get_topic_id(&self) -> Option<TopicId> {
85        self.data().topic_id
86    }
87
88    /// Sets the topic ID which is being updated.
89    pub fn topic_id(&mut self, id: impl Into<TopicId>) -> &mut Self {
90        self.data_mut().topic_id = Some(id.into());
91        self
92    }
93
94    /// Returns the new expiration time to extend to (ignored if equal to or before the current one).
95    #[must_use]
96    pub fn get_expiration_time(&self) -> Option<OffsetDateTime> {
97        self.data().expiration_time
98    }
99
100    /// Sets the new expiration time to extend to (ignored if equal to or before the current one).
101    pub fn expiration_time(&mut self, at: OffsetDateTime) -> &mut Self {
102        self.data_mut().expiration_time = Some(at);
103        self
104    }
105
106    /// Returns the new topic memo for the topic.
107    #[must_use]
108    pub fn get_topic_memo(&self) -> Option<&str> {
109        self.data().topic_memo.as_deref()
110    }
111
112    /// Sets the short publicly visible memo about the topic.
113    ///
114    /// No guarantee of uniqueness.
115    pub fn topic_memo(&mut self, memo: impl Into<String>) -> &mut Self {
116        self.data_mut().topic_memo = Some(memo.into());
117        self
118    }
119
120    /// Returns the access control for [`TopicUpdateTransaction`] and [`TopicDeleteTransaction`](crate::TopicDeleteTransaction).
121    #[must_use]
122    pub fn get_admin_key(&self) -> Option<&Key> {
123        self.data().admin_key.as_ref()
124    }
125
126    /// Sets the access control for [`TopicUpdateTransaction`] and [`TopicDeleteTransaction`](crate::TopicDeleteTransaction).
127    pub fn admin_key(&mut self, key: impl Into<Key>) -> &mut Self {
128        self.data_mut().admin_key = Some(key.into());
129        self
130    }
131
132    /// Clears the access control for [`TopicUpdateTransaction`] and [`TopicDeleteTransaction`](crate::TopicDeleteTransaction).
133    pub fn clear_admin_key(&mut self) -> &mut Self {
134        self.data_mut().admin_key = Some(Key::KeyList(crate::KeyList::new()));
135        self
136    }
137
138    /// Returns the access control for [`TopicMessageSubmitTransaction`](crate::TopicMessageSubmitTransaction).
139    #[must_use]
140    pub fn get_submit_key(&self) -> Option<&Key> {
141        self.data().submit_key.as_ref()
142    }
143
144    /// Sets the access control for [`TopicMessageSubmitTransaction`](crate::TopicMessageSubmitTransaction).
145    pub fn submit_key(&mut self, key: impl Into<Key>) -> &mut Self {
146        self.data_mut().submit_key = Some(key.into());
147        self
148    }
149    /// Clears the access control for [`TopicUpdateTransaction`] and [`TopicDeleteTransaction`](crate::TopicDeleteTransaction).
150    pub fn clear_submit_key(&mut self) -> &mut Self {
151        self.data_mut().submit_key = Some(Key::KeyList(crate::KeyList::new()));
152        self
153    }
154
155    /// Returns the initial lifetime of the topic and the amount of time to attempt to
156    /// extend the topic's lifetime by automatically at the topic's expiration time.
157    #[must_use]
158    pub fn get_auto_renew_period(&self) -> Option<Duration> {
159        self.data().auto_renew_period
160    }
161
162    /// Sets the initial lifetime of the topic and the amount of time to attempt to
163    /// extend the topic's lifetime by automatically at the topic's expiration time.
164    pub fn auto_renew_period(&mut self, period: Duration) -> &mut Self {
165        self.data_mut().auto_renew_period = Some(period);
166        self
167    }
168
169    /// Returns the account to be used at the topic's expiration time to extend the life of the topic.
170    #[must_use]
171    pub fn get_auto_renew_account_id(&self) -> Option<AccountId> {
172        self.data().auto_renew_account_id
173    }
174
175    /// Sets the account to be used at the topic's expiration time to extend the life of the topic.
176    pub fn auto_renew_account_id(&mut self, id: AccountId) -> &mut Self {
177        self.data_mut().auto_renew_account_id = Some(id);
178        self
179    }
180
181    /// Clear the auto renew account ID for this topic.
182    pub fn clear_auto_renew_account_id(&mut self) -> &mut Self {
183        self.auto_renew_account_id(AccountId {
184            shard: 0,
185            realm: 0,
186            num: 0,
187            alias: None,
188            evm_address: None,
189            checksum: None,
190        })
191    }
192
193    /// The key that can be used to update the fee schedule for the topic.
194    pub fn fee_schedule_key(&mut self, key: impl Into<Key>) -> &mut Self {
195        self.data_mut().fee_schedule_key = Some(key.into());
196        self
197    }
198
199    /// The key that can be used to update the fee schedule for the topic.
200    #[must_use]
201    pub fn get_fee_schedule_key(&self) -> Option<&Key> {
202        self.data().fee_schedule_key.as_ref()
203    }
204
205    /// The keys that can be used to update the fee schedule for the topic.
206    pub fn fee_exempt_keys(&mut self, keys: Vec<Key>) -> &mut Self {
207        self.data_mut().fee_exempt_keys = Some(keys);
208        self
209    }
210
211    /// The keys that can be used to update the fee schedule for the topic.
212    #[must_use]
213    pub fn get_fee_exempt_keys(&self) -> Option<&Vec<Key>> {
214        self.data().fee_exempt_keys.as_ref()
215    }
216
217    /// Clears the keys that can be used to update the fee schedule for the topic.
218    /// This will send an empty list to consensus, clearing all keys.
219    pub fn clear_fee_exempt_keys(&mut self) -> &mut Self {
220        self.data_mut().fee_exempt_keys = Some(vec![]);
221        self
222    }
223
224    /// Adds a key to the list of keys that can be used to update the fee schedule for the topic.
225    pub fn add_fee_exempt_key(&mut self, key: Key) -> &mut Self {
226        let data = self.data_mut();
227        if let Some(keys) = &mut data.fee_exempt_keys {
228            keys.push(key);
229        } else {
230            data.fee_exempt_keys = Some(vec![key]);
231        }
232        self
233    }
234
235    /// The custom fees to be assessed during a message submission to this topic.
236    pub fn custom_fees(&mut self, fees: Vec<CustomFixedFee>) -> &mut Self {
237        self.data_mut().custom_fees = Some(fees);
238        self
239    }
240
241    /// Clears the custom fees for this topic.
242    /// This will send an empty list to consensus, clearing all custom fees.
243    pub fn clear_custom_fees(&mut self) -> &mut Self {
244        self.data_mut().custom_fees = Some(vec![]);
245        self
246    }
247
248    /// The custom fees to be assessed during a message submission to this topic.
249    #[must_use]
250    pub fn get_custom_fees(&self) -> Option<&Vec<CustomFixedFee>> {
251        self.data().custom_fees.as_ref()
252    }
253
254    /// Adds a custom fee to the list of custom fees for this topic.
255    pub fn add_custom_fee(&mut self, fee: CustomFixedFee) -> &mut Self {
256        self.data_mut().custom_fees = Some(vec![fee]);
257        self
258    }
259}
260
261impl TransactionData for TopicUpdateTransactionData {}
262
263impl TransactionExecute for TopicUpdateTransactionData {
264    fn execute(
265        &self,
266        channel: Channel,
267        request: services::Transaction,
268    ) -> BoxGrpcFuture<'_, services::TransactionResponse> {
269        Box::pin(async { ConsensusServiceClient::new(channel).update_topic(request).await })
270    }
271}
272
273impl ValidateChecksums for TopicUpdateTransactionData {
274    fn validate_checksums(&self, ledger_id: &RefLedgerId) -> Result<(), Error> {
275        self.topic_id.validate_checksums(ledger_id)?;
276        self.auto_renew_account_id.validate_checksums(ledger_id)
277    }
278}
279
280impl ToTransactionDataProtobuf for TopicUpdateTransactionData {
281    fn to_transaction_data_protobuf(
282        &self,
283        chunk_info: &ChunkInfo,
284    ) -> services::transaction_body::Data {
285        let _ = chunk_info.assert_single_transaction();
286
287        services::transaction_body::Data::ConsensusUpdateTopic(self.to_protobuf())
288    }
289}
290
291impl ToSchedulableTransactionDataProtobuf for TopicUpdateTransactionData {
292    fn to_schedulable_transaction_data_protobuf(
293        &self,
294    ) -> services::schedulable_transaction_body::Data {
295        services::schedulable_transaction_body::Data::ConsensusUpdateTopic(self.to_protobuf())
296    }
297}
298
299impl From<TopicUpdateTransactionData> for AnyTransactionData {
300    fn from(transaction: TopicUpdateTransactionData) -> Self {
301        Self::TopicUpdate(transaction)
302    }
303}
304
305impl FromProtobuf<services::ConsensusUpdateTopicTransactionBody> for TopicUpdateTransactionData {
306    fn from_protobuf(pb: services::ConsensusUpdateTopicTransactionBody) -> crate::Result<Self> {
307        let custom_fees = if let Some(custom_fees) = pb.custom_fees {
308            Some(
309                custom_fees
310                    .fees
311                    .into_iter()
312                    .map(CustomFixedFee::from_protobuf)
313                    .collect::<Result<Vec<_>, _>>()?,
314            )
315        } else {
316            None
317        };
318
319        let fee_exempt_keys = if let Some(fee_exempt_keys) = pb.fee_exempt_key_list {
320            Some(
321                fee_exempt_keys
322                    .keys
323                    .into_iter()
324                    .map(|pb_key| Key::from_protobuf(pb_key))
325                    .collect::<Result<Vec<_>, _>>()?,
326            )
327        } else {
328            None
329        };
330
331        Ok(Self {
332            topic_id: Option::from_protobuf(pb.topic_id)?,
333            expiration_time: pb.expiration_time.map(Into::into),
334            topic_memo: pb.memo,
335            admin_key: Option::from_protobuf(pb.admin_key)?,
336            submit_key: Option::from_protobuf(pb.submit_key)?,
337            auto_renew_period: pb.auto_renew_period.map(Into::into),
338            auto_renew_account_id: Option::from_protobuf(pb.auto_renew_account)?,
339            fee_schedule_key: Option::from_protobuf(pb.fee_schedule_key)?,
340            fee_exempt_keys,
341            custom_fees,
342        })
343    }
344}
345
346impl ToProtobuf for TopicUpdateTransactionData {
347    type Protobuf = services::ConsensusUpdateTopicTransactionBody;
348
349    fn to_protobuf(&self) -> Self::Protobuf {
350        let topic_id = self.topic_id.to_protobuf();
351        let expiration_time = self.expiration_time.map(Into::into);
352        let admin_key = self.admin_key.to_protobuf();
353        let submit_key = self.submit_key.to_protobuf();
354        let fee_schedule_key = self.fee_schedule_key.to_protobuf();
355
356        let auto_renew_period = self.auto_renew_period.map(Into::into);
357        let auto_renew_account_id = self.auto_renew_account_id.to_protobuf();
358        let custom_fees = self.custom_fees.as_ref().map(|fees| services::FixedCustomFeeList {
359            fees: fees.iter().map(|fee| fee.to_protobuf()).collect(),
360        });
361
362        let fee_exempt_key_list = self.fee_exempt_keys.as_ref().map(|keys| {
363            services::FeeExemptKeyList { keys: keys.iter().map(|key| key.to_protobuf()).collect() }
364        });
365
366        services::ConsensusUpdateTopicTransactionBody {
367            auto_renew_account: auto_renew_account_id,
368            memo: self.topic_memo.clone(),
369            expiration_time,
370            topic_id,
371            admin_key,
372            submit_key,
373            auto_renew_period,
374            fee_exempt_key_list,
375            fee_schedule_key,
376            custom_fees,
377        }
378    }
379}
380
381#[cfg(test)]
382mod tests {
383    use expect_test::expect;
384    use time::{
385        Duration,
386        OffsetDateTime,
387    };
388
389    use crate::custom_fixed_fee::CustomFixedFee;
390    use crate::transaction::test_helpers::{
391        check_body,
392        transaction_body,
393        unused_private_key,
394        VALID_START,
395    };
396    use crate::{
397        AccountId,
398        AnyTransaction,
399        Key,
400        PrivateKey,
401        TokenId,
402        TopicId,
403        TopicUpdateTransaction,
404    };
405
406    const TEST_TOPIC_ID: TopicId = TopicId::new(0, 0, 5007);
407    const TEST_TOPIC_MEMO: &str = "test memo";
408    const TEST_AUTO_RENEW_PERIOD: Duration = Duration::days(1);
409    const TEST_AUTO_RENEW_ACCOUNT_ID: AccountId = AccountId::new(0, 0, 5007);
410    const TEST_EXPIRATION_TIME: OffsetDateTime = VALID_START;
411
412    fn make_transaction() -> TopicUpdateTransaction {
413        let mut tx = TopicUpdateTransaction::new_for_tests();
414
415        tx.topic_id("0.0.5007".parse::<TopicId>().unwrap())
416            .clear_admin_key()
417            .clear_auto_renew_account_id()
418            .clear_submit_key()
419            .topic_memo("")
420            .freeze()
421            .unwrap();
422
423        tx
424    }
425
426    #[test]
427    fn serialize() {
428        let tx = make_transaction();
429
430        let tx = transaction_body(tx);
431
432        let tx = check_body(tx);
433
434        expect![[r#"
435            ConsensusUpdateTopic(
436                ConsensusUpdateTopicTransactionBody {
437                    topic_id: Some(
438                        TopicId {
439                            shard_num: 0,
440                            realm_num: 0,
441                            topic_num: 5007,
442                        },
443                    ),
444                    memo: Some(
445                        "",
446                    ),
447                    expiration_time: None,
448                    admin_key: Some(
449                        Key {
450                            key: Some(
451                                KeyList(
452                                    KeyList {
453                                        keys: [],
454                                    },
455                                ),
456                            ),
457                        },
458                    ),
459                    submit_key: Some(
460                        Key {
461                            key: Some(
462                                KeyList(
463                                    KeyList {
464                                        keys: [],
465                                    },
466                                ),
467                            ),
468                        },
469                    ),
470                    auto_renew_period: None,
471                    auto_renew_account: Some(
472                        AccountId {
473                            shard_num: 0,
474                            realm_num: 0,
475                            account: Some(
476                                AccountNum(
477                                    0,
478                                ),
479                            ),
480                        },
481                    ),
482                    fee_schedule_key: None,
483                    fee_exempt_key_list: None,
484                    custom_fees: None,
485                },
486            )
487        "#]]
488        .assert_debug_eq(&tx)
489    }
490
491    #[test]
492    fn to_from_bytes() {
493        let tx = make_transaction();
494
495        let tx2 = AnyTransaction::from_bytes(&tx.to_bytes().unwrap()).unwrap();
496
497        let tx = transaction_body(tx);
498
499        let tx2 = transaction_body(tx2);
500
501        assert_eq!(tx, tx2);
502    }
503
504    fn make_transaction2() -> TopicUpdateTransaction {
505        let mut tx = TopicUpdateTransaction::new_for_tests();
506
507        tx.topic_id("0.0.5007".parse::<TopicId>().unwrap())
508            .admin_key(unused_private_key().public_key())
509            .auto_renew_account_id("0.0.5009".parse().unwrap())
510            .auto_renew_period(Duration::days(1))
511            .submit_key(unused_private_key().public_key())
512            .topic_memo("Hello memo")
513            .expiration_time(VALID_START)
514            .freeze()
515            .unwrap();
516
517        tx
518    }
519
520    #[test]
521    fn serialize2() {
522        let tx = make_transaction2();
523
524        let tx = transaction_body(tx);
525
526        let tx = check_body(tx);
527
528        expect![[r#"
529            ConsensusUpdateTopic(
530                ConsensusUpdateTopicTransactionBody {
531                    topic_id: Some(
532                        TopicId {
533                            shard_num: 0,
534                            realm_num: 0,
535                            topic_num: 5007,
536                        },
537                    ),
538                    memo: Some(
539                        "Hello memo",
540                    ),
541                    expiration_time: Some(
542                        Timestamp {
543                            seconds: 1554158542,
544                            nanos: 0,
545                        },
546                    ),
547                    admin_key: Some(
548                        Key {
549                            key: Some(
550                                Ed25519(
551                                    [
552                                        224,
553                                        200,
554                                        236,
555                                        39,
556                                        88,
557                                        165,
558                                        135,
559                                        159,
560                                        250,
561                                        194,
562                                        38,
563                                        161,
564                                        60,
565                                        12,
566                                        81,
567                                        107,
568                                        121,
569                                        158,
570                                        114,
571                                        227,
572                                        81,
573                                        65,
574                                        160,
575                                        221,
576                                        130,
577                                        143,
578                                        148,
579                                        211,
580                                        121,
581                                        136,
582                                        164,
583                                        183,
584                                    ],
585                                ),
586                            ),
587                        },
588                    ),
589                    submit_key: Some(
590                        Key {
591                            key: Some(
592                                Ed25519(
593                                    [
594                                        224,
595                                        200,
596                                        236,
597                                        39,
598                                        88,
599                                        165,
600                                        135,
601                                        159,
602                                        250,
603                                        194,
604                                        38,
605                                        161,
606                                        60,
607                                        12,
608                                        81,
609                                        107,
610                                        121,
611                                        158,
612                                        114,
613                                        227,
614                                        81,
615                                        65,
616                                        160,
617                                        221,
618                                        130,
619                                        143,
620                                        148,
621                                        211,
622                                        121,
623                                        136,
624                                        164,
625                                        183,
626                                    ],
627                                ),
628                            ),
629                        },
630                    ),
631                    auto_renew_period: Some(
632                        Duration {
633                            seconds: 86400,
634                        },
635                    ),
636                    auto_renew_account: Some(
637                        AccountId {
638                            shard_num: 0,
639                            realm_num: 0,
640                            account: Some(
641                                AccountNum(
642                                    5009,
643                                ),
644                            ),
645                        },
646                    ),
647                    fee_schedule_key: None,
648                    fee_exempt_key_list: None,
649                    custom_fees: None,
650                },
651            )
652        "#]]
653        .assert_debug_eq(&tx)
654    }
655
656    #[test]
657    fn to_from_bytes2() {
658        let tx = make_transaction2();
659
660        let tx2 = AnyTransaction::from_bytes(&tx.to_bytes().unwrap()).unwrap();
661
662        let tx = transaction_body(tx);
663
664        let tx2 = transaction_body(tx2);
665
666        assert_eq!(tx, tx2);
667    }
668
669    #[test]
670    fn get_set_topic_id() {
671        let mut tx = TopicUpdateTransaction::new();
672        tx.topic_id(TEST_TOPIC_ID);
673
674        assert_eq!(tx.get_topic_id(), Some(TEST_TOPIC_ID));
675    }
676
677    #[test]
678    #[should_panic]
679    fn get_set_topic_id_frozen_panics() {
680        make_transaction().topic_id(TEST_TOPIC_ID);
681    }
682
683    #[test]
684    fn get_set_topic_memo() {
685        let mut tx = TopicUpdateTransaction::new();
686        tx.topic_memo(TEST_TOPIC_MEMO);
687
688        assert_eq!(tx.get_topic_memo(), Some(TEST_TOPIC_MEMO));
689    }
690
691    #[test]
692    #[should_panic]
693    fn get_set_topic_memo_frozen_panics() {
694        make_transaction().topic_memo(TEST_TOPIC_MEMO);
695    }
696
697    #[test]
698    fn get_set_expiration_time() {
699        let mut tx = TopicUpdateTransaction::new();
700        tx.expiration_time(TEST_EXPIRATION_TIME);
701
702        assert_eq!(tx.get_expiration_time(), Some(TEST_EXPIRATION_TIME));
703    }
704
705    #[test]
706    #[should_panic]
707    fn get_set_expiration_time_frozen_panics() {
708        make_transaction().expiration_time(TEST_EXPIRATION_TIME);
709    }
710
711    #[test]
712    fn get_set_admin_key() {
713        let mut tx = TopicUpdateTransaction::new();
714        tx.admin_key(unused_private_key().public_key());
715
716        assert_eq!(tx.get_admin_key(), Some(&unused_private_key().public_key().into()));
717    }
718
719    #[test]
720    #[should_panic]
721    fn get_set_admin_key_frozen_panics() {
722        make_transaction().admin_key(unused_private_key().public_key());
723    }
724
725    #[test]
726    fn clear_admin_key() {
727        let mut tx = TopicUpdateTransaction::new();
728        tx.admin_key(unused_private_key().public_key());
729        tx.clear_admin_key();
730
731        assert_eq!(tx.get_admin_key(), Some(&Key::KeyList(crate::KeyList::new())));
732    }
733
734    #[test]
735    #[should_panic]
736    fn clear_admin_key_frozen_panics() {
737        make_transaction().clear_admin_key();
738    }
739
740    #[test]
741    fn get_set_submit_key() {
742        let mut tx = TopicUpdateTransaction::new();
743        tx.submit_key(unused_private_key().public_key());
744
745        assert_eq!(tx.get_submit_key(), Some(&unused_private_key().public_key().into()));
746    }
747
748    #[test]
749    #[should_panic]
750    fn get_set_submit_key_frozen_panics() {
751        make_transaction().submit_key(unused_private_key().public_key());
752    }
753
754    #[test]
755    fn clear_submit_key() {
756        let mut tx = TopicUpdateTransaction::new();
757        tx.submit_key(unused_private_key().public_key());
758        tx.clear_submit_key();
759
760        assert_eq!(tx.get_submit_key(), Some(&Key::KeyList(crate::KeyList::new())));
761    }
762
763    #[test]
764    #[should_panic]
765    fn clear_submit_key_frozen_panics() {
766        make_transaction().clear_submit_key();
767    }
768
769    #[test]
770    fn get_set_auto_renew_period() {
771        let mut tx = TopicUpdateTransaction::new();
772        tx.auto_renew_period(TEST_AUTO_RENEW_PERIOD);
773
774        assert_eq!(tx.get_auto_renew_period(), Some(TEST_AUTO_RENEW_PERIOD));
775    }
776
777    #[test]
778    #[should_panic]
779    fn get_set_auto_renew_period_frozen_panics() {
780        make_transaction().auto_renew_period(TEST_AUTO_RENEW_PERIOD);
781    }
782
783    #[test]
784    fn get_set_auto_renew_account_id() {
785        let mut tx = TopicUpdateTransaction::new();
786        tx.auto_renew_account_id(TEST_AUTO_RENEW_ACCOUNT_ID);
787
788        assert_eq!(tx.get_auto_renew_account_id(), Some(TEST_AUTO_RENEW_ACCOUNT_ID));
789    }
790
791    #[test]
792    #[should_panic]
793    fn get_set_auto_renew_account_id_frozen_panics() {
794        make_transaction().auto_renew_account_id(TEST_AUTO_RENEW_ACCOUNT_ID);
795    }
796
797    #[test]
798    fn clear_auto_renew_account_id() {
799        let mut tx = TopicUpdateTransaction::new();
800        tx.auto_renew_account_id(TEST_AUTO_RENEW_ACCOUNT_ID);
801        tx.clear_auto_renew_account_id();
802
803        assert_eq!(tx.get_auto_renew_account_id(), Some(AccountId::new(0, 0, 0)));
804    }
805
806    #[test]
807    #[should_panic]
808    fn clear_auto_renew_account_id_frozen_panics() {
809        make_transaction().clear_auto_renew_account_id();
810    }
811
812    #[test]
813    fn get_set_fee_schedule_key() {
814        let fee_schedule_key = PrivateKey::generate_ecdsa();
815        let mut tx = TopicUpdateTransaction::new();
816        tx.fee_schedule_key(fee_schedule_key.public_key());
817
818        assert_eq!(tx.get_fee_schedule_key(), Some(&fee_schedule_key.public_key().into()));
819    }
820
821    #[test]
822    fn get_set_fee_exempt_keys() {
823        let fee_exempt_keys = vec![PrivateKey::generate_ecdsa(), PrivateKey::generate_ecdsa()];
824        let mut tx = TopicUpdateTransaction::new();
825        tx.fee_exempt_keys(fee_exempt_keys.iter().map(|key| key.public_key().into()).collect());
826
827        let expected_keys =
828            fee_exempt_keys.iter().map(|key| key.public_key().into()).collect::<Vec<_>>();
829
830        assert_eq!(tx.get_fee_exempt_keys(), Some(&expected_keys));
831    }
832
833    #[test]
834    fn add_fee_exempt_key_to_empty_list() {
835        let mut tx = TopicUpdateTransaction::new();
836        let fee_exempt_key = PrivateKey::generate_ecdsa();
837        tx.add_fee_exempt_key(fee_exempt_key.public_key().into());
838
839        assert_eq!(tx.get_fee_exempt_keys(), Some(&vec![fee_exempt_key.public_key().into()]));
840    }
841
842    #[test]
843    fn add_fee_exempt_key_to_list() {
844        let fee_exempt_key = PrivateKey::generate_ecdsa();
845        let mut tx = TopicUpdateTransaction::new();
846        tx.fee_exempt_keys(vec![fee_exempt_key.public_key().into()]);
847
848        let fee_exempt_key_to_add = PrivateKey::generate_ecdsa();
849        tx.add_fee_exempt_key(fee_exempt_key_to_add.public_key().into());
850
851        let expected_keys =
852            vec![fee_exempt_key.public_key().into(), fee_exempt_key_to_add.public_key().into()];
853
854        assert_eq!(tx.get_fee_exempt_keys(), Some(&expected_keys));
855    }
856
857    #[test]
858    fn clear_fee_exempt_keys() {
859        let fee_exempt_key = PrivateKey::generate_ecdsa();
860        let mut tx = TopicUpdateTransaction::new();
861        tx.fee_exempt_keys(vec![fee_exempt_key.public_key().into()]);
862        tx.clear_fee_exempt_keys();
863
864        assert_eq!(tx.get_fee_exempt_keys(), Some(&vec![]));
865    }
866
867    #[test]
868    fn get_set_custom_fees() {
869        let custom_fees = vec![
870            CustomFixedFee::new(1, Some(TokenId::new(0, 0, 0)), None),
871            CustomFixedFee::new(2, Some(TokenId::new(0, 0, 1)), None),
872            CustomFixedFee::new(3, Some(TokenId::new(0, 0, 2)), None),
873        ];
874
875        let mut tx = TopicUpdateTransaction::new();
876        tx.custom_fees(custom_fees.clone());
877
878        assert_eq!(tx.get_custom_fees(), Some(&custom_fees));
879    }
880
881    #[test]
882    fn add_custom_fee_to_list() {
883        let custom_fees = vec![
884            CustomFixedFee::new(1, Some(TokenId::new(0, 0, 0)), None),
885            CustomFixedFee::new(2, Some(TokenId::new(0, 0, 1)), None),
886            CustomFixedFee::new(3, Some(TokenId::new(0, 0, 2)), None),
887        ];
888
889        let custom_fee_to_add = CustomFixedFee::new(4, Some(TokenId::new(0, 0, 3)), None);
890
891        let mut tx = TopicUpdateTransaction::new();
892        tx.custom_fees(custom_fees);
893        tx.add_custom_fee(custom_fee_to_add.clone());
894
895        assert_eq!(tx.get_custom_fees(), Some(&vec![custom_fee_to_add]));
896    }
897
898    #[test]
899    fn add_custom_fee_to_empty_list() {
900        let custom_fee_to_add = CustomFixedFee::new(4, Some(TokenId::new(0, 0, 3)), None);
901
902        let mut tx = TopicUpdateTransaction::new();
903        tx.add_custom_fee(custom_fee_to_add.clone());
904
905        assert_eq!(tx.get_custom_fees(), Some(&vec![custom_fee_to_add]));
906    }
907
908    #[test]
909    fn clear_custom_fees() {
910        let custom_fees = vec![
911            CustomFixedFee::new(1, Some(TokenId::new(0, 0, 0)), None),
912            CustomFixedFee::new(2, Some(TokenId::new(0, 0, 1)), None),
913            CustomFixedFee::new(3, Some(TokenId::new(0, 0, 2)), None),
914        ];
915
916        let mut tx = TopicUpdateTransaction::new();
917        tx.custom_fees(custom_fees);
918        tx.clear_custom_fees();
919
920        assert_eq!(tx.get_custom_fees(), Some(&vec![]));
921    }
922}