Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
f694268
add tokenInfoQuery functionality
aceppaluni May 22, 2025
d5310c8
refactor: update TokenInfoQuery implementation
Dosik13 May 27, 2025
76b0d85
test: add unit tests
Dosik13 May 27, 2025
256e807
test: add integration tests
Dosik13 May 27, 2025
32443f1
docs: add examples for both non-fungible/fungible tokens
Dosik13 May 27, 2025
3c3a6ea
docs: update README in examples
Dosik13 May 27, 2025
1a453ee
chore: add TokenInfoQuery to __init__.py
Dosik13 May 27, 2025
1c6ac60
test: reduce test_token_info_query_execute function length
Dosik13 May 28, 2025
df1069c
test: fix incorrect integration test function names
Dosik13 May 28, 2025
67c9eb7
docs: change network from solo to testnet and some minor changes in e…
Dosik13 May 28, 2025
d7d6c18
test: address PR comments for integration/unit tests
Dosik13 May 30, 2025
79c1f10
docs: update examples for TokenInfoQuery to address PR comments
Dosik13 May 30, 2025
a4372ad
Merge branch 'hiero-ledger:main' into main
aceppaluni Jun 2, 2025
17ace16
Merge branch 'hiero-ledger:main' into main
aceppaluni Jun 4, 2025
090b2bb
Merge branch 'hiero-ledger:main' into main
aceppaluni Jun 16, 2025
854c0ca
Merge branch 'hiero-ledger:main' into main
aceppaluni Aug 6, 2025
168d706
Merge branch 'hiero-ledger:main' into main
aceppaluni Aug 7, 2025
143b727
Merge branch 'hiero-ledger:main' into main
aceppaluni Aug 15, 2025
ad6df88
Merge branch 'hiero-ledger:main' into main
aceppaluni Aug 20, 2025
fdcc0cb
Merge branch 'hiero-ledger:main' into main
aceppaluni Sep 3, 2025
b9ad245
Merge branch 'hiero-ledger:main' into main
aceppaluni Sep 8, 2025
7f4ee47
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 14, 2025
e17c504
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 19, 2025
22ba822
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 20, 2025
2741bde
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 21, 2025
9621065
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 22, 2025
9469f23
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 23, 2025
cfd8e1c
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 24, 2025
1cb2132
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 27, 2025
9328d1f
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 28, 2025
e594364
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 28, 2025
a5267b8
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 29, 2025
13b3573
Merge branch 'hiero-ledger:main' into main
aceppaluni Oct 30, 2025
177248e
Merge branch 'hiero-ledger:main' into main
aceppaluni Nov 4, 2025
db93977
Add set_node_account_id method
aceppaluni Sep 8, 2025
18e17c8
fix: add missing List import and update changelog
aceppaluni Oct 28, 2025
1817ac2
style: add spacing in set_node_account_id method
aceppaluni Oct 28, 2025
32e4227
feat: support selecting node account ID for execution flow
aceppaluni Oct 29, 2025
5f694bd
Fix node selection to use _select_node instead of _get_node
aceppaluni Oct 30, 2025
6e60202
feat: add Network._get_node() and update executable to support node s…
aceppaluni Nov 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
- Added expiration_time, auto_renew_period, auto_renew_account, fee_schedule_key, kyc_key in `TokenCreateTransaction`, `TokenUpdateTransaction` classes
- Added comprehensive Google-style docstrings to the `CustomFee` class and its methods in `custom_fee.py`.
- docs: Add `docs/sdk_developers/project_structure.md` to explain repository layout and import paths.
- Support selecting specific node account ID(s) for queries and transactions (#362)
- Added `Network._get_node()` method and updated execution flow to use node selection (#362)

### Changed
- chore: validate that token airdrop transactions require an available token service on the channel (#632)
Expand Down
15 changes: 15 additions & 0 deletions src/hiero_sdk_python/client/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,21 @@ def _select_node(self) -> _Node:
self._node_index = (self._node_index + 1) % len(self.nodes)
self.current_node = self.nodes[self._node_index]
return self.current_node

def _get_node(self, account_id: AccountId) -> Optional[_Node]:
"""
Get a node matching the given account ID.

Args:
account_id (AccountId): The account ID of the node to locate.

Returns:
Optional[_Node]: The matching node, or None if not found.
"""
for node in self.nodes:
if node._account_id == account_id:
return node
return None

def get_mirror_address(self) -> str:
"""
Expand Down
13 changes: 9 additions & 4 deletions src/hiero_sdk_python/executable.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,15 @@ def _execute(self, client: "Client"):
if attempt > 0 and current_backoff < self._max_backoff:
current_backoff *= 2

# Set the node account id to the client's node account id
node = client.network.current_node
self.node_account_id = node._account_id

# Select preferred node if provided, fallback to client's default
selected_node_account_id = (
self._select_node_account_id()
or client.network.current_node._account_id
)

self.node_account_id = selected_node_account_id
node = client.network._get_node(self.node_account_id)

# Create a channel wrapper from the client's channel
channel = node._get_channel()

Expand Down
44 changes: 44 additions & 0 deletions src/hiero_sdk_python/query/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ def __init__(self) -> None:
self.node_index: int = 0
self.payment_amount: Optional[Hbar] = None

self.node_account_ids: Optional[List[AccountId]] = None
self._used_node_account_id: Optional[AccountId] = None

def _get_query_response(self, response: Any) -> query_pb2.Query:
"""
Extracts the query-specific response object from the full response.
Expand Down Expand Up @@ -379,3 +382,44 @@ def _is_payment_required(self) -> bool:
bool: True if payment is required, False otherwise
"""
return True

def set_node_account_ids(self, node_account_ids: List[AccountId]):
"""
Sets the list of node account IDs the query can be sent to.

Args:
node_account_ids (List[AccountId]): The list of node account IDs.

Returns:
Self: Returns self for method chaining.
"""
self.node_account_ids = node_account_ids
return self

def set_node_account_id(self, node_account_id: AccountId):
"""
Sets a single node account ID the query will be sent to.

Args:
node_account_id (AccountId): The node account ID.

Returns:
Self: Returns self for method chaining.
"""

return self.set_node_account_ids([node_account_id])

def _select_node_account_id(self) -> Optional[AccountId]:
"""
Internal method to select a node account ID to send the query to.
Defaults to the first in the list.

Returns:
Optional[AccountId]: The selected node account ID.
"""
if self.node_account_ids:
selected = self.node_account_ids[0]
self._used_node_account_id = selected
return selected
return None

7 changes: 5 additions & 2 deletions src/hiero_sdk_python/transaction/transaction.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import hashlib
from typing import Optional
from typing import List, Optional

from typing import TYPE_CHECKING

Expand Down Expand Up @@ -59,7 +59,10 @@ def __init__(self) -> None:
# and ensures that the correct signatures are used when submitting transactions
self._signature_map: dict[bytes, basic_types_pb2.SignatureMap] = {}
self._default_transaction_fee = 2_000_000
self.operator_account_id = None
self.operator_account_id = None

self.node_account_ids: Optional[List[AccountId]] = None
self._used_node_account_id: Optional[AccountId] = None

def _make_request(self):
"""
Expand Down
31 changes: 31 additions & 0 deletions tests/unit/test_query_nodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import pytest
from hiero_sdk_python.query.query import Query
from hiero_sdk_python.account.account_id import AccountId

def test_set_single_node_account_id():
q = Query()
node = AccountId(0, 0, 3)

q.set_node_account_id(node)

assert q.node_account_ids == [node]
assert q._used_node_account_id is None # not selected until execution

def test_set_multiple_node_account_ids():
q = Query()
nodes = [AccountId(0, 0, 3), AccountId(0, 0, 4)]

q.set_node_account_ids(nodes)

assert q.node_account_ids == nodes
assert q._used_node_account_id is None

def test_select_node_account_id():
q = Query()
nodes = [AccountId(0, 0, 3), AccountId(0, 0, 4)]
q.set_node_account_ids(nodes)

selected = q._select_node_account_id()

assert selected == nodes[0]
assert q._used_node_account_id == nodes[0]
52 changes: 52 additions & 0 deletions tests/unit/test_transaction_nodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import pytest
from hiero_sdk_python.transaction.transaction import Transaction
from hiero_sdk_python.account.account_id import AccountId


class DummyTransaction(Transaction):
"""
Minimal subclass of Transaction for testing.
Transaction is abstract (requires build methods), so we stub them out.
"""
def __init__(self):
super().__init__()

def build_base_transaction_body(self):
return None # stub

def _make_request(self):
return None # stub

def _get_method(self):
return None # stub


def test_set_single_node_account_id():
txn = DummyTransaction()
node = AccountId(0, 0, 3)

txn.set_node_account_id(node)

assert txn.node_account_ids == [node]
assert txn._used_node_account_id is None


def test_set_multiple_node_account_ids():
txn = DummyTransaction()
nodes = [AccountId(0, 0, 3), AccountId(0, 0, 4)]

txn.set_node_account_ids(nodes)

assert txn.node_account_ids == nodes
assert txn._used_node_account_id is None


def test_select_node_account_id():
txn = DummyTransaction()
nodes = [AccountId(0, 0, 3), AccountId(0, 0, 4)]
txn.set_node_account_ids(nodes)

selected = txn._select_node_account_id()

assert selected == nodes[0]
assert txn._used_node_account_id == nodes[0]
Loading