-
Notifications
You must be signed in to change notification settings - Fork 92
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
Open
undefinedIsMyLife
wants to merge
13
commits into
hiero-ledger:main
Choose a base branch
from
undefinedIsMyLife:example-token-pause-key-clean
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 11 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
e269f57
feat(examples): add pause key example for token create
undefinedIsMyLife 9b46d89
fix(example): remove unsupported bonus pause key removal logic
undefinedIsMyLife 809d038
chore(example): remove unsupported bonus pause-key section
undefinedIsMyLife 15bf91b
fix(example): improve receipt handling per review feedback
undefinedIsMyLife f409d91
fix(example): receipt checks and cleanup
undefinedIsMyLife 6b3188b
fix(changelog): restore removed lines and update entry
undefinedIsMyLife e90bbb1
fix(example): final reviewer adjustments
undefinedIsMyLife 58f6188
fix(changelog): place pause-key example correctly under Unreleased
undefinedIsMyLife 82c3a30
fix(changelog): correct path and PR number for pause key example (#833)
undefinedIsMyLife 119add0
chore(changelog): temporarily remove pause-key entry
undefinedIsMyLife fd80cc5
chore(changelog): restore pause-key example entry (#833)
undefinedIsMyLife e5d5b2b
chore(changelog): remove pause-key line as requested
undefinedIsMyLife c818c98
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 @@ | ||
| """ | ||
exploreriii marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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() | ||
Oops, something went wrong.
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.