1- """
2- This module provides the `TopicInfo` class for representing consensus topic
3- metadata on the Hedera network using the Hiero SDK.
4-
5- It handles constructing the object from a protobuf message, formatting
6- optional fields, and providing a readable string representation of the
7- topic state.
8- """
9- from datetime import datetime
10- from typing import List , Optional
11-
12- from hiero_sdk_python .crypto .public_key import PublicKey
13- from hiero_sdk_python .hapi .services .basic_types_pb2 import Key , AccountID
14- from hiero_sdk_python .hapi .services .timestamp_pb2 import Timestamp
15- from hiero_sdk_python .hapi .services import consensus_topic_info_pb2
16- from hiero_sdk_python .Duration import Duration
17- from hiero_sdk_python .tokens .custom_fixed_fee import CustomFixedFee
18- from hiero_sdk_python .utils .key_format import format_key
19-
1+ from hedera_sdk_python .hapi .basic_types_pb2 import Key , AccountID
2+ from hedera_sdk_python .hapi .timestamp_pb2 import Timestamp
3+ from hedera_sdk_python .hapi .duration_pb2 import Duration
204
215class TopicInfo :
226 """
23- Represents consensus topic information on the Hedera network.
24-
25- It wraps the `ConsensusTopicInfo` protobuf message, exposing attributes
26- such as memo, running hash, sequence number, expiration time, admin key,
27- submit key, auto-renewal configuration, and ledger ID.
7+ Represents the information retrieved from ConsensusService.getTopicInfo() about a topic.
288 """
299
3010 def __init__ (
31- self ,
32- memo : str ,
33- running_hash : bytes ,
34- sequence_number : int ,
35- expiration_time : Optional [Timestamp ],
36- admin_key : Optional [Key ],
37- submit_key : Optional [Key ],
38- auto_renew_period : Optional [Duration ],
39- auto_renew_account : Optional [AccountID ],
40- ledger_id : Optional [bytes ],
41- fee_schedule_key : Optional [PublicKey ],
42- fee_exempt_keys : Optional [List [PublicKey ]],
43- custom_fees : Optional [List [CustomFixedFee ]],
44- ) -> None :
45- """
46- Initializes a new instance of the TopicInfo class.
47- Args:
48- memo (str): The memo associated with the topic.
49- running_hash (bytes): The current running hash of the topic.
50- sequence_number (int): The sequence number of the topic.
51- expiration_time (Optional[Timestamp]): The expiration time of the topic.
52- admin_key (Optional[Key]): The admin key for the topic.
53- submit_key (Optional[Key]): The submit key for the topic.
54- auto_renew_period (Optional[Duration]): The auto-renew period for the topic.
55- auto_renew_account (Optional[AccountID]): The account ID for auto-renewal.
56- ledger_id (Optional[bytes]): The ledger ID associated with the topic.
57- fee_schedule_key (PublicKey): The fee schedule key for the topic.
58- fee_exempt_keys (List[PublicKey]): The fee exempt keys for the topic.
59- custom_fees (List[CustomFixedFee]): The custom fees for the topic.
60- """
61- self .memo : str = memo
62- self .running_hash : bytes = running_hash
63- self .sequence_number : int = sequence_number
64- self .expiration_time : Optional [Timestamp ] = expiration_time
65- self .admin_key : Optional [Key ] = admin_key
66- self .submit_key : Optional [Key ] = submit_key
67- self .auto_renew_period : Optional [Duration ] = auto_renew_period
68- self .auto_renew_account : Optional [AccountID ] = auto_renew_account
69- self .ledger_id : Optional [bytes ] = ledger_id
70- self .fee_schedule_key : PublicKey = fee_schedule_key
71- self .fee_exempt_keys : List [PublicKey ] = (
72- list (fee_exempt_keys ) if fee_exempt_keys is not None else []
73- )
74- self .custom_fees : List [CustomFixedFee ] = (
75- list (custom_fees ) if custom_fees is not None else []
76- )
11+ self ,
12+ memo : str ,
13+ running_hash : bytes ,
14+ sequence_number : int ,
15+ expiration_time : Timestamp ,
16+ admin_key : Key ,
17+ submit_key : Key ,
18+ auto_renew_period : Duration ,
19+ auto_renew_account : AccountID ,
20+ ledger_id : bytes ,
21+ ):
22+ self .memo = memo
23+ self .running_hash = running_hash
24+ self .sequence_number = sequence_number
25+ self .expiration_time = expiration_time
26+ self .admin_key = admin_key
27+ self .submit_key = submit_key
28+ self .auto_renew_period = auto_renew_period
29+ self .auto_renew_account = auto_renew_account
30+ self .ledger_id = ledger_id
7731
7832 @classmethod
79- def _from_proto (
80- cls ,
81- topic_info_proto : consensus_topic_info_pb2 .ConsensusTopicInfo
82- ) -> "TopicInfo" :
33+ def from_proto (cls , topic_info_proto ):
8334 """
8435 Constructs a TopicInfo object from a protobuf ConsensusTopicInfo message.
8536
8637 Args:
87- topic_info_proto (ConsensusTopicInfo): The protobuf message.
38+ topic_info_proto (ConsensusTopicInfo): The protobuf message with topic info .
8839
8940 Returns:
90- TopicInfo: The constructed TopicInfo object .
41+ TopicInfo: A new instance populated from the protobuf message .
9142 """
9243 return cls (
9344 memo = topic_info_proto .memo ,
9445 running_hash = topic_info_proto .runningHash ,
9546 sequence_number = topic_info_proto .sequenceNumber ,
96- expiration_time = (
97- topic_info_proto .expirationTime
98- if topic_info_proto .HasField ("expirationTime" ) else None
99- ),
100- admin_key = (
101- topic_info_proto .adminKey
102- if topic_info_proto .HasField ("adminKey" ) else None
103- ),
104- submit_key = (
105- topic_info_proto .submitKey
106- if topic_info_proto .HasField ("submitKey" ) else None
107- ),
108- auto_renew_period = (
109- Duration ._from_proto (proto = topic_info_proto .autoRenewPeriod )
110- if topic_info_proto .HasField ("autoRenewPeriod" ) else None
111- ),
112- auto_renew_account = (
113- topic_info_proto .autoRenewAccount
114- if topic_info_proto .HasField ("autoRenewAccount" ) else None
115- ),
116- ledger_id = getattr (topic_info_proto , "ledger_id" , None ),
117- fee_schedule_key = (
118- PublicKey ._from_proto (topic_info_proto .fee_schedule_key )
119- if topic_info_proto .HasField ("fee_schedule_key" ) else None
120- ),
121- fee_exempt_keys = [PublicKey ._from_proto (key ) for key in topic_info_proto .fee_exempt_key_list ],
122- custom_fees = [CustomFixedFee ._from_proto (fee ) for fee in topic_info_proto .custom_fees ],
47+ expiration_time = topic_info_proto .expirationTime ,
48+ admin_key = topic_info_proto .adminKey if topic_info_proto .HasField ("adminKey" ) else None ,
49+ submit_key = topic_info_proto .submitKey if topic_info_proto .HasField ("submitKey" ) else None ,
50+ auto_renew_period = topic_info_proto .autoRenewPeriod
51+ if topic_info_proto .HasField ("autoRenewPeriod" )
52+ else None ,
53+ auto_renew_account = topic_info_proto .autoRenewAccount
54+ if topic_info_proto .HasField ("autoRenewAccount" )
55+ else None ,
56+ ledger_id = topic_info_proto .ledger_id ,
12357 )
12458
125- def __repr__ (self ) -> str :
126- """
127- If you print the object with `repr(topic_info)`, you'll see this output.
128-
129- Returns:
130- str: The string representation.
131- """
132- return self .__str__ ()
133-
134- def __str__ (self ) -> str :
135- """
136- Pretty-print the TopicInfo in a multi-line, user-friendly style.
137-
138- Returns:
139- str: A nicely formatted string representation of the topic.
140- """
141- exp_dt : Optional [datetime ] = None
142- if self .expiration_time and hasattr (self .expiration_time , "seconds" ):
143- exp_dt = datetime .fromtimestamp (self .expiration_time .seconds )
144-
145- running_hash_str : Optional [str ] = f"0x{ self .running_hash .hex ()} " if self .running_hash else "None"
146-
147- # shows 0x{hex} when present, or "None" as a string when absent (previously could be 0xNone)
148- ledger_id_hex : Optional [str ] = None
149- if self .ledger_id and isinstance (self .ledger_id , (bytes , bytearray )):
150- ledger_id_hex = self .ledger_id .hex ()
151- ledger_id_str = f"0x{ ledger_id_hex } " if ledger_id_hex else "None"
152-
153- # extracts and displays just the seconds value (e.g., 7776000) from Duration
154- auto_renew_seconds = (
155- self .auto_renew_period .seconds if self .auto_renew_period else None
156- )
157-
158- if self .auto_renew_account is None :
159- auto_renew_account_str = "None"
160- elif hasattr (self .auto_renew_account , "shardNum" ):
161- # Protobuf AccountID -displays AccountId(shard=X, realm=Y, account=Z) format
162- auto_renew_account_str = (
163- f"AccountId(shard={ self .auto_renew_account .shardNum } , "
164- f"realm={ self .auto_renew_account .realmNum } , "
165- f"account={ self .auto_renew_account .accountNum } )"
166- )
167- else :
168- auto_renew_account_str = str (self .auto_renew_account )
169-
170- fee_exempt_keys_formatted = [format_key (key ) for key in self .fee_exempt_keys ]
171-
59+ def __repr__ (self ):
17260 return (
173- "TopicInfo(\n "
174- f" memo='{ self .memo } ',\n "
175- f" running_hash={ running_hash_str } ,\n "
176- f" sequence_number={ self .sequence_number } ,\n "
177- f" expiration_time={ exp_dt } ,\n "
178- f" admin_key={ format_key (self .admin_key )} ,\n "
179- f" submit_key={ format_key (self .submit_key )} ,\n "
180- f" auto_renew_period={ auto_renew_seconds } ,\n "
181- f" auto_renew_account={ auto_renew_account_str } ,\n "
182- f" ledger_id={ ledger_id_str } ,\n "
183- f" fee_schedule_key={ format_key (self .fee_schedule_key )} ,\n "
184- f" fee_exempt_keys={ fee_exempt_keys_formatted } ,\n "
185- f" custom_fees={ self .custom_fees } ,\n "
186- ")"
187- )
61+ f"TopicInfo(memo={ self .memo !r} , running_hash={ self .running_hash !r} , "
62+ f"sequence_number={ self .sequence_number } , expiration_time={ self .expiration_time } , "
63+ f"admin_key={ self .admin_key } , submit_key={ self .submit_key } , "
64+ f"auto_renew_period={ self .auto_renew_period } , auto_renew_account={ self .auto_renew_account } , "
65+ f"ledger_id={ self .ledger_id !r} )"
66+ )
0 commit comments