Skip to content

Commit 9c2eb67

Browse files
committed
chore: deprecated the node_account_id to use node_account_ids
Signed-off-by: Manish Dait <daitmanish88@gmail.com>
1 parent 62c368e commit 9c2eb67

8 files changed

Lines changed: 75 additions & 80 deletions

File tree

src/hiero_sdk_python/executable.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,32 @@ def __init__(self):
8686
self._grpc_deadline: float | None = None
8787
self._request_timeout: float | None = None
8888

89-
self.node_account_id: AccountId | None = None
89+
self._node_account_id: AccountId | None = None
9090
self.node_account_ids: list[AccountId] = []
9191

9292
self._used_node_account_id: AccountId | None = None
9393
self._node_account_ids_index: int = 0
94+
95+
@property
96+
def node_account_id(self) -> AccountId | None:
97+
warnings.warn(
98+
"'node_account_id' is deprecated; use 'node_account_ids' instead.",
99+
DeprecationWarning,
100+
stacklevel=2
101+
)
102+
103+
return self._node_account_id
104+
105+
@node_account_id.setter
106+
def node_account_id(self, account_id: AccountId) -> None:
107+
warnings.warn(
108+
"'node_account_id' is deprecated; use 'node_account_ids' instead.",
109+
DeprecationWarning,
110+
stacklevel=2
111+
)
112+
113+
self.node_account_ids = [account_id] if account_id is not None else []
114+
94115

95116
def set_node_account_ids(self, node_account_ids: list[AccountId]):
96117
"""
@@ -115,6 +136,12 @@ def set_node_account_id(self, node_account_id: AccountId):
115136
Returns:
116137
The current instance of the class for chaining.
117138
"""
139+
warnings.warn(
140+
"Method 'set_node_account_id()' is deprecated; use 'set_node_account_ids()' instead.",
141+
DeprecationWarning,
142+
stacklevel=2
143+
)
144+
118145
return self.set_node_account_ids([node_account_id])
119146

120147
def set_max_attempts(self, max_attempts: int):
@@ -346,9 +373,10 @@ def _resolve_execution_config(self, client: Client, timeout: int | float | None)
346373
if getattr(self, attr) is None:
347374
setattr(self, attr, default)
348375

349-
# nodes to which the executaion must be run against, if not provided used nodes from client
350376
if not self.node_account_ids:
351-
self.node_account_ids = [node._account_id for node in client.network._healthy_nodes]
377+
self.node_account_ids = [
378+
node._account_id for node in client.network.nodes
379+
]
352380

353381
if not self.node_account_ids:
354382
raise RuntimeError("No healthy nodes available for execution")
@@ -429,10 +457,10 @@ def _execute(self, client: Client, timeout: int | float | None = None):
429457
node = client.network._get_node(node_id)
430458

431459
if node is None:
432-
raise RuntimeError(f"No node found for node_account_id: {self.node_account_id}")
460+
raise RuntimeError(f"No node found for node_account_id: {self._node_account_id}")
433461

434462
# Store for logging and receipts
435-
self.node_account_id = node._account_id
463+
self._node_account_id = node._account_id
436464

