-
Notifications
You must be signed in to change notification settings - Fork 93
feat(examples): add pause key example for token create #833
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
exploreriii
merged 9 commits into
hiero-ledger:main
from
undefinedIsMyLife:example-token-pause-key-clean
Dec 3, 2025
+263
−2
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
61ee06a
chore: prepare for rebase
undefinedIsMyLife 573a36f
fix(example): remove unsupported bonus pause key removal logic
undefinedIsMyLife fd43b04
chore(example): remove unsupported bonus pause-key section
undefinedIsMyLife e0fde7e
fix(example): improve receipt handling per review feedback
undefinedIsMyLife 1e76321
fix(example): receipt checks and cleanup
undefinedIsMyLife a9fb700
fix(changelog): restore removed lines and update entry
undefinedIsMyLife 374fa70
fix(example): final reviewer adjustments
undefinedIsMyLife 9e791ce
fix(changelog): correct path and PR number for pause key example (#833)
undefinedIsMyLife 47db691
Merge branch 'main' into example-token-pause-key-clean
undefinedIsMyLife File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,262 @@ | ||
| """ | ||
| This example demonstrates the pause key capabilities for token management using the Hiero Python SDK. | ||
|
|
||
| It shows: | ||
| 1. Creating a token *without* a pause key | ||
| 2. Attempting to pause it — expected failure | ||
| 3. Creating a token *with* a pause key | ||
| 4. Successfully pausing and unpausing the token | ||
| 5. Demonstrating that transfers fail while the token is paused | ||
|
|
||
| Required environment variables: | ||
| - OPERATOR_ID | ||
| - OPERATOR_KEY | ||
|
|
||
| Usage: | ||
| uv run examples/token_create_transaction_pause_key.py | ||
| """ | ||
|
|
||
| import os | ||
| import sys | ||
| from dotenv import load_dotenv | ||
|
|
||
| from hiero_sdk_python import ( | ||
| Client, | ||
| AccountId, | ||
| PrivateKey, | ||
| Network, | ||
| TokenCreateTransaction, | ||
| TokenPauseTransaction, | ||
| TokenUnpauseTransaction, | ||
| TokenUpdateTransaction, | ||
| TokenInfoQuery, | ||
| TransferTransaction, | ||
| AccountCreateTransaction, | ||
| Hbar, | ||
| ) | ||
|
|
||
| from hiero_sdk_python.response_code import ResponseCode | ||
| from hiero_sdk_python.tokens.token_type import TokenType | ||
| from hiero_sdk_python.tokens.supply_type import SupplyType | ||
|
|
||
| load_dotenv() | ||
| network_name = os.getenv("NETWORK", "testnet").lower() | ||
|
|
||
|
|
||
| # ------------------------------------------------------- | ||
| # CLIENT SETUP | ||
| # ------------------------------------------------------- | ||
| def setup_client(): | ||
| """Create client from environment variables""" | ||
| network = Network(network_name) | ||
| print(f"Connecting to Hedera {network_name} network...") | ||
| client = Client(network) | ||
|
|
||
| try: | ||
| operator_id = AccountId.from_string(os.getenv("OPERATOR_ID", "")) | ||
| operator_key = PrivateKey.from_string(os.getenv("OPERATOR_KEY", "")) | ||
| client.set_operator(operator_id, operator_key) | ||
| print(f"Client ready — Operator: {client.operator_account_id}\n") | ||
| return client, operator_id, operator_key | ||
|
|
||
| except Exception: | ||
| print("❌ ERROR: Invalid OPERATOR_ID or OPERATOR_KEY in .env") | ||
| sys.exit(1) | ||
|
|
||
|
|
||
| # ------------------------------------------------------- | ||
| # TOKEN CREATION (NO PAUSE KEY) | ||
| # ------------------------------------------------------- | ||
| def create_token_without_pause_key(client, operator_id, operator_key): | ||
| print("🔹 Creating token WITHOUT pause key...") | ||
|
|
||
| tx = ( | ||
| TokenCreateTransaction() | ||
| .set_token_name("PauseKeyMissing") | ||
| .set_token_symbol("NOPAUSE") | ||
| .set_decimals(0) | ||
| .set_initial_supply(100) | ||
| .set_treasury_account_id(operator_id) | ||
| .set_token_type(TokenType.FUNGIBLE_COMMON) | ||
| .set_supply_type(SupplyType.INFINITE) | ||
| .freeze_with(client) | ||
| .sign(operator_key) | ||
| ) | ||
|
|
||
| receipt = tx.execute(client) | ||
| if receipt.status != ResponseCode.SUCCESS: | ||
| print("❌ Token creation failed") | ||
| sys.exit(1) | ||
|
|
||
| token_id = receipt.token_id | ||
| print(f"✅ Token created WITHOUT pause key → {token_id}\n") | ||
| return token_id | ||
|
|
||
|
|
||
| def attempt_pause_should_fail(client, token_id, operator_key): | ||
| print("🔹 Attempting to pause token WITHOUT a pause key... (expected failure)") | ||
|
|
||
| tx = ( | ||
| TokenPauseTransaction() | ||
| .set_token_id(token_id) | ||
| .freeze_with(client) | ||
| .sign(operator_key) | ||
| ) | ||
|
|
||
| receipt = tx.execute(client) | ||
|
|
||
| if receipt.status == ResponseCode.TOKEN_HAS_NO_PAUSE_KEY: | ||
| print("✅ Expected failure: token cannot be paused because no pause key exists.\n") | ||
| else: | ||
| print(f"❌ Unexpected status: {ResponseCode(receipt.status).name}\n") | ||
|
|
||
|
|
||
| # ------------------------------------------------------- | ||
| # TOKEN CREATION WITH PAUSE KEY | ||
| # ------------------------------------------------------- | ||
| def create_token_with_pause_key(client, operator_id, operator_key, pause_key): | ||
| print("🔹 Creating token WITH pause key...") | ||
|
|
||
| tx = ( | ||
| TokenCreateTransaction() | ||
| .set_token_name("PauseKeyDemo") | ||
| .set_token_symbol("PAUSE") | ||
| .set_decimals(0) | ||
| .set_initial_supply(100) | ||
| .set_treasury_account_id(operator_id) | ||
| .set_token_type(TokenType.FUNGIBLE_COMMON) | ||
| .set_supply_type(SupplyType.INFINITE) | ||
| .set_pause_key(pause_key) # NEW | ||
| .freeze_with(client) | ||
| ) | ||
|
|
||
| tx.sign(operator_key) | ||
| tx.sign(pause_key) | ||
|
|
||
| receipt = tx.execute(client) | ||
| if receipt.status != ResponseCode.SUCCESS: | ||
| print("❌ Token creation failed") | ||
| sys.exit(1) | ||
|
|
||
| token_id = receipt.token_id | ||
| print(f"✅ Token created WITH pause key → {token_id}\n") | ||
| return token_id | ||
|
|
||
|
|
||
| # ------------------------------------------------------- | ||
| # PAUSE / UNPAUSE DEMO | ||
| # ------------------------------------------------------- | ||
| def pause_token(client, token_id, pause_key): | ||
| print("🔹 Pausing token...") | ||
|
|
||
| tx = ( | ||
| TokenPauseTransaction() | ||
| .set_token_id(token_id) | ||
| .freeze_with(client) | ||
| .sign(pause_key) | ||
| ) | ||
|
|
||
| receipt = tx.execute(client) | ||
| if receipt.status == ResponseCode.SUCCESS: | ||
| print("✅ Token paused successfully!\n") | ||
| else: | ||
| print(f"❌ Pause failed: {ResponseCode(receipt.status).name}") | ||
|
|
||
|
|
||
| def unpause_token(client, token_id, pause_key): | ||
| print("🔹 Unpausing token...") | ||
|
|
||
| tx = ( | ||
| TokenUnpauseTransaction() | ||
| .set_token_id(token_id) | ||
| .freeze_with(client) | ||
| .sign(pause_key) | ||
| ) | ||
|
|
||
| receipt = tx.execute(client) | ||
| if receipt.status == ResponseCode.SUCCESS: | ||
| print("✅ Token unpaused successfully!\n") | ||
| else: | ||
| print(f"❌ Unpause failed: {ResponseCode(receipt.status).name}") | ||
|
|
||
|
|
||
| # ------------------------------------------------------- | ||
| # TRANSFERS WHILE PAUSED SHOULD FAIL | ||
| # ------------------------------------------------------- | ||
| def create_temp_account(client, operator_key): | ||
| """Creates a small account for transfer testing.""" | ||
| new_key = PrivateKey.generate_ed25519() | ||
| pub_key = new_key.public_key() | ||
|
|
||
| print("🔹 Creating a temporary recipient account...") | ||
|
|
||
| tx = ( | ||
| AccountCreateTransaction() | ||
| .set_key(pub_key) # MUST use public key | ||
| .set_initial_balance(Hbar.from_tinybars(1000)) | ||
| .freeze_with(client) | ||
| .sign(operator_key) | ||
| ) | ||
|
|
||
| receipt = tx.execute(client) | ||
|
|
||
| if receipt.status != ResponseCode.SUCCESS: | ||
| print(f"❌ Failed to create temp account: {ResponseCode(receipt.status).name}") | ||
| sys.exit(1) | ||
|
|
||
| account_id = receipt.account_id | ||
| print(f"✅ Temp account created: {account_id}\n") | ||
exploreriii marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return account_id, new_key | ||
|
|
||
|
|
||
|
|
||
| def test_transfer_while_paused(client, operator_id, operator_key, recipient_id, token_id): | ||
| print("🔹 Attempting transfer WHILE token is paused (expected failure)...") | ||
|
|
||
| tx = ( | ||
| TransferTransaction() | ||
| .add_token_transfer(token_id, operator_id, -10) | ||
| .add_token_transfer(token_id, recipient_id, 10) | ||
| .freeze_with(client) | ||
| .sign(operator_key) | ||
| ) | ||
|
|
||
| receipt = tx.execute(client) | ||
|
|
||
| if receipt.status == ResponseCode.TOKEN_IS_PAUSED: | ||
| print("✅ Transfer failed as expected: TOKEN_IS_PAUSED\n") | ||
| else: | ||
| print(f"⚠️ Unexpected status: {ResponseCode(receipt.status).name}\n") | ||
|
|
||
| # ------------------------------------------------------- | ||
| # MAIN | ||
| # ------------------------------------------------------- | ||
| def main(): | ||
| client, operator_id, operator_key = setup_client() | ||
|
|
||
| print("\n==================== PART 1 — NO PAUSE KEY ====================\n") | ||
| token_no_pause = create_token_without_pause_key(client, operator_id, operator_key) | ||
| attempt_pause_should_fail(client, token_no_pause, operator_key) | ||
|
|
||
| print("\n==================== PART 2 — WITH PAUSE KEY ====================\n") | ||
| pause_key = PrivateKey.generate_ed25519() | ||
|
|
||
| token_with_pause = create_token_with_pause_key( | ||
| client, operator_id, operator_key, pause_key | ||
| ) | ||
|
|
||
| pause_token(client, token_with_pause, pause_key) | ||
|
|
||
| recipient_id, _ = create_temp_account(client, operator_key) | ||
| test_transfer_while_paused( | ||
| client, operator_id, operator_key, recipient_id, token_with_pause | ||
| ) | ||
|
|
||
| unpause_token(client, token_with_pause, pause_key) | ||
|
|
||
| print("\n🎉 Pause key demonstration completed!") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.