|
| 1 | +""" |
| 2 | +Example: Using CustomFeeLimit with a revenue-generating topic. |
| 3 | +
|
| 4 | +- Creates a topic that charges a fixed custom fee per message. |
| 5 | +- Submits a message with a CustomFeeLimit specifying how much the payer is |
| 6 | + willing to pay in custom fees for that message. |
| 7 | +""" |
| 8 | + |
| 9 | +import os |
| 10 | +import sys |
| 11 | +from dotenv import load_dotenv |
| 12 | + |
| 13 | +from hiero_sdk_python import ( |
| 14 | + Client, |
| 15 | + AccountId, |
| 16 | + PrivateKey, |
| 17 | + Hbar, |
| 18 | + Network, |
| 19 | + TopicCreateTransaction, |
| 20 | + TopicMessageSubmitTransaction, |
| 21 | + CustomFixedFee, |
| 22 | +) |
| 23 | +from hiero_sdk_python.transaction.custom_fee_limit import CustomFeeLimit |
| 24 | + |
| 25 | + |
| 26 | +def setup_client() -> tuple[Client, AccountId]: |
| 27 | + """Initialize client and operator from .env file.""" |
| 28 | + load_dotenv() |
| 29 | + |
| 30 | + if "OPERATOR_ID" not in os.environ or "OPERATOR_KEY" not in os.environ: |
| 31 | + print("Environment variables OPERATOR_ID or OPERATOR_KEY are missing.") |
| 32 | + sys.exit(1) |
| 33 | + |
| 34 | + try: |
| 35 | + operator_id = AccountId.from_string(os.environ["OPERATOR_ID"]) |
| 36 | + operator_key = PrivateKey.from_string(os.environ["OPERATOR_KEY"]) |
| 37 | + except Exception as e: # noqa: BLE001 |
| 38 | + print(f"Failed to parse OPERATOR_ID or OPERATOR_KEY: {e}") |
| 39 | + sys.exit(1) |
| 40 | + |
| 41 | + network_name = os.environ.get("NETWORK", "testnet") |
| 42 | + |
| 43 | + try: |
| 44 | + client = Client(Network(network_name)) |
| 45 | + except Exception as e: |
| 46 | + print(f"Failed to create client for network '{network_name}': {e}") |
| 47 | + sys.exit(1) |
| 48 | + |
| 49 | + client.set_operator(operator_id, operator_key) |
| 50 | + print(f"Operator set: {operator_id}") |
| 51 | + |
| 52 | + return client, operator_id |
| 53 | + |
| 54 | + |
| 55 | +def create_revenue_generating_topic(client: Client, operator_id: AccountId): |
| 56 | + """ |
| 57 | + Create a topic that charges a fixed custom fee per message. |
| 58 | +
|
| 59 | + The topic charges 1 HBAR (in tinybars) to the operator account for every message. |
| 60 | + """ |
| 61 | + print("\nCreating a topic with a fixed custom fee per message...") |
| 62 | + |
| 63 | + # Charge 1 HBAR to the operator for every message |
| 64 | + custom_fee = CustomFixedFee( |
| 65 | + amount=Hbar(1).to_tinybars(), |
| 66 | + fee_collector_account_id=operator_id, |
| 67 | + ) |
| 68 | + |
| 69 | + try: |
| 70 | + topic_tx = TopicCreateTransaction() |
| 71 | + topic_tx.set_custom_fees([custom_fee]) |
| 72 | + |
| 73 | + # execute() returns the receipt |
| 74 | + topic_receipt = topic_tx.execute(client) |
| 75 | + |
| 76 | + topic_id = topic_receipt.topic_id |
| 77 | + print(f"Topic created successfully: {topic_id}") |
| 78 | + print("This topic charges a fixed fee of 1 HBAR per message.") |
| 79 | + |
| 80 | + return topic_id |
| 81 | + except Exception as e: # noqa: BLE001 |
| 82 | + print(f"Failed to create topic: {e}") |
| 83 | + return None |
| 84 | + |
| 85 | + |
| 86 | +def submit_message_with_custom_fee_limit( |
| 87 | + client: Client, topic_id, operator_id: AccountId |
| 88 | +) -> None: |
| 89 | + """ |
| 90 | + Submit a message to the topic with a CustomFeeLimit applied. |
| 91 | +
|
| 92 | + The CustomFeeLimit caps the total custom fees the payer is willing to pay |
| 93 | + for this message at 2 HBAR. |
| 94 | + """ |
| 95 | + print("\nSubmitting a message with a CustomFeeLimit...") |
| 96 | + |
| 97 | + # We are willing to pay up to 2 HBAR in custom fees for this message |
| 98 | + limit_fee = CustomFixedFee( |
| 99 | + amount=Hbar(2).to_tinybars(), |
| 100 | + fee_collector_account_id=operator_id, |
| 101 | + ) |
| 102 | + |
| 103 | + fee_limit = CustomFeeLimit() |
| 104 | + fee_limit.set_payer_id(operator_id) |
| 105 | + fee_limit.add_custom_fee(limit_fee) |
| 106 | + |
| 107 | + print( |
| 108 | + f"Setting fee limit: max {limit_fee.amount} tinybars " |
| 109 | + f"in custom fees for payer {operator_id}" |
| 110 | + ) |
| 111 | + |
| 112 | + try: |
| 113 | + submit_tx = TopicMessageSubmitTransaction() |
| 114 | + submit_tx.set_topic_id(topic_id) |
| 115 | + submit_tx.set_message("Hello Hedera with Fee Limits!") |
| 116 | + |
| 117 | + # Ensure the base transaction fee is high enough to cover processing |
| 118 | + submit_tx.transaction_fee = Hbar(5).to_tinybars() |
| 119 | + |
| 120 | + # Attach the custom fee limit to the transaction |
| 121 | + submit_tx.set_custom_fee_limits([fee_limit]) |
| 122 | + |
| 123 | + submit_receipt = submit_tx.execute(client) |
| 124 | + |
| 125 | + print("Message submitted successfully!") |
| 126 | + print(f"Transaction status: {submit_receipt.status}") |
| 127 | + except Exception as e: # noqa: BLE001 |
| 128 | + print(f"Transaction failed: {e}") |
| 129 | + |
| 130 | + |
| 131 | +def main() -> None: |
| 132 | + client, operator_id = setup_client() |
| 133 | + |
| 134 | + topic_id = create_revenue_generating_topic(client, operator_id) |
| 135 | + if topic_id is None: |
| 136 | + return |
| 137 | + |
| 138 | + submit_message_with_custom_fee_limit(client, topic_id, operator_id) |
| 139 | + |
| 140 | + print("\nExample complete.") |
| 141 | + |
| 142 | + |
| 143 | +if __name__ == "__main__": |
| 144 | + main() |
0 commit comments