437465
# Create a channel wrapper from the client's channel
438466
channel = node._get_channel()
@@ -442,7 +470,7 @@ def _execute(self, client: Client, timeout: int | float | None = None):
442470
"requestId",
443471
self._get_request_id(),
444472
"nodeAccountID",
445-
self.node_account_id,
473+
self._node_account_id,
446474
"attempt",
447475
attempt + 1,
448476
"maxAttempts",
@@ -483,7 +511,7 @@ def _execute(self, client: Client, timeout: int | float | None = None):
483511
logger.trace(
484512
f"{self.__class__.__name__} status received",
485513
"nodeAccountID",
486-
self.node_account_id,
514+
self._node_account_id,
487515
"network",
488516
client.network.network,
489517
"state",
@@ -518,7 +546,7 @@ def _execute(self, client: Client, timeout: int | float | None = None):
518546
case _ExecutionState.FINISHED:
519547
# If the transaction completed successfully, map the response and return it
520548
logger.trace(f"{self.__class__.__name__} finished execution")
521-
return self._map_response(response, self.node_account_id, proto_request)
549+
return self._map_response(response, self._node_account_id, proto_request)
522550

523551
logger.error(
524552
"Exceeded maximum attempts for request",
@@ -529,7 +557,7 @@ def _execute(self, client: Client, timeout: int | float | None = None):
529557
)
530558
raise MaxAttemptsError(
531559
"Exceeded maximum attempts or request timeout",
532-
self.node_account_id,
560+
self._node_account_id,
533561
err_persistant,
534562
)
535563

src/hiero_sdk_python/query/query.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,11 @@ def _make_request_header(self) -> query_header_pb2.QueryHeader:
179179
header.responseType = query_header_pb2.ResponseType.COST_ANSWER
180180
return header
181181

182-
if self.operator is not None and self.node_account_id is not None and self.payment_amount is not None:
182+
if self.operator is not None and self.node_account_ids[self._node_account_ids_index] is not None and self.payment_amount is not None:
183183
payment_tx = self._build_query_payment_transaction(
184184
payer_account_id=self.operator.account_id,
185185
payer_private_key=self.operator.private_key,
186-
node_account_id=self.node_account_id,
186+
node_account_id=self.node_account_ids[self._node_account_ids_index],
187187
amount=self.payment_amount,
188188
)
189189
header.payment.CopyFrom(payment_tx)

src/hiero_sdk_python/transaction/transaction.py

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,9 @@ def _to_proto(self):
216216
# We require the transaction to be frozen before converting to protobuf
217217
self._require_frozen()
218218

219-
body_bytes = self._transaction_body_bytes.get(self.node_account_id)
219+
body_bytes = self._transaction_body_bytes.get(self._node_account_id)
220220
if body_bytes is None:
221-
raise ValueError(f"No transaction body found for node {self.node_account_id}")
221+
raise ValueError(f"No transaction body found for node {self._node_account_id}")
222222

223223
# Get signature map, or create empty one if transaction is not signed
224224
sig_map = self._signature_map.get(body_bytes)
@@ -245,7 +245,7 @@ def _resolve_transaction_id(self, client: Client):
245245
)
246246

247247
def _resolve_node_ids(self, client: Client):
248-
if self.node_account_id is None and len(self.node_account_ids) == 0 and client is None:
248+
if self._node_account_id is None and len(self.node_account_ids) == 0 and client is None:
249249
raise ValueError(
250250
"Node account ID must be set before freezing. Use freeze_with(client) or manually set node_account_ids."
251251
)
@@ -297,27 +297,27 @@ def freeze_with(self, client: Client):
297297

298298
if self.batch_key:
299299
# For Inner Transaction of batch transaction node_account_id=0.0.0
300-
self.node_account_id = AccountId(0, 0, 0)
301-
self._transaction_body_bytes[AccountId(0, 0, 0)] = self.build_transaction_body().SerializeToString()
302-
return self
300+
self._node_account_id = AccountId(0, 0, 0)
301+
self.node_account_ids = [AccountId(0, 0, 0)]
303302

304-
# Single node
305-
if self.node_account_id:
306-
self.set_node_account_id(self.node_account_id)
307-
self._transaction_body_bytes[self.node_account_id] = self.build_transaction_body().SerializeToString()
308-
return self
303+
transaction_body = self.build_transaction_body()
304+
transaction_body.transactionID.CopyFrom(self.transaction_id._to_proto())
305+
transaction_body.nodeAccountID.CopyFrom(self._node_account_id._to_proto())
309306

