Skip to content

Commit abe06fe

Browse files
committed
feat: typing for transaction module
Signed-off-by: exploreriii <133720349+exploreriii@users.noreply.github.com>
1 parent 4fa807f commit abe06fe

File tree

7 files changed

+150
-74
lines changed

7 files changed

+150
-74
lines changed

src/hiero_sdk_python/transaction/query_payment.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
from hiero_sdk_python.consensus.topic_id import TopicId
21
from hiero_sdk_python.account.account_id import AccountId
3-
from hiero_sdk_python.tokens.token_id import TokenId
2+
from hiero_sdk_python.crypto.private_key import PrivateKey
43
from hiero_sdk_python.hbar import Hbar
54
from hiero_sdk_python.transaction.transfer_transaction import TransferTransaction
65
from hiero_sdk_python.transaction.transaction_id import TransactionId
6+
from hiero_sdk_python.hapi.services import transaction_body_pb2
77

88
def build_query_payment_transaction(
99
payer_account_id: AccountId,
10-
payer_private_key,
10+
payer_private_key: PrivateKey,
1111
node_account_id: AccountId,
1212
amount: Hbar
13-
):
13+
) -> transaction_body_pb2.TransactionBody:
1414
"""
1515
Build and sign a TransferTransaction that sends `amount` of HBAR from
1616
`payer_account_id` to `node_account_id`. Returns a Transaction proto

src/hiero_sdk_python/transaction/transaction.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Transaction(_Executable):
2222
2. _get_method(channel) - Return the appropriate gRPC method to call
2323
"""
2424

25-
def __init__(self):
25+
def __init__(self) -> None:
2626
"""
2727
Initializes a new Transaction instance with default values.
2828
"""
@@ -60,7 +60,11 @@ def _make_request(self):
6060
"""
6161
return self._to_proto()
6262

63-
def _map_response(self, response, node_id, proto_request):
63+
def _map_response(
64+
self,
65+
response,
66+
node_id,
67+
proto_request):
6468
"""
6569
Implements the Executable._map_response method to create a TransactionResponse.
6670
@@ -386,4 +390,4 @@ def set_transaction_memo(self, memo):
386390
"""
387391
self._require_not_frozen()
388392
self.memo = memo
389-
return self
393+
return self

src/hiero_sdk_python/transaction/transaction_id.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import secrets
2+
13
import time
4+
from typing import Any, Optional
25
from hiero_sdk_python.hapi.services import basic_types_pb2, timestamp_pb2
36
from hiero_sdk_python.account.account_id import AccountId
4-
import random
57

68
class TransactionId:
79
"""
@@ -15,19 +17,23 @@ class TransactionId:
1517
valid_start (Timestamp): The valid start time of the transaction.
1618
"""
1719

18-
def __init__(self, account_id: AccountId = None, valid_start: timestamp_pb2.Timestamp = None):
20+
def __init__(
21+
self,
22+
account_id: Optional[AccountId] = None,
23+
valid_start: Optional[timestamp_pb2.Timestamp] = None
24+
) -> None:
1925
"""
2026
Initializes a TransactionId with the given account ID and valid start timestamp.
2127
2228
Args:
23-
account_id (AccountId): The account ID initiating the transaction.
24-
valid_start (Timestamp): The valid start time of the transaction.
29+
account_id (AccountId, optional): The account ID initiating the transaction.
30+
valid_start (timestamp_pb2.Timestamp, optional): The valid start time of the transaction.
2531
"""
26-
self.account_id = account_id
27-
self.valid_start = valid_start
32+
self.account_id: Optional[AccountId] = account_id
33+
self.valid_start: Optional[timestamp_pb2.Timestamp] = valid_start
2834

2935
@classmethod
30-
def generate(cls, account_id: AccountId):
36+
def generate(cls, account_id: AccountId) -> "TransactionId":
3137
"""
3238
Generates a new TransactionId using the current time as the valid start,
3339
subtracting a random number of seconds to adjust for potential network delays.
@@ -38,15 +44,15 @@ def generate(cls, account_id: AccountId):
3844
Returns:
3945
TransactionId: A new TransactionId instance.
4046
"""
41-
cut_off_seconds = random.randint(5, 8) # subtract random number of seconds between 5 and 8
42-
adjusted_time = time.time() - cut_off_seconds
43-
seconds = int(adjusted_time)
44-
nanos = int((adjusted_time - seconds) * 1e9)
47+
cut_off_seconds = secrets.choice([5, 6, 7, 8])
48+
adjusted_time: float = time.time() - cut_off_seconds
49+
seconds: int = int(adjusted_time)
50+
nanos: int = int((adjusted_time - seconds) * 1e9)
4551
valid_start = timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos)
4652
return cls(account_id, valid_start)
4753

4854
@classmethod
49-
def from_string(cls, transaction_id_str: str):
55+
def from_string(cls, transaction_id_str: str) -> "TransactionId":
5056
"""
5157
Parses a TransactionId from a string in the format 'account_id@seconds.nanos'.
5258
@@ -60,6 +66,8 @@ def from_string(cls, transaction_id_str: str):
6066
ValueError: If the input string is not in the correct format.
6167
"""
6268
try:
69+
account_id_str: Optional[str] = None
70+
timestamp_str: Optional[str] = None
6371
account_id_str, timestamp_str = transaction_id_str.split('@')
6472
account_id = AccountId.from_string(account_id_str)
6573
seconds_str, nanos_str = timestamp_str.split('.')
@@ -92,7 +100,7 @@ def _to_proto(self) -> basic_types_pb2.TransactionID:
92100
return transaction_id_proto
93101

94102
@classmethod
95-
def _from_proto(cls, transaction_id_proto: basic_types_pb2.TransactionID):
103+
def _from_proto(cls, transaction_id_proto: basic_types_pb2.TransactionID) -> "TransactionId":
96104
"""
97105
Creates a TransactionId instance from a protobuf TransactionID object.
98106
@@ -106,7 +114,7 @@ def _from_proto(cls, transaction_id_proto: basic_types_pb2.TransactionID):
106114
valid_start = transaction_id_proto.transactionValidStart
107115
return cls(account_id, valid_start)
108116

