Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
- Added TokenUnpauseTransaction class
- 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`.
- Added repr method to `src/hiero_sdk_python/tokens/custom_fixed_fee.py`, made `examples/custom_fee_fixed.` modular, and updated `tests/unit/test_custom_fee.py` correspondingly.

### Changed
- chore: validate that token airdrop transactions require an available token service on the channel (#632)
Expand Down
32 changes: 22 additions & 10 deletions examples/custom_fee_fixed.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,41 @@
"""
Run with:
Example for creating and displaying a CustomFixedFee object.

This example demonstrates:
1. How to instantiate CustomFixedFee.
2. The output of the new __repr__ method for clear debugging.
3. How to convert the fee object to its protobuf representation.

Run with:
uv run examples/custom_fixed_fee.py
python examples/custom_fixed_fee.py
"""
from hiero_sdk_python.tokens.custom_fixed_fee import CustomFixedFee
from hiero_sdk_python.account.account_id import AccountId
from hiero_sdk_python.tokens.token_id import TokenId

def custom_fixed_fee():
def demonstrate_custom_fixed_fee():
"""Creates and displays a CustomFixedFee."""

# 1. Create the CustomFixedFee object
fixed_fee = CustomFixedFee(
amount=100,
denominating_token_id=TokenId(0, 0, 123),
fee_collector_account_id=AccountId(0, 0, 456),
all_collectors_are_exempt=False,
)
print("CustomFixedFee:")
print(f"Amount: {fixed_fee.amount}")
print(f"Denominating Token ID: {fixed_fee.denominating_token_id}")
print(f"Fee Collector Account ID: {fixed_fee.fee_collector_account_id}")
print(f"All Collectors Exempt: {fixed_fee.all_collectors_are_exempt}")
# Convert to protobuf

# 2. Print the object directly to see the __repr__ output
print("--- CustomFixedFee (using __repr__) ---")
print(fixed_fee)

# 3. Convert to protobuf
fixed_fee_proto = fixed_fee._to_proto()

print("Fixed Fee Protobuf:", fixed_fee_proto)
print("\n--- Fixed Fee Protobuf ---")
print(fixed_fee_proto)


if __name__ == "__main__":
custom_fixed_fee()
# Call the main function when the script is executed
demonstrate_custom_fixed_fee()
23 changes: 21 additions & 2 deletions src/hiero_sdk_python/tokens/custom_fixed_fee.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class CustomFixedFee(CustomFee):
custom fee is attached to.
"""

__slots__ = ("amount", "denominating_token_id")

def __init__(
self,
amount: int = 0,
Expand Down Expand Up @@ -181,7 +183,7 @@ def _to_topic_fee_proto(self) -> "custom_fees_pb2.FixedCustomFee":

Raises:
ValueError: If the fee amount is negative or potentially if IDs are invalid.
(Note: Current implementation doesn't explicitly check amount >= 0).
(Note: Current implementation doesn't explicitly check amount >= 0).
"""
from hiero_sdk_python.hapi.services import custom_fees_pb2

Expand Down Expand Up @@ -261,4 +263,21 @@ def __eq__(self, other: "CustomFixedFee") -> bool:
Returns:
bool: True if the objects are considered equal, False otherwise.
"""
return super().__eq__(other) and self.amount == other.amount and self.denominating_token_id == other.denominating_token_id
if not isinstance(other, CustomFixedFee):
return False

return (
super().__eq__(other) and
self.amount == other.amount and
self.denominating_token_id == other.denominating_token_id
)

def __repr__(self) -> str:
"""Generates a developer-friendly string representation of the object."""
return (
f"{self.__class__.__name__}("
f"amount={self.amount}, "
f"denominating_token_id={self.denominating_token_id!r}, "
f"fee_collector_account_id={self.fee_collector_account_id!r}, "
f"all_collectors_are_exempt={self.all_collectors_are_exempt})"
)
24 changes: 16 additions & 8 deletions tests/unit/test_custom_fee.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@ def test_custom_fixed_fee():
all_collectors_are_exempt=True,
)

proto = fee._to_proto() # Changed from _to_protobuf
new_fee = CustomFixedFee._from_proto(proto) # Changed from CustomFee._from_protobuf

proto = fee._to_proto()
new_fee = CustomFixedFee._from_proto(proto)
assert isinstance(new_fee, CustomFixedFee)
assert new_fee.amount == 100
assert new_fee.denominating_token_id == TokenId(0, 0, 123)
assert new_fee.fee_collector_account_id == AccountId(0, 0, 456)
assert new_fee.all_collectors_are_exempt is True
assert fee == new_fee
fee_repr = repr(fee)
assert "CustomFixedFee" in fee_repr
assert "amount=100" in fee_repr
assert "denominating_token_id=TokenId(shard_num=0, realm_num=0, num=123)" in fee_repr
assert "fee_collector_account_id=AccountId(shard_num=0, realm_num=0, num=456)" in fee_repr
assert "all_collectors_are_exempt=True" in fee_repr

def test_custom_fractional_fee():
fee = CustomFractionalFee(
Expand All @@ -37,8 +43,8 @@ def test_custom_fractional_fee():
all_collectors_are_exempt=False,
)

proto = fee._to_proto() # Changed from _to_protobuf
new_fee = CustomFractionalFee._from_proto(proto) # Changed from CustomFee._from_protobuf
proto = fee._to_proto()
new_fee = CustomFractionalFee._from_proto(proto)

assert isinstance(new_fee, CustomFractionalFee)
assert new_fee.numerator == 1
Expand All @@ -48,6 +54,7 @@ def test_custom_fractional_fee():
assert new_fee.assessment_method == FeeAssessmentMethod.EXCLUSIVE
assert new_fee.fee_collector_account_id == AccountId(0, 0, 456)
assert new_fee.all_collectors_are_exempt is False
assert fee == new_fee

def test_custom_royalty_fee():
fallback_fee = CustomFixedFee(
Expand All @@ -62,8 +69,8 @@ def test_custom_royalty_fee():
all_collectors_are_exempt=True,
)

proto = fee._to_proto() # Changed from _to_protobuf
new_fee = CustomRoyaltyFee._from_proto(proto) # Changed from CustomFee._from_protobuf
proto = fee._to_proto()
new_fee = CustomRoyaltyFee._from_proto(proto)

assert isinstance(new_fee, CustomRoyaltyFee)
assert new_fee.numerator == 5
Expand All @@ -72,4 +79,5 @@ def test_custom_royalty_fee():
assert new_fee.all_collectors_are_exempt is True
assert isinstance(new_fee.fallback_fee, CustomFixedFee)
assert new_fee.fallback_fee.amount == 50
assert new_fee.fallback_fee.denominating_token_id == TokenId(0, 0, 789)
assert new_fee.fallback_fee.denominating_token_id == TokenId(0, 0, 789)
assert fee == new_fee
Loading