Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
- Update changelog workflow to trigger automatically on pull requests instead of manual dispatch (#1567)

### Fixed
- Aligned token freeze example filename references and improved error handling by catching broader exceptions with clearer messages. (#1412)
- Fixed jq syntax in bot-office-hours.sh (#1502)
- Prevented linkbot from commenting on or auto-closing bot-authored pull requests. (#1516)
- Respect `dry-run` input in `bot-community-calls.yml` workflow (#1425)
Expand Down
67 changes: 37 additions & 30 deletions examples/tokens/token_freeze_transaction.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# uv run examples/tokens/token_freeze.py
# python examples/tokens/token_freeze.py
"""
Creates a freezeable token and demonstrates freezing and unfreezing
the token for the operator (treasury) account.

uv run examples/tokens/token_freeze_transaction.py
python examples/tokens/token_freeze_transaction.py
"""

import os
import sys

Expand All @@ -19,12 +19,17 @@
)



def setup_client():
"""Setup client from environment variables"""
client = Client.from_env()
operator_id = client.operator_account_id
operator_key = client.operator_private_key

print(f"Network: {client.network.network}")
print(f"Client set up with operator id {client.operator_account_id}")
return client
print(f"Client set up with operator id {operator_id}")

return client, operator_id, operator_key


def generate_freeze_key():
"""Generate a Freeze Key"""
Expand All @@ -38,59 +43,61 @@ def create_freezeable_token(client, operator_id, operator_key):
"""Create a token with the freeze key"""
freeze_key = generate_freeze_key()
print("\nSTEP 2: Creating a new freezeable token...")

try:
tx = (
TokenCreateTransaction()
.set_token_name("Freezeable Token")
.set_token_symbol("FRZ")
.set_initial_supply(1000)
.set_treasury_account_id(operator_id)
.set_freeze_key(freeze_key) # <-- THE FIX: Pass the private key directly
.set_freeze_key(freeze_key)
)

# Freeze, sign with BOTH operator and the new freeze key, then execute
receipt = (
tx.freeze_with(client)
.sign(operator_key)
.sign(freeze_key) # The new freeze key must sign to give consent
.sign(freeze_key)
.execute(client)
)

token_id = receipt.token_id
print(f"✅ Success! Created token with ID: {token_id}")

return freeze_key, token_id, client, operator_id, operator_key
except RuntimeError as e:

except Exception as e:
print(f"❌ Error creating token: {e}")
sys.exit(1)


def freeze_token(token_id, client, operator_id, freeze_key):
"""
Freeze the token for the operator account.
"""
"""Freeze the token for the operator account"""
print(f"\nSTEP 3: Freezing token {token_id} for operator account {operator_id}...")

try:
receipt = (
TokenFreezeTransaction()
.set_token_id(token_id)
.set_account_id(operator_id) # Target the operator account
.set_account_id(operator_id)
.freeze_with(client)
.sign(freeze_key) # Must be signed by the freeze key
.sign(freeze_key)
.execute(client)
)

print(
f"✅ Success! Token freeze complete. Status: {ResponseCode(receipt.status).name}"
)

except RuntimeError as e:
except Exception as e:
print(f"❌ Error freezing token: {e}")
sys.exit(1)


def verify_freeze(token_id, client, operator_id, operator_key):
"""Attempt a token transfer to confirm the account
cannot perform the operation while frozen."""
"""Attempt a token transfer to confirm the account is frozen"""
print("\nVerifying freeze: Attempting token transfer...")
# Try to transfer 1 token from operator to itself (should fail if frozen)

try:
transfer_receipt = (
TransferTransaction()
Expand All @@ -100,9 +107,9 @@ def verify_freeze(token_id, client, operator_id, operator_key):
.sign(operator_key)
.execute(client)
)
# Handle status code 165 (ACCOUNT_FROZEN_FOR_TOKEN) and print a clear message
status_code = transfer_receipt.status
status_name = ResponseCode(status_code).name

status_name = ResponseCode(transfer_receipt.status).name

if status_name in ["ACCOUNT_FROZEN_FOR_TOKEN", "ACCOUNT_FROZEN"]:
print(
f"✅ Verified: Transfer blocked as expected due to freeze. Status: {status_name}"
Expand All @@ -112,28 +119,28 @@ def verify_freeze(token_id, client, operator_id, operator_key):
"❌ Error: Transfer succeeded, but should have failed because the account is frozen."
)
else:
print(f"❌ Unexpected: Transfer result. Status: {status_name}")
except RuntimeError as e:
print(f"✅ Verified: Transfer failed as expected due to freeze. Error: {e}")
print(f"❌ Unexpected transfer result. Status: {status_name}")

except Exception as e:
print(f"❌ Error during transfer verification: {e}")
sys.exit(1)


def main():
"""
1. Create a freezeable token with a freeze key.
2. Freeze the token for the operator account using the freeze key.
3. Attempt a token transfer to verify the freeze (should fail).
4. Return token details for further operations."""

client = setup_client()
operator_id = client.operator_account_id
operator_key = client.operator_private_key
"""
client, operator_id, operator_key = setup_client()

freeze_key, token_id, client, operator_id, operator_key = create_freezeable_token(
client, operator_id, operator_key
)

freeze_token(token_id, client, operator_id, freeze_key)
verify_freeze(token_id, client, operator_id, operator_key)


if __name__ == "__main__":
main()
main()