109-
def __eq__(self, other):
117+
def __eq__(self, other: Any) -> bool:
110118
"""
111119
Checks if this TransactionId is equal to another.
112120
@@ -123,7 +131,7 @@ def __eq__(self, other):
123131
self.valid_start.nanos == other.valid_start.nanos
124132
)
125133

126-
def __hash__(self):
134+
def __hash__(self) -> int:
127135
"""
128136
Returns the hash of the TransactionId.
129137
@@ -132,7 +140,7 @@ def __hash__(self):
132140
"""
133141
return hash((self.account_id, self.valid_start.seconds, self.valid_start.nanos))
134142

135-
def __str__(self):
143+
def __str__(self) -> str:
136144
"""
137145
Returns the string representation of the TransactionId.
138146
Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
1-
import warnings
2-
from hiero_sdk_python.contract.contract_id import ContractId
1+
"""
2+
transaction_receipt.py
3+
~~~~~~~~~~~~~~~~~~~~~~
4+
5+
Defines the TransactionReceipt class, which represents the outcome of a Hedera transaction.
6+
7+
This module provides structured access to fields in a transaction receipt,
8+
including associated IDs like TokenId, TopicId, AccountId, and FileId.
9+
It wraps the underlying protobuf object and exposes key properties with
10+
optional deprecated alias support via `_DeprecatedAliasesMixin`.
11+
12+
Classes:
13+
- TransactionReceipt: Parses and exposes fields from a transaction receipt protobuf.
14+
"""
15+
from typing import Optional, cast
316
from hiero_sdk_python.file.file_id import FileId
17+
from hiero_sdk_python.contract.contract_id import ContractId
418
from hiero_sdk_python.tokens.token_id import TokenId
519
from hiero_sdk_python.consensus.topic_id import TopicId
620
from hiero_sdk_python.account.account_id import AccountId
721
from hiero_sdk_python._deprecated import _DeprecatedAliasesMixin
22+
from hiero_sdk_python.transaction.transaction_id import TransactionId
23+
from hiero_sdk_python.hapi.services import transaction_receipt_pb2, response_code_pb2
824