310-
# Multiple node
311-
if len(self.node_account_ids) > 0:
312-
for node_account_id in self.node_account_ids:
313-
self.node_account_id = node_account_id
314-
self._transaction_body_bytes[node_account_id] = self.build_transaction_body().SerializeToString()
307+
self._transaction_body_bytes[AccountId(0, 0, 0)] = transaction_body.SerializeToString()
315308

316-
else:
317-
# Use all nodes from client network
318-
for node in client.network.nodes:
319-
self.node_account_id = node._account_id
320-
self._transaction_body_bytes[node._account_id] = self.build_transaction_body().SerializeToString()
309+
# If nodes not set by user use all nodes from client network
310+
if len(self.node_account_ids) == 0:
311+
self.node_account_ids = [node._account_id for node in client.network.nodes]
312+
313+
for node_account_id in self.node_account_ids:
314+
self._node_account_id = node_account_id
315+
316+
transaction_body = self.build_transaction_body()
317+
transaction_body.transactionID.CopyFrom(self.transaction_id._to_proto())
318+
transaction_body.nodeAccountID.CopyFrom(node_account_id._to_proto())
319+
320+
self._transaction_body_bytes[node_account_id] = transaction_body.SerializeToString()
321321

322322
return self
323323

@@ -405,7 +405,7 @@ def is_signed_by(self, public_key):
405405
"""
406406
public_key_bytes = public_key.to_bytes_raw()
407407

408-
sig_map = self._signature_map.get(self._transaction_body_bytes.get(self.node_account_id))
408+
sig_map = self._signature_map.get(self._transaction_body_bytes.get(self._node_account_id))
409409

410410
if sig_map is None:
411411
return False
@@ -452,20 +452,7 @@ def build_base_transaction_body(self) -> transaction_pb2.TransactionBody:
452452
Raises:
453453
ValueError: If required IDs are not set.
454454
"""
455-
if self.transaction_id is None:
456-
if self.operator_account_id is None:
457-
raise ValueError("Operator account ID is not set.")
458-
self.transaction_id = TransactionId.generate(self.operator_account_id)
459-
460-
transaction_id_proto = self.transaction_id._to_proto()
461-
462-
selected_node = self.node_account_id or (self.node_account_ids[0] if self.node_account_ids else None)
463-
if selected_node is None:
464-
raise ValueError("Node account ID is not set.")
465-
466455
transaction_body = transaction_pb2.TransactionBody()
467-
transaction_body.transactionID.CopyFrom(transaction_id_proto)
468-
transaction_body.nodeAccountID.CopyFrom(selected_node._to_proto())
469456

470457
fee = self._transaction_fee or self._default_transaction_fee
471458
if hasattr(fee, "to_tinybars"):

tests/unit/executable_test.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -838,11 +838,12 @@ def test_executable_overrides_client_config(mock_client):
838838

839839
def test_no_healthy_nodes_raises(mock_client):
840840
"""Test that execution fails if no healthy nodes are available."""
841-
mock_client.network._healthy_nodes = []
842-
843841
tx = AccountCreateTransaction().set_key_without_alias(PrivateKey.generate().public_key()).set_initial_balance(1)
844842

845-
with pytest.raises(RuntimeError, match="No healthy nodes available"):
843+
for node in mock_client.network.nodes:
844+
node.is_healthy = lambda: False
845+
846+
with pytest.raises(RuntimeError, match="All nodes are unhealthy"):
846847
tx.execute(mock_client)
847848

848849

tests/unit/token_airdrop_transaction_test.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,22 +161,24 @@ def test_add_zero_transfer_amount(mock_account_ids):
161161
airdrop_tx.add_approved_token_transfer_with_decimals(token_id, account_id, 0, 1)
162162

163163

164+
# TODO: Flaing wrong
164165
def test_add_unbalanced_transfer_amount(mock_account_ids):
165166
sender, receiver, _, token_id, _ = mock_account_ids
166167
airdrop_tx = TokenAirdropTransaction()
167168
airdrop_tx.add_token_transfer(token_id, sender, -1)
168169
airdrop_tx.add_token_transfer(token_id, receiver, -2)
169170

