From eb5a8701b17622144bbac68beca3a9ba28b2c74c Mon Sep 17 00:00:00 2001 From: Emmanuel Nwajari Date: Thu, 14 May 2026 17:33:13 +0100 Subject: [PATCH 1/2] feat: add arithmetic operators to Hbar Signed-off-by: Emmanuel Nwajari --- src/hiero_sdk_python/hbar.py | 37 +++++++++++++++++++++++++ tests/unit/hbar_test.py | 52 ++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/src/hiero_sdk_python/hbar.py b/src/hiero_sdk_python/hbar.py index 22e3d03a6..ecfda9be9 100644 --- a/src/hiero_sdk_python/hbar.py +++ b/src/hiero_sdk_python/hbar.py @@ -216,6 +216,43 @@ def __ge__(self, other: object) -> bool: return NotImplemented return self._amount_in_tinybar >= other._amount_in_tinybar + def __add__(self, other: object) -> Hbar: + """ + Return a new Hbar representing the sum of this and another Hbar. + + Args: + other (Hbar): The Hbar to add. + + Returns: + Hbar: A new Hbar instance with the combined tinybar amount. + """ + if not isinstance(other, Hbar): + return NotImplemented + return Hbar.from_tinybars(self._amount_in_tinybar + other._amount_in_tinybar) + + def __sub__(self, other: object) -> Hbar: + """ + Return a new Hbar representing the difference of this and another Hbar. + + Args: + other (Hbar): The Hbar to subtract. + + Returns: + Hbar: A new Hbar instance with the resulting tinybar amount. + """ + if not isinstance(other, Hbar): + return NotImplemented + return Hbar.from_tinybars(self._amount_in_tinybar - other._amount_in_tinybar) + + def __abs__(self) -> Hbar: + """ + Return a new Hbar representing the absolute value of this Hbar. + + Returns: + Hbar: A new Hbar instance with the absolute tinybar amount. + """ + return Hbar.from_tinybars(abs(self._amount_in_tinybar)) + Hbar.ZERO = Hbar(0) Hbar.MAX = Hbar(50_000_000_000) diff --git a/tests/unit/hbar_test.py b/tests/unit/hbar_test.py index f0e42120e..74723a865 100644 --- a/tests/unit/hbar_test.py +++ b/tests/unit/hbar_test.py @@ -332,3 +332,55 @@ def test_from_tinybars_invalid_type_param(invalid_tinybars): """Test from_tinybar method raises error if the type is not int.""" with pytest.raises(TypeError, match=re.escape("tinybars must be an int.")): Hbar.from_tinybars(invalid_tinybars) + + +# Arithmetic operator tests for issue #2274 +# --------------------------------------------------------------------------- + + +def test_add_two_hbars(): + """Test that two Hbar values can be added using the + operator.""" + assert Hbar(10) + Hbar(5) == Hbar(15) + assert (Hbar(10) + Hbar(5)).to_tinybars() == Hbar(15).to_tinybars() + + +def test_sub_two_hbars(): + """Test that two Hbar values can be subtracted using the - operator.""" + assert Hbar(10) - Hbar(5) == Hbar(5) + assert (Hbar(10) - Hbar(5)).to_tinybars() == Hbar(5).to_tinybars() + + +def test_abs_hbar(): + """Test that abs() returns the absolute value of an Hbar.""" + assert abs(Hbar(-3)) == Hbar(3) + assert abs(Hbar(3)) == Hbar(3) + + +def test_add_non_hbar_raises_type_error(): + """Test that adding a non-Hbar type raises TypeError.""" + with pytest.raises(TypeError): + _ = Hbar(1) + 5 + + with pytest.raises(TypeError): + _ = Hbar(1) + "5" + + +def test_sub_non_hbar_raises_type_error(): + """Test that subtracting a non-Hbar type raises TypeError.""" + with pytest.raises(TypeError): + _ = Hbar(1) - 5 + + with pytest.raises(TypeError): + _ = Hbar(1) - "5" + + +def test_add_hbar_zero(): + """Test that adding Hbar.ZERO returns the same value.""" + assert Hbar(5) + Hbar.ZERO == Hbar(5) + + +def test_sub_resulting_in_negative(): + """Test that subtraction can produce a negative Hbar.""" + result = Hbar(5) - Hbar(10) + assert result == Hbar(-5) + assert result.to_tinybars() == Hbar(-5).to_tinybars() From 696368d8379559a0d3775b78e371cbbaa3013c1b Mon Sep 17 00:00:00 2001 From: Emmanuel Nwajari Date: Thu, 14 May 2026 17:55:31 +0100 Subject: [PATCH 2/2] test: address CodeRabbit review add isinstance checks and edge case tests Signed-off-by: Emmanuel Nwajari --- tests/unit/hbar_test.py | 59 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/tests/unit/hbar_test.py b/tests/unit/hbar_test.py index 74723a865..e493fdbe2 100644 --- a/tests/unit/hbar_test.py +++ b/tests/unit/hbar_test.py @@ -340,19 +340,25 @@ def test_from_tinybars_invalid_type_param(invalid_tinybars): def test_add_two_hbars(): """Test that two Hbar values can be added using the + operator.""" - assert Hbar(10) + Hbar(5) == Hbar(15) + result = Hbar(10) + Hbar(5) + assert isinstance(result, Hbar) + assert result == Hbar(15) assert (Hbar(10) + Hbar(5)).to_tinybars() == Hbar(15).to_tinybars() def test_sub_two_hbars(): """Test that two Hbar values can be subtracted using the - operator.""" - assert Hbar(10) - Hbar(5) == Hbar(5) + result = Hbar(10) - Hbar(5) + assert isinstance(result, Hbar) + assert result == Hbar(5) assert (Hbar(10) - Hbar(5)).to_tinybars() == Hbar(5).to_tinybars() def test_abs_hbar(): """Test that abs() returns the absolute value of an Hbar.""" - assert abs(Hbar(-3)) == Hbar(3) + result = abs(Hbar(-3)) + assert isinstance(result, Hbar) + assert result == Hbar(3) assert abs(Hbar(3)) == Hbar(3) @@ -374,6 +380,24 @@ def test_sub_non_hbar_raises_type_error(): _ = Hbar(1) - "5" +def test_reversed_add_non_hbar_raises_type_error(): + """Test that adding Hbar to a non-Hbar type (reversed) raises TypeError.""" + with pytest.raises(TypeError): + _ = 5 + Hbar(1) + + with pytest.raises(TypeError): + _ = "5" + Hbar(1) + + +def test_reversed_sub_non_hbar_raises_type_error(): + """Test that subtracting Hbar from a non-Hbar type (reversed) raises TypeError.""" + with pytest.raises(TypeError): + _ = 5 - Hbar(1) + + with pytest.raises(TypeError): + _ = "5" - Hbar(1) + + def test_add_hbar_zero(): """Test that adding Hbar.ZERO returns the same value.""" assert Hbar(5) + Hbar.ZERO == Hbar(5) @@ -382,5 +406,34 @@ def test_add_hbar_zero(): def test_sub_resulting_in_negative(): """Test that subtraction can produce a negative Hbar.""" result = Hbar(5) - Hbar(10) + assert isinstance(result, Hbar) assert result == Hbar(-5) assert result.to_tinybars() == Hbar(-5).to_tinybars() + + +def test_abs_hbar_zero(): + """Test that abs(Hbar.ZERO) returns Hbar.ZERO.""" + result = abs(Hbar.ZERO) + assert isinstance(result, Hbar) + assert result == Hbar.ZERO + + +def test_chained_addition(): + """Test that addition operations can be chained.""" + result = Hbar(1) + Hbar(2) + Hbar(3) + assert isinstance(result, Hbar) + assert result == Hbar(6) + + +def test_chained_subtraction(): + """Test that subtraction operations can be chained.""" + result = Hbar(10) - Hbar(3) - Hbar(2) + assert isinstance(result, Hbar) + assert result == Hbar(5) + + +def test_mixed_arithmetic_operations(): + """Test that arithmetic operations can be mixed and chained.""" + result = abs(Hbar(-5) + Hbar(2)) + assert isinstance(result, Hbar) + assert result == Hbar(3)