9-
class TransactionReceipt(_DeprecatedAliasesMixin):
25+
class TransactionReceipt(_DeprecatedAliasesMixin): # type: ignore[misc]
1026
"""
1127
Represents the receipt of a transaction.
1228
Imports deprecated aliases for tokenId, topicId and accountId.
@@ -17,21 +33,27 @@ class TransactionReceipt(_DeprecatedAliasesMixin):
1733
Attributes:
1834
status (ResponseCode): The status code of the transaction.
1935
_receipt_proto (TransactionReceiptProto): The underlying protobuf receipt.
36+
_transaction_id (TransactionId): The transaction ID associated with this receipt.
2037
"""
2138

22-
def __init__(self, receipt_proto, transaction_id=None):
39+
def __init__(
40+
self,
41+
receipt_proto: transaction_receipt_pb2.TransactionReceipt,
42+
transaction_id: Optional[TransactionId] = None
43+
) -> None:
2344
"""
2445
Initializes the TransactionReceipt with the provided protobuf receipt.
2546
2647
Args:
27-
receipt_proto (TransactionReceiptProto): The protobuf transaction receipt.
48+
receipt_proto (transaction_receipt_pb2.TransactionReceiptProto, optional): The protobuf transaction receipt.
49+
transaction_id (TransactionId, optional): The transaction ID associated with this receipt.
2850
"""
29-
self._transaction_id = transaction_id
30-
self.status = receipt_proto.status
31-
self._receipt_proto = receipt_proto
51+
self._transaction_id: Optional[TransactionId] = transaction_id
52+
self.status: Optional[response_code_pb2.ResponseCodeEnum] = receipt_proto.status
53+
self._receipt_proto: transaction_receipt_pb2.TransactionReceipt = receipt_proto
3254

3355
@property
34-
def token_id(self):
56+
def token_id(self) -> Optional[TokenId]:
3557
"""
3658
Retrieves the TokenId associated with the transaction receipt, if available.
3759
@@ -40,11 +62,10 @@ def token_id(self):
4062
"""
4163
if self._receipt_proto.HasField('tokenID') and self._receipt_proto.tokenID.tokenNum != 0:
4264
return TokenId._from_proto(self._receipt_proto.tokenID)
43-
else:
44-
return None
65+
return None
4566

4667
@property
47-
def topic_id(self):
68+
def topic_id(self) -> Optional[TopicId]:
4869
"""
4970
Retrieves the TopicId associated with the transaction receipt, if available.
5071
@@ -53,44 +74,44 @@ def topic_id(self):
5374
"""
5475
if self._receipt_proto.HasField('topicID') and self._receipt_proto.topicID.topicNum != 0:
5576
return TopicId._from_proto(self._receipt_proto.topicID)
56-
else:
57-
return None
77+
return None
5878

5979
@property
60-
def account_id(self):
80+
def account_id(self) -> Optional[AccountId]:
6181
"""
6282
Retrieves the AccountId associated with the transaction receipt, if available.
6383
6484
Returns:
6585
AccountId or None: The AccountId if present; otherwise, None.
6686
"""
67-
if self._receipt_proto.HasField('accountID') and self._receipt_proto.accountID.accountNum != 0:
87+
if (
88+
self._receipt_proto.HasField('accountID')
89+
and self._receipt_proto.accountID.accountNum != 0
90+
):
6891
return AccountId._from_proto(self._receipt_proto.accountID)
69-
else:
70-
return None
92+
return None
7193

7294
@property
73-
def serial_numbers(self):
95+
def serial_numbers(self) -> list[int]:
7496
"""
7597
Retrieves the serial numbers associated with the transaction receipt, if available.
7698
7799
Returns:
78100
list of int: The serial numbers if present; otherwise, an empty list.
79101
"""
80-
return self._receipt_proto.serialNumbers
102+
return cast(list[int], self._receipt_proto.serialNumbers)
81103

