hiero-sdk-python 0.0.2.dev3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hedera_sdk_python/__init__.py +93 -0
- hedera_sdk_python/account/__init__.py +0 -0
- hedera_sdk_python/account/account_balance.py +44 -0
- hedera_sdk_python/account/account_create_transaction.py +173 -0
- hedera_sdk_python/account/account_id.py +62 -0
- hedera_sdk_python/client/__init__.py +0 -0
- hedera_sdk_python/client/client.py +139 -0
- hedera_sdk_python/client/network.py +143 -0
- hedera_sdk_python/consensus/__init__.py +0 -0
- hedera_sdk_python/consensus/topic_create_transaction.py +83 -0
- hedera_sdk_python/consensus/topic_delete_transaction.py +67 -0
- hedera_sdk_python/consensus/topic_id.py +44 -0
- hedera_sdk_python/consensus/topic_info.py +91 -0
- hedera_sdk_python/consensus/topic_message.py +61 -0
- hedera_sdk_python/consensus/topic_message_submit_transaction.py +87 -0
- hedera_sdk_python/consensus/topic_update_transaction.py +173 -0
- hedera_sdk_python/crypto/__init__.py +0 -0
- hedera_sdk_python/crypto/private_key.py +196 -0
- hedera_sdk_python/crypto/public_key.py +162 -0
- hedera_sdk_python/hbar.py +33 -0
- hedera_sdk_python/query/__init__.py +0 -0
- hedera_sdk_python/query/account_balance_query.py +100 -0
- hedera_sdk_python/query/query.py +138 -0
- hedera_sdk_python/query/topic_info_query.py +105 -0
- hedera_sdk_python/query/topic_message_query.py +105 -0
- hedera_sdk_python/query/transaction_get_receipt_query.py +128 -0
- hedera_sdk_python/response_code.py +587 -0
- hedera_sdk_python/timestamp.py +166 -0
- hedera_sdk_python/tokens/__init__.py +0 -0
- hedera_sdk_python/tokens/token_associate_transaction.py +85 -0
- hedera_sdk_python/tokens/token_create_transaction.py +144 -0
- hedera_sdk_python/tokens/token_delete_transaction.py +84 -0
- hedera_sdk_python/tokens/token_dissociate_transaction.py +81 -0
- hedera_sdk_python/tokens/token_id.py +44 -0
- hedera_sdk_python/tokens/token_mint_transaction.py +143 -0
- hedera_sdk_python/transaction/__init__.py +0 -0
- hedera_sdk_python/transaction/query_payment.py +32 -0
- hedera_sdk_python/transaction/transaction.py +267 -0
- hedera_sdk_python/transaction/transaction_id.py +140 -0
- hedera_sdk_python/transaction/transaction_receipt.py +78 -0
- hedera_sdk_python/transaction/transfer_transaction.py +119 -0
- hedera_sdk_python/utils/key_format.py +22 -0
- hiero_sdk_python-0.0.2.dev3.dist-info/METADATA +822 -0
- hiero_sdk_python-0.0.2.dev3.dist-info/RECORD +47 -0
- hiero_sdk_python-0.0.2.dev3.dist-info/WHEEL +4 -0
- hiero_sdk_python-0.0.2.dev3.dist-info/entry_points.txt +4 -0
- hiero_sdk_python-0.0.2.dev3.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
from hiero-sdk-python.query.query import Query
|
|
2
|
+
from hiero-sdk-python.hapi.services import query_pb2, consensus_get_topic_info_pb2
|
|
3
|
+
from hiero-sdk-python.consensus.topic_id import TopicId
|
|
4
|
+
from hiero-sdk-python.consensus.topic_info import TopicInfo
|
|
5
|
+
|
|
6
|
+
class TopicInfoQuery(Query):
|
|
7
|
+
"""
|
|
8
|
+
A query to retrieve information about a specific Hedera topic.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, topic_id=None):
|
|
12
|
+
"""
|
|
13
|
+
Initializes a new TopicInfoQuery instance with an optional topic_id.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
topic_id (TopicId, optional): The ID of the topic to query.
|
|
17
|
+
"""
|
|
18
|
+
super().__init__()
|
|
19
|
+
self.topic_id = topic_id
|
|
20
|
+
self._frozen = False
|
|
21
|
+
|
|
22
|
+
def _require_not_frozen(self):
|
|
23
|
+
"""
|
|
24
|
+
Ensures the query is not frozen before making changes.
|
|
25
|
+
"""
|
|
26
|
+
if self._frozen:
|
|
27
|
+
raise ValueError("This query is frozen and cannot be modified.")
|
|
28
|
+
|
|
29
|
+
def set_topic_id(self, topic_id: TopicId):
|
|
30
|
+
"""
|
|
31
|
+
Sets the ID of the topic to query.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
topic_id (TopicId): The ID of the topic.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
TopicInfoQuery: Returns self for method chaining.
|
|
38
|
+
"""
|
|
39
|
+
self._require_not_frozen()
|
|
40
|
+
self.topic_id = topic_id
|
|
41
|
+
return self
|
|
42
|
+
|
|
43
|
+
def freeze(self):
|
|
44
|
+
"""
|
|
45
|
+
Marks the query as frozen, preventing further modification.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
TopicInfoQuery: Returns self for chaining.
|
|
49
|
+
"""
|
|
50
|
+
self._frozen = True
|
|
51
|
+
return self
|
|
52
|
+
|
|
53
|
+
def _make_request(self):
|
|
54
|
+
"""
|
|
55
|
+
Constructs the protobuf request for the query.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Query: The protobuf query message.
|
|
59
|
+
|
|
60
|
+
Raises:
|
|
61
|
+
ValueError: If the topic ID is not set.
|
|
62
|
+
"""
|
|
63
|
+
if not self.topic_id:
|
|
64
|
+
raise ValueError("Topic ID must be set before making the request.")
|
|
65
|
+
|
|
66
|
+
query_header = self._make_request_header()
|
|
67
|
+
|
|
68
|
+
topic_info_query = consensus_get_topic_info_pb2.ConsensusGetTopicInfoQuery()
|
|
69
|
+
topic_info_query.header.CopyFrom(query_header)
|
|
70
|
+
topic_info_query.topicID.CopyFrom(self.topic_id.to_proto())
|
|
71
|
+
|
|
72
|
+
query = query_pb2.Query()
|
|
73
|
+
query.consensusGetTopicInfo.CopyFrom(topic_info_query)
|
|
74
|
+
return query
|
|
75
|
+
|
|
76
|
+
def _get_status_from_response(self, response):
|
|
77
|
+
"""
|
|
78
|
+
Extracts the status from the query response.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
response: The response protobuf message.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
ResponseCode: The status code from the response.
|
|
85
|
+
"""
|
|
86
|
+
return response.consensusGetTopicInfo.header.nodeTransactionPrecheckCode
|
|
87
|
+
|
|
88
|
+
def _map_response(self, response):
|
|
89
|
+
"""
|
|
90
|
+
Maps the protobuf response to a TopicInfo instance.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
response: The response protobuf message.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
TopicInfo: The topic info.
|
|
97
|
+
|
|
98
|
+
Raises:
|
|
99
|
+
Exception: If no topicInfo is returned in the response.
|
|
100
|
+
"""
|
|
101
|
+
if not response.consensusGetTopicInfo.topicInfo:
|
|
102
|
+
raise Exception("No topicInfo returned in the response.")
|
|
103
|
+
|
|
104
|
+
proto_topic_info = response.consensusGetTopicInfo.topicInfo
|
|
105
|
+
return TopicInfo.from_proto(proto_topic_info)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Optional, Callable, Union
|
|
3
|
+
import threading
|
|
4
|
+
from hiero-sdk-python.consensus.topic_message import TopicMessage
|
|
5
|
+
from hiero-sdk-python.hapi.mirror import consensus_service_pb2 as mirror_proto
|
|
6
|
+
from hiero-sdk-python.hapi.services import basic_types_pb2, timestamp_pb2
|
|
7
|
+
from hiero-sdk-python.consensus.topic_id import TopicId
|
|
8
|
+
|
|
9
|
+
class TopicMessageQuery:
|
|
10
|
+
"""
|
|
11
|
+
A query to subscribe to messages from a specific HCS topic, via a mirror node.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
topic_id: Optional[Union[str, TopicId]] = None,
|
|
17
|
+
start_time: Optional[datetime] = None,
|
|
18
|
+
end_time: Optional[datetime] = None,
|
|
19
|
+
limit: Optional[int] = None,
|
|
20
|
+
chunking_enabled: bool = False,
|
|
21
|
+
):
|
|
22
|
+
"""
|
|
23
|
+
Initializes a new TopicMessageQuery instance.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
topic_id (str or TopicId, optional): The ID of the topic to subscribe to.
|
|
27
|
+
start_time (datetime, optional): Start time for the subscription.
|
|
28
|
+
end_time (datetime, optional): End time for the subscription.
|
|
29
|
+
limit (int, optional): Maximum number of messages to retrieve.
|
|
30
|
+
chunking_enabled (bool, optional): Whether to enable chunking.
|
|
31
|
+
"""
|
|
32
|
+
self._topic_id = self._parse_topic_id(topic_id) if topic_id else None
|
|
33
|
+
self._start_time = self._parse_timestamp(start_time) if start_time else None
|
|
34
|
+
self._end_time = self._parse_timestamp(end_time) if end_time else None
|
|
35
|
+
self._limit = limit
|
|
36
|
+
self._chunking_enabled = chunking_enabled
|
|
37
|
+
|
|
38
|
+
def _parse_topic_id(self, topic_id: Union[str, TopicId]):
|
|
39
|
+
if isinstance(topic_id, str):
|
|
40
|
+
parts = topic_id.strip().split(".")
|
|
41
|
+
if len(parts) != 3:
|
|
42
|
+
raise ValueError(f"Invalid topic ID string: {topic_id}")
|
|
43
|
+
shard, realm, topic = map(int, parts)
|
|
44
|
+
return basic_types_pb2.TopicID(shardNum=shard, realmNum=realm, topicNum=topic)
|
|
45
|
+
elif isinstance(topic_id, TopicId):
|
|
46
|
+
return topic_id.to_proto()
|
|
47
|
+
else:
|
|
48
|
+
raise TypeError("Invalid topic_id format. Must be a string or TopicId.")
|
|
49
|
+
|
|
50
|
+
def _parse_timestamp(self, dt: datetime):
|
|
51
|
+
seconds = int(dt.timestamp())
|
|
52
|
+
nanos = int((dt.timestamp() - seconds) * 1e9)
|
|
53
|
+
return timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos)
|
|
54
|
+
|
|
55
|
+
def set_topic_id(self, topic_id: Union[str, TopicId]):
|
|
56
|
+
self._topic_id = self._parse_topic_id(topic_id)
|
|
57
|
+
return self
|
|
58
|
+
|
|
59
|
+
def set_start_time(self, dt: datetime):
|
|
60
|
+
self._start_time = self._parse_timestamp(dt)
|
|
61
|
+
return self
|
|
62
|
+
|
|
63
|
+
def set_end_time(self, dt: datetime):
|
|
64
|
+
self._end_time = self._parse_timestamp(dt)
|
|
65
|
+
return self
|
|
66
|
+
|
|
67
|
+
def set_limit(self, limit: int):
|
|
68
|
+
self._limit = limit
|
|
69
|
+
return self
|
|
70
|
+
|
|
71
|
+
def set_chunking_enabled(self, enabled: bool):
|
|
72
|
+
self._chunking_enabled = enabled
|
|
73
|
+
return self
|
|
74
|
+
|
|
75
|
+
def subscribe(
|
|
76
|
+
self,
|
|
77
|
+
client,
|
|
78
|
+
on_message: Callable[[TopicMessage], None],
|
|
79
|
+
on_error: Optional[Callable[[Exception], None]] = None,
|
|
80
|
+
):
|
|
81
|
+
if not self._topic_id:
|
|
82
|
+
raise ValueError("Topic ID must be set before subscribing.")
|
|
83
|
+
if not client.mirror_stub:
|
|
84
|
+
raise ValueError("Client has no mirror_stub. Did you configure a mirror node address?")
|
|
85
|
+
|
|
86
|
+
request = mirror_proto.ConsensusTopicQuery(topicID=self._topic_id)
|
|
87
|
+
if self._start_time:
|
|
88
|
+
request.consensusStartTime.CopyFrom(self._start_time)
|
|
89
|
+
if self._end_time:
|
|
90
|
+
request.consensusEndTime.CopyFrom(self._end_time)
|
|
91
|
+
if self._limit is not None:
|
|
92
|
+
request.limit = self._limit
|
|
93
|
+
|
|
94
|
+
def run_stream():
|
|
95
|
+
try:
|
|
96
|
+
message_stream = client.mirror_stub.subscribeTopic(request)
|
|
97
|
+
for response in message_stream:
|
|
98
|
+
msg_obj = TopicMessage.from_proto(response)
|
|
99
|
+
on_message(msg_obj)
|
|
100
|
+
except Exception as e:
|
|
101
|
+
if on_error:
|
|
102
|
+
on_error(e)
|
|
103
|
+
|
|
104
|
+
thread = threading.Thread(target=run_stream, daemon=True)
|
|
105
|
+
thread.start()
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
from hiero-sdk-python.query.query import Query
|
|
2
|
+
from hiero-sdk-python.hapi.services import transaction_get_receipt_pb2, query_pb2, query_header_pb2
|
|
3
|
+
from hiero-sdk-python.response_code import ResponseCode
|
|
4
|
+
from hiero-sdk-python.transaction.transaction_id import TransactionId
|
|
5
|
+
from hiero-sdk-python.transaction.transaction_receipt import TransactionReceipt
|
|
6
|
+
import traceback
|
|
7
|
+
|
|
8
|
+
class TransactionGetReceiptQuery(Query):
|
|
9
|
+
"""
|
|
10
|
+
A query to retrieve the receipt of a specific transaction from the Hedera network.
|
|
11
|
+
|
|
12
|
+
This class constructs and executes a query to obtain the receipt of a transaction,
|
|
13
|
+
which includes the transaction's status and other pertinent information.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, transaction_id=None):
|
|
17
|
+
"""
|
|
18
|
+
Initializes a new instance of the TransactionGetReceiptQuery class.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
transaction_id (TransactionId, optional): The ID of the transaction.
|
|
22
|
+
"""
|
|
23
|
+
super().__init__()
|
|
24
|
+
self.transaction_id = transaction_id
|
|
25
|
+
self._frozen = False
|
|
26
|
+
|
|
27
|
+
def _require_not_frozen(self):
|
|
28
|
+
"""
|
|
29
|
+
Ensures the query is not frozen before making changes.
|
|
30
|
+
"""
|
|
31
|
+
if self._frozen:
|
|
32
|
+
raise ValueError("This query is frozen and cannot be modified.")
|
|
33
|
+
|
|
34
|
+
def set_transaction_id(self, transaction_id: TransactionId):
|
|
35
|
+
"""
|
|
36
|
+
Sets the transaction ID for which to retrieve the receipt.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
transaction_id (TransactionId): The ID of the transaction.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
TransactionGetReceiptQuery: The current instance for method chaining.
|
|
43
|
+
"""
|
|
44
|
+
self._require_not_frozen()
|
|
45
|
+
self.transaction_id = transaction_id
|
|
46
|
+
return self
|
|
47
|
+
|
|
48
|
+
def freeze(self):
|
|
49
|
+
"""
|
|
50
|
+
Marks the query as frozen, preventing further modification.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
TransactionGetReceiptQuery: The current instance for method chaining.
|
|
54
|
+
"""
|
|
55
|
+
self._frozen = True
|
|
56
|
+
return self
|
|
57
|
+
|
|
58
|
+
def _is_payment_required(self):
|
|
59
|
+
"""
|
|
60
|
+
Override the default in the base Query class:
|
|
61
|
+
This particular query does NOT require a payment.
|
|
62
|
+
"""
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
def _make_request(self):
|
|
66
|
+
"""
|
|
67
|
+
Constructs the protobuf request for the transaction receipt query.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Query: The protobuf Query object containing the transaction receipt query.
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
ValueError: If the transaction ID is not set.
|
|
74
|
+
Exception: If an error occurs during request construction.
|
|
75
|
+
"""
|
|
76
|
+
try:
|
|
77
|
+
if not self.transaction_id:
|
|
78
|
+
raise ValueError("Transaction ID must be set before making the request.")
|
|
79
|
+
|
|
80
|
+
query_header = query_header_pb2.QueryHeader()
|
|
81
|
+
query_header.responseType = query_header_pb2.ResponseType.ANSWER_ONLY
|
|
82
|
+
|
|
83
|
+
transaction_get_receipt = transaction_get_receipt_pb2.TransactionGetReceiptQuery()
|
|
84
|
+
transaction_get_receipt.header.CopyFrom(query_header)
|
|
85
|
+
transaction_get_receipt.transactionID.CopyFrom(self.transaction_id.to_proto())
|
|
86
|
+
|
|
87
|
+
query = query_pb2.Query()
|
|
88
|
+
if not hasattr(query, 'transactionGetReceipt'):
|
|
89
|
+
raise AttributeError("Query object has no attribute 'transactionGetReceipt'")
|
|
90
|
+
query.transactionGetReceipt.CopyFrom(transaction_get_receipt)
|
|
91
|
+
|
|
92
|
+
return query
|
|
93
|
+
except Exception as e:
|
|
94
|
+
print(f"Exception in _make_request: {e}")
|
|
95
|
+
traceback.print_exc()
|
|
96
|
+
raise
|
|
97
|
+
|
|
98
|
+
def _get_status_from_response(self, response):
|
|
99
|
+
"""
|
|
100
|
+
Extracts the status code from the response header.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
response (Response): The response received from the network.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
int: The status code indicating the result of the query.
|
|
107
|
+
"""
|
|
108
|
+
header = response.transactionGetReceipt.header
|
|
109
|
+
return header.nodeTransactionPrecheckCode
|
|
110
|
+
|
|
111
|
+
def _map_response(self, response):
|
|
112
|
+
"""
|
|
113
|
+
Maps the response to a TransactionReceipt object.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
response (Response): The response received from the network.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
TransactionReceipt: The transaction receipt extracted from the response.
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
Exception: If the transaction receipt is not found in the response.
|
|
123
|
+
"""
|
|
124
|
+
if response.transactionGetReceipt and response.transactionGetReceipt.receipt:
|
|
125
|
+
receipt_proto = response.transactionGetReceipt.receipt
|
|
126
|
+
return TransactionReceipt.from_proto(receipt_proto)
|
|
127
|
+
else:
|
|
128
|
+
raise Exception("Transaction receipt not found in the response.")
|