170171
with pytest.raises(ValueError):
171-
airdrop_tx.build_transaction_body()
172+
airdrop_tx.freeze()
172173

173174

175+
# TODO: Flaing wrong
174176
def test_add_invalid_transfer(mock_account_ids):
175177
_, _, _, _, _ = mock_account_ids
176178
airdrop_tx = TokenAirdropTransaction()
177179

178180
with pytest.raises(ValueError):
179-
airdrop_tx.build_transaction_body()
181+
airdrop_tx.freeze()
180182

181183

182184
def test_sign_transaction(mock_account_ids, mock_client):

tests/unit/token_pause_transaction_test.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,9 @@ def test_build_transaction_body(mock_account_ids, token_id):
3333
pause_tx.operator_account_id = account_id
3434
pause_tx.node_account_id = node_account_id
3535

36-
transaction_body = pause_tx.build_transaction_body() # Will generate a transaction_id
36+
transaction_body = pause_tx.build_transaction_body()
3737

3838
assert transaction_body.token_pause.token == token_id._to_proto()
39-
assert transaction_body.transactionID == pause_tx.transaction_id._to_proto()
40-
assert transaction_body.nodeAccountID == pause_tx.node_account_id._to_proto()
4139

4240

4341
def test_build_transaction_body_nft(mock_account_ids, nft_id):
@@ -54,8 +52,9 @@ def test_build_transaction_body_nft(mock_account_ids, nft_id):
5452
transaction_body = pause_tx.build_transaction_body()
5553

5654
assert transaction_body.token_pause.token == base_token_id._to_proto()
57-
assert transaction_body.transactionID == pause_tx.transaction_id._to_proto()
58-
assert transaction_body.nodeAccountID == pause_tx.node_account_id._to_proto()
55+
56+
57+
# TODO: Test that freeze set the transactionId and the nodeId to transaction_proto_body
5958

6059

6160
# This test uses fixture (token_id, mock_client) as parameter

tests/unit/topic_create_transaction_test.py

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -220,29 +220,7 @@ def test_build_scheduled_body(mock_account_ids, custom_fixed_fee, key_type, use_
220220
)
221221

222222

223-
# This test uses fixture mock_account_ids as parameter
224-
def test_missing_operator_in_topic_create(mock_account_ids):
225-
"""
226-
Test that building the body fails if no operator ID is set.
227-
"""
228-
_, _, node_account_id, _, _ = mock_account_ids
229-
230-
tx = TopicCreateTransaction(memo="No Operator")
231-
tx.node_account_id = node_account_id
232-
233-
with pytest.raises(ValueError, match="Operator account ID is not set."):
234-
tx.build_transaction_body()
235-
236-
237-
def test_missing_node_in_topic_create():
238-
"""
239-
Test that building the body fails if no node account ID is set.
240-
"""
241-
tx = TopicCreateTransaction(memo="No Node")
242-
tx.operator_account_id = AccountId(0, 0, 2)
243-
244-
with pytest.raises(ValueError, match="Node account ID is not set."):
245-
tx.build_transaction_body()
223+
# TODO: Test for the freeze set the node/transaction id
246224

247225

248226
# This test uses fixtures (mock_account_ids, private_key) as parameters

tests/unit/transaction_freeze_and_bytes_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ def test_transaction_freeze_without_node_ids(mock_client):
663663
tx = TransferTransaction()
664664
tx.freeze_with(mock_client)
665665

666-
assert tx.node_account_ids == []
666+
assert tx.node_account_ids == [node._account_id for node in mock_client.network.nodes]
667667
# Verify creates transaction_bytes for client network nodes
668668
assert len(tx._transaction_body_bytes) == len(mock_client.network.nodes)
669669
assert set(tx._transaction_body_bytes.keys()) == set(node._account_id for node in mock_client.network.nodes)

0 commit comments

Comments
 (0)