82104
@property
83-
def file_id(self):
105+
def file_id(self) -> Optional[FileId]:
84106
"""
85107
Returns the file ID associated with this receipt.
86108
"""
87109
if self._receipt_proto.HasField('fileID') and self._receipt_proto.fileID.fileNum != 0:
88110
return FileId._from_proto(self._receipt_proto.fileID)
89-
else:
90-
return None
91-
111+
return None
112+
92113
@property
93-
def transaction_id(self):
114+
def transaction_id(self) -> Optional[TransactionId]:
94115
"""
95116
Returns the transaction ID associated with this receipt.
96117
@@ -117,10 +138,18 @@ def _to_proto(self):
117138
Returns the underlying protobuf transaction receipt.
118139
119140
Returns:
120-
TransactionReceiptProto: The protobuf transaction receipt.
141+
transaction_receipt_pb2.TransactionReceipt: The protobuf transaction receipt.
121142
"""
122143
return self._receipt_proto
123144

124145
@classmethod
125-
def _from_proto(cls, proto, transaction_id=None):
146+
def _from_proto(cls, proto: transaction_receipt_pb2.TransactionReceipt, transaction_id: TransactionId) -> "TransactionReceipt":
147+
"""
148+
Creates a TransactionReceipt instance from a protobuf TransactionReceipt object.
149+
Args:
150+
proto (transaction_receipt_pb2.TransactionReceipt): The protobuf TransactionReceipt object.
151+
transaction_id (TransactionId): The transaction ID associated with this receipt.
152+
Returns:
153+
TransactionReceipt: A new instance of TransactionReceipt populated with data from the protobuf object.
154+
"""
126155
return cls(receipt_proto=proto, transaction_id=transaction_id)

src/hiero_sdk_python/transaction/transaction_record.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def _from_proto(cls, proto: transaction_record_pb2.TransactionRecord, transactio
7979
transaction_hash=proto.transactionHash,
8080
transaction_memo=proto.memo,
8181
transaction_fee=proto.transactionFee,
82-
receipt=TransactionReceipt._from_proto(proto.receipt),
82+
receipt=TransactionReceipt._from_proto(proto.receipt, transaction_id),
8383
token_transfers=token_transfers,
8484
nft_transfers=nft_transfers,
8585
transfers=transfers,

src/hiero_sdk_python/transaction/transaction_response.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
1+
"""
2+
transaction_response.py
3+
~~~~~~~~~~~~~~~~~~~~~~~~
4+
5+
Represents the response from a transaction submitted to the Hedera network.
6+
Provides methods to retrieve the receipt and access core transaction details.
7+
"""
18
from hiero_sdk_python.account.account_id import AccountId
29
from hiero_sdk_python.transaction.transaction_id import TransactionId
10+
# pylint: disable=too-few-public-methods
311

412
class TransactionResponse:
513
"""
614
Represents the response from a transaction submitted to the Hedera network.
715
"""
816

9-
def __init__(self):
17+
def __init__(self) -> None:
1018
"""
1119
Initialize a new TransactionResponse instance with default values.
1220
"""
1321
self.transaction_id = TransactionId()
14-
self.node_id = AccountId()
15-
self.hash = bytes()
16-
self.validate_status = False
22+
self.node_id: AccountId = AccountId()
23+
self.hash: bytes = bytes()
24+
self.validate_status: bool = False
1725
self.transaction = None
1826

1927
def get_receipt(self, client):
@@ -30,6 +38,10 @@ def get_receipt(self, client):
3038
# TODO: Decide how to avoid circular imports
3139
from hiero_sdk_python.query.transaction_get_receipt_query import TransactionGetReceiptQuery
3240
# TODO: Implement set_node_account_ids() to get failure reason for preHandle failures
33-
receipt = TransactionGetReceiptQuery().set_transaction_id(self.transaction_id).execute(client)
34-
35-
return receipt
41+
receipt = (
42+
TransactionGetReceiptQuery()
43+
.set_transaction_id(self.transaction_id)
44+
.execute(client)
45+
)
46+
47+
return receipt

0 commit comments

Comments
 (0)