Skip to content

Commit b3e019e

Browse files
committed
fix: hbar test coverage issue
Signed-off-by: prajeeta pal <[email protected]>
1 parent ea91f78 commit b3e019e

File tree

3 files changed

+120
-11
lines changed

3 files changed

+120
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
99

1010

1111
### Added
12+
- Added Hbar object support for TransferTransaction HBAR transfers: methods now accept Union[int, Hbar] for amount parameters, with immediate normalization to tinybars. Includes comprehensive unit tests covering various Hbar units (HBAR, MICROBAR, MILLIBAR, TINYBAR) and accumulation behavior with mixed int and Hbar inputs.
1213
- examples/mypy.ini for stricter type checking in example scripts
1314
- Added a GitHub Actions workflow that reminds contributors to link pull requests to issues.
1415
- Added `__str__` and `__repr__` methods to `AccountInfo` class for improved logging and debugging experience (#1098)

src/hiero_sdk_python/transaction/transfer_transaction.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
Defines TransferTransaction for transferring HBAR or tokens between accounts.
33
"""
44

5-
from typing import Dict, List, Optional, Tuple
5+
from typing import Dict, List, Optional, Tuple, Union
66

77
from hiero_sdk_python.account.account_id import AccountId
88
from hiero_sdk_python.channels import _Channel
99
from hiero_sdk_python.executable import _Method
10+
from hiero_sdk_python.hbar import Hbar
1011
from hiero_sdk_python.hapi.services import basic_types_pb2, crypto_transfer_pb2, transaction_pb2
1112
from hiero_sdk_python.hapi.services.schedulable_transaction_body_pb2 import (
1213
SchedulableTransactionBody,
@@ -59,14 +60,14 @@ def _init_hbar_transfers(self, hbar_transfers: Dict[AccountId, int]) -> None:
5960
self.add_hbar_transfer(account_id, amount)
6061

6162
def _add_hbar_transfer(
62-
self, account_id: AccountId, amount: int, is_approved: bool = False
63+
self, account_id: AccountId, amount: Union[int, Hbar], is_approved: bool = False
6364
) -> "TransferTransaction":
6465
"""
6566
Internal method to add a HBAR transfer to the transaction.
6667
6768
Args:
6869
account_id (AccountId): The account ID of the sender or receiver.
69-
amount (int): The amount of the HBAR to transfer.
70+
amount (Union[int, Hbar]): The amount of the HBAR to transfer.
7071
is_approved (bool, optional): Whether the transfer is approved. Defaults to False.
7172
7273
Returns:
@@ -75,8 +76,12 @@ def _add_hbar_transfer(
7576
self._require_not_frozen()
7677
if not isinstance(account_id, AccountId):
7778
raise TypeError("account_id must be an AccountId instance.")
78-
if not isinstance(amount, int) or amount == 0:
79-
raise ValueError("Amount must be a non-zero integer.")
79+
if isinstance(amount, Hbar):
80+
amount = amount.to_tinybars()
81+
elif not isinstance(amount, int):
82+
raise TypeError("amount must be an int or Hbar instance.")
83+
if amount == 0:
84+
raise ValueError("Amount must be a non-zero value.")
8085
if not isinstance(is_approved, bool):
8186
raise TypeError("is_approved must be a boolean.")
8287

@@ -88,13 +93,13 @@ def _add_hbar_transfer(
8893
self.hbar_transfers.append(HbarTransfer(account_id, amount, is_approved))
8994
return self
9095

91-
def add_hbar_transfer(self, account_id: AccountId, amount: int) -> "TransferTransaction":
96+
def add_hbar_transfer(self, account_id: AccountId, amount: Union[int, Hbar]) -> "TransferTransaction":
9297
"""
9398
Adds a HBAR transfer to the transaction.
9499
95100
Args:
96101
account_id (AccountId): The account ID of the sender or receiver.
97-
amount (int): The amount of the HBAR to transfer.
102+
amount (Union[int, Hbar]): The amount of the HBAR to transfer.
98103
99104
Returns:
100105
TransferTransaction: The current instance of the transaction for chaining.
@@ -103,14 +108,14 @@ def add_hbar_transfer(self, account_id: AccountId, amount: int) -> "TransferTran
103108
return self
104109

105110
def add_approved_hbar_transfer(
106-
self, account_id: AccountId, amount: int
111+
self, account_id: AccountId, amount: Union[int, Hbar]
107112
) -> "TransferTransaction":
108113
"""
109114
Adds a HBAR transfer with approval to the transaction.
110115
111116
Args:
112117
account_id (AccountId): The account ID of the sender or receiver.
113-
amount (int): The amount of the HBAR to transfer.
118+
amount (Union[int, Hbar]): The amount of the HBAR to transfer.
114119
115120
Returns:
116121
TransferTransaction: The current instance of the transaction for chaining.

tests/unit/transfer_transaction_test.py

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
from hiero_sdk_python.hapi.services.schedulable_transaction_body_pb2 import (
88
SchedulableTransactionBody,
99
)
10+
from hiero_sdk_python.hbar import Hbar
11+
from hiero_sdk_python.hbar_unit import HbarUnit
1012
from hiero_sdk_python.tokens.nft_id import NftId
1113
from hiero_sdk_python.transaction.transfer_transaction import TransferTransaction
1214

@@ -283,8 +285,8 @@ def test_zero_amount_validation(mock_account_ids):
283285
account_id_1, _, _, token_id_1, _ = mock_account_ids
284286
transfer_tx = TransferTransaction()
285287

286-
# Test zero HBAR amount should raise ValueError
287-
with pytest.raises(ValueError, match="Amount must be a non-zero integer"):
288+
# Test zero HBAR amount should raise ValueError with updated message
289+
with pytest.raises(ValueError, match="Amount must be a non-zero value"):
288290
transfer_tx.add_hbar_transfer(account_id_1, 0)
289291

290292
# Test zero token amount should raise ValueError
@@ -510,3 +512,104 @@ def test_approved_token_transfer_validation(mock_account_ids):
510512
# Test zero amount
511513
with pytest.raises(ValueError, match="Amount must be a non-zero integer"):
512514
transfer_tx.add_approved_token_transfer_with_decimals(token_id_1, account_id_1, 0, 6)
515+
516+
517+
def test_add_hbar_transfer_with_hbar_object(mock_account_ids):
518+
"""Test adding HBAR transfers with Hbar objects (covers Hbar normalization)."""
519+
account_id_sender, account_id_recipient, _, _, _ = mock_account_ids
520+
transfer_tx = TransferTransaction()
521+
522+
transfer_tx.add_hbar_transfer(account_id_sender, Hbar(-500))
523+
transfer_tx.add_hbar_transfer(account_id_recipient, Hbar(500))
524+
525+
sender_transfer = next(
526+
t for t in transfer_tx.hbar_transfers if t.account_id == account_id_sender
527+
)
528+
recipient_transfer = next(
529+
t for t in transfer_tx.hbar_transfers if t.account_id == account_id_recipient
530+
)
531+
532+
assert sender_transfer.amount == -50_000_000_000
533+
assert recipient_transfer.amount == 50_000_000_000
534+
535+
536+
def test_add_hbar_transfer_with_hbar_tinybars(mock_account_ids):
537+
"""Test adding HBAR transfers with Hbar objects in TINYBAR units."""
538+
account_id_sender, account_id_recipient, _, _, _ = mock_account_ids
539+
transfer_tx = TransferTransaction()
540+
541+
transfer_tx.add_hbar_transfer(account_id_sender, Hbar(-500, HbarUnit.TINYBAR))
542+
transfer_tx.add_hbar_transfer(account_id_recipient, Hbar(500, HbarUnit.TINYBAR))
543+
544+
sender_transfer = next(
545+
t for t in transfer_tx.hbar_transfers if t.account_id == account_id_sender
546+
)
547+
recipient_transfer = next(
548+
t for t in transfer_tx.hbar_transfers if t.account_id == account_id_recipient
549+
)
550+
551+
assert sender_transfer.amount == -500
552+
assert recipient_transfer.amount == 500
553+
554+
555+
def test_add_approved_hbar_transfer_with_hbar_object(mock_account_ids):
556+
"""Test adding approved HBAR transfers with Hbar objects."""
557+
account_id_sender, _, _, _, _ = mock_account_ids
558+
transfer_tx = TransferTransaction()
559+
560+
transfer_tx.add_approved_hbar_transfer(account_id_sender, Hbar(1000))
561+
562+
transfer = transfer_tx.hbar_transfers[0]
563+
assert transfer.account_id == account_id_sender
564+
assert transfer.amount == 100_000_000_000
565+
assert transfer.is_approved is True
566+
567+
568+
def test_hbar_accumulation_with_mixed_int_and_hbar(mock_account_ids):
569+
"""Test that HBAR transfers accumulate correctly with mixed int and Hbar inputs."""
570+
account_id_1, _, _, _, _ = mock_account_ids
571+
transfer_tx = TransferTransaction()
572+
573+
transfer_tx.add_hbar_transfer(account_id_1, 100)
574+
transfer_tx.add_hbar_transfer(account_id_1, Hbar(1))
575+
transfer_tx.add_hbar_transfer(account_id_1, -50)
576+
577+
transfer = transfer_tx.hbar_transfers[0]
578+
assert transfer.amount == 100 + 100_000_000 - 50
579+
580+
581+
def test_zero_hbar_value_validation(mock_account_ids):
582+
"""Test that zero Hbar amounts are properly rejected."""
583+
account_id_1, _, _, _, _ = mock_account_ids
584+
transfer_tx = TransferTransaction()
585+
586+
with pytest.raises(ValueError, match="Amount must be a non-zero value"):
587+
transfer_tx.add_hbar_transfer(account_id_1, Hbar(0))
588+
589+
with pytest.raises(ValueError, match="Amount must be a non-zero value"):
590+
transfer_tx.add_hbar_transfer(account_id_1, 0)
591+
592+
593+
def test_add_hbar_transfer_with_various_hbar_units(mock_account_ids):
594+
"""Test adding HBAR transfers with various Hbar units."""
595+
account_id_1, _, _, _, _ = mock_account_ids
596+
transfer_tx = TransferTransaction()
597+
598+
transfer_tx.add_hbar_transfer(account_id_1, Hbar(1, HbarUnit.HBAR))
599+
transfer_tx.add_hbar_transfer(account_id_1, Hbar(1000, HbarUnit.MICROBAR))
600+
transfer_tx.add_hbar_transfer(account_id_1, Hbar(100, HbarUnit.MILLIBAR))
601+
602+
transfer = transfer_tx.hbar_transfers[0]
603+
assert transfer.amount == 100_000_000 + 100_000 + 10_000_000
604+
605+
606+
def test_invalid_amount_type_hbar_transfer(mock_account_ids):
607+
"""Test that invalid amount types raise TypeError (covers type checking)."""
608+
account_id_1, _, _, _, _ = mock_account_ids
609+
transfer_tx = TransferTransaction()
610+
611+
with pytest.raises(TypeError, match="amount must be an int or Hbar instance"):
612+
transfer_tx.add_hbar_transfer(account_id_1, "invalid")
613+
614+
with pytest.raises(TypeError, match="amount must be an int or Hbar instance"):
615+
transfer_tx.add_hbar_transfer(account_id_1, 123.45)

0 commit comments

Comments
 (0)