Skip to content

Commit 1abfe97

Browse files
committed
feat: TokenPause Transaction
Signed-off-by: exploreriii <[email protected]>
1 parent 9b827e7 commit 1abfe97

15 files changed

+733
-9
lines changed

examples/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ You can choose either syntax or even mix both styles in your projects.
2828
- [Rejecting a Token](#rejecting-a-token)
2929
- [Rejecting a Non-Fungible Token](#rejecting-a-non-fungible-token)
3030
- [Token Update NFTs](#token-update-nfts)
31+
- [Pausing a Token](#pausing-a-token)
3132
- [Querying NFT Info](#querying-nft-info)
3233
- [Querying Fungible Token Info](#querying-fungible-token-info)
3334
- [HBAR Transactions](#hbar-transactions)
@@ -479,6 +480,30 @@ transaction.execute(client)
479480
480481
```
481482

483+
### Pausing a Token
484+
485+
#### Pythonic Syntax:
486+
```
487+
transaction = TokenPauseTransaction(
488+
token_id=token_id
489+
).freeze_with(client)
490+
491+
transaction.sign(pause_key)
492+
transaction.execute(client)
493+
494+
```
495+
#### Method Chaining:
496+
```
497+
transaction = (
498+
TokenPauseTransaction()
499+
.set_token_id(token_id)
500+
.freeze_with(client)
501+
.sign(pause_key)
502+
)
503+
transaction.execute(client)
504+
505+
```
506+
482507
### Querying NFT Info
483508

484509
#### Pythonic Syntax:

examples/token_create_fungible_finite.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
99
Required environment variables:
1010
- OPERATOR_ID, OPERATOR_KEY (mandatory)
11-
- ADMIN_KEY, SUPPLY_KEY, FREEZE_KEY (optional)
11+
- ADMIN_KEY, SUPPLY_KEY, FREEZE_KEY, PAUSE_KEY (optional)
1212
1313
Dependencies:
1414
- dotenv
@@ -47,6 +47,7 @@ def create_token_fungible_finite():
4747
admin_key = PrivateKey.from_string_ed25519(os.getenv('ADMIN_KEY'))# Optional
4848
supply_key = PrivateKey.from_string_ed25519(os.getenv('SUPPLY_KEY'))# Optional
4949
freeze_key = PrivateKey.from_string_ed25519(os.getenv('FREEZE_KEY'))# Optional
50+
pause_key = PrivateKey.from_string_ed25519(os.getenv('PAUSE_KEY'))# Optional
5051

5152
# Set the operator for the client
5253
client.set_operator(operator_id, operator_key)
@@ -66,6 +67,7 @@ def create_token_fungible_finite():
6667
.set_admin_key(admin_key) # Optional
6768
.set_supply_key(supply_key) # Optional
6869
.set_freeze_key(freeze_key) # Optional
70+
.set_pause_key(pause_key) # Optional
6971
.freeze_with(client) # Freeze the transaction. Returns self so we can sign.
7072
)
7173

examples/token_create_fungible_infinite.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
99
Required environment variables:
1010
- OPERATOR_ID, OPERATOR_KEY (mandatory)
11-
- ADMIN_KEY, SUPPLY_KEY, FREEZE_KEY (optional)
11+
- ADMIN_KEY, SUPPLY_KEY, FREEZE_KEY, PAUSE_KEY (optional)
1212
1313
Dependencies:
1414
- dotenv
@@ -47,6 +47,7 @@ def create_token_fungible_infinite():
4747
admin_key = PrivateKey.from_string_ed25519(os.getenv('ADMIN_KEY'))# Optional
4848
supply_key = PrivateKey.from_string_ed25519(os.getenv('SUPPLY_KEY'))# Optional
4949
freeze_key = PrivateKey.from_string_ed25519(os.getenv('FREEZE_KEY'))# Optional
50+
pause_key = PrivateKey.from_string_ed25519(os.getenv('PAUSE_KEY'))# Optional
5051

5152
# Set the operator for the client
5253
client.set_operator(operator_id, operator_key)
@@ -66,6 +67,7 @@ def create_token_fungible_infinite():
6667
.set_admin_key(admin_key) # Optional
6768
.set_supply_key(supply_key) # Optional
6869
.set_freeze_key(freeze_key) # Optional
70+
.set_pause_key(pause_key) # Optional
6971
.freeze_with(client) # Freeze the transaction. Returns self so we can sign.
7072
)
7173

examples/token_create_nft_finite.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
99
Required environment variables:
1010
- OPERATOR_ID, OPERATOR_KEY (mandatory)
11-
- ADMIN_KEY, SUPPLY_KEY, FREEZE_KEY (optional)
11+
- ADMIN_KEY, SUPPLY_KEY, FREEZE_KEY, PAUSE_KEY (optional)
1212
1313
Dependencies:
1414
- dotenv
@@ -47,6 +47,7 @@ def create_token_nft():
4747
admin_key = PrivateKey.from_string_ed25519(os.getenv('ADMIN_KEY'))# Optional
4848
supply_key = PrivateKey.from_string_ed25519(os.getenv('SUPPLY_KEY'))# Optional
4949
freeze_key = PrivateKey.from_string_ed25519(os.getenv('FREEZE_KEY'))# Optional
50+
pause_key = PrivateKey.from_string_ed25519(os.getenv('PAUSE_KEY'))# Optional
5051

5152
# Set the operator for the client
5253
client.set_operator(operator_id, operator_key)
@@ -66,6 +67,7 @@ def create_token_nft():
6667
.set_admin_key(admin_key) # Optional
6768
.set_supply_key(supply_key) # Optional
6869
.set_freeze_key(freeze_key) # Optional
70+
.set_pause_key(pause_key) # Optional
6971
.freeze_with(client) # Freeze the transaction. Returns self so we can sign.
7072
)
7173

examples/token_create_nft_infinite.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
99
Required environment variables:
1010
- OPERATOR_ID, OPERATOR_KEY (mandatory)
11-
- ADMIN_KEY, SUPPLY_KEY, FREEZE_KEY (optional)
11+
- ADMIN_KEY, SUPPLY_KEY, FREEZE_KEY, PAUSE_KEY (optional)
1212
1313
Dependencies:
1414
- dotenv
@@ -47,6 +47,7 @@ def create_token_nft_infinite():
4747
admin_key = PrivateKey.from_string_ed25519(os.getenv('ADMIN_KEY'))# Optional
4848
supply_key = PrivateKey.from_string_ed25519(os.getenv('SUPPLY_KEY'))# Optional
4949
freeze_key = PrivateKey.from_string_ed25519(os.getenv('FREEZE_KEY'))# Optional
50+
pause_key = PrivateKey.from_string_ed25519(os.getenv('PAUSE_KEY'))# Optional
5051

5152
# Set the operator for the client
5253
client.set_operator(operator_id, operator_key)
@@ -66,6 +67,7 @@ def create_token_nft_infinite():
6667
.set_admin_key(admin_key) # Optional
6768
.set_supply_key(supply_key) # Optional
6869
.set_freeze_key(freeze_key) # Optional
70+
.set_pause_key(pause_key) # Optional
6971
.freeze_with(client) # Freeze the transaction. Returns self so we can sign.
7072
)
7173

examples/token_pause.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import os
2+
import sys
3+
from dotenv import load_dotenv
4+
5+
from hiero_sdk_python import (
6+
Client,
7+
AccountId,
8+
PrivateKey,
9+
Network
10+
)
11+
from hiero_sdk_python.response_code import ResponseCode
12+
from hiero_sdk_python.tokens.supply_type import SupplyType
13+
from hiero_sdk_python.tokens.token_type import TokenType
14+
from hiero_sdk_python.tokens.token_create_transaction import TokenCreateTransaction
15+
from hiero_sdk_python.tokens.token_pause_transaction import TokenPauseTransaction
16+
from hiero_sdk_python.tokens.token_delete_transaction import TokenDeleteTransaction
17+
from hiero_sdk_python.query.token_info_query import TokenInfoQuery
18+
19+
load_dotenv()
20+
21+
def setup_client():
22+
"""Initialize and set up the client with operator account"""
23+
# Initialize network and client
24+
network = Network(network='testnet')
25+
client = Client(network)
26+
27+
# Set up operator account
28+
operator_id = AccountId.from_string(os.getenv('OPERATOR_ID'))
29+
operator_key = PrivateKey.from_string(os.getenv('OPERATOR_KEY'))
30+
client.set_operator(operator_id, operator_key)
31+
32+
return client, operator_id, operator_key
33+
34+
def assert_success(receipt, action: str):
35+
"""
36+
Verify that a transaction or query succeeded, else raise.
37+
38+
Args:
39+
receipt: The receipt object returned by `execute(client)` on a Transaction or Query.
40+
action (str): A short description of the attempted operation (e.g. "Token creation").
41+
42+
Raises:
43+
RuntimeError: If the receipt’s status is not `ResponseCode.SUCCESS`, with a message
44+
indicating which action failed and the status name.
45+
"""
46+
if receipt.status != ResponseCode.SUCCESS:
47+
name = ResponseCode.get_name(receipt.status)
48+
raise RuntimeError(f"{action!r} failed with status {name}")
49+
50+
def create_token(client, operator_id, admin_key, pause_key):
51+
"""Create a fungible token"""
52+
# Create fungible token
53+
create_token_transaction = (
54+
TokenCreateTransaction()
55+
.set_token_name("Token123")
56+
.set_token_symbol("T123")
57+
.set_decimals(2)
58+
.set_initial_supply(10)
59+
.set_treasury_account_id(operator_id)
60+
.set_token_type(TokenType.FUNGIBLE_COMMON)
61+
.set_supply_type(SupplyType.FINITE)
62+
.set_max_supply(100)
63+
.set_admin_key(admin_key) # Required for token delete
64+
.set_pause_key(pause_key) # Required for pausing tokens
65+
.freeze_with(client)
66+
)
67+
68+
receipt = create_token_transaction.execute(client)
69+
assert_success(receipt, "Token creation")
70+
71+
# Get token ID from receipt
72+
token_id = receipt.tokenId
73+
print(f"Token created with ID: {token_id}")
74+
75+
return token_id
76+
77+
def pause_token(client, token_id, pause_key):
78+
"""Pause token"""
79+
# Note: This requires the pause key that was specified during token creation
80+
pause_transaction = (
81+
TokenPauseTransaction()
82+
.set_token_id(token_id)
83+
.freeze_with(client)
84+
.sign(pause_key)
85+
)
86+
87+
receipt = pause_transaction.execute(client)
88+
assert_success(receipt, "Token pause")
89+
90+
print(f"Successfully paused token {token_id}")
91+
92+
def check_pause_status(client, token_id):
93+
"""
94+
Query and print the current paused/unpaused status of a token.
95+
"""
96+
info = TokenInfoQuery().set_token_id(token_id).execute(client)
97+
print(f"Token status is now: {info.pause_status.name}")
98+
99+
def delete_token(client, token_id, admin_key):
100+
"""Delete token"""
101+
# Note: This requires the admin key that was specified during token creation
102+
delete_transaction = (
103+
TokenDeleteTransaction()
104+
.set_token_id(token_id)
105+
.freeze_with(client)
106+
.sign(admin_key)
107+
)
108+
109+
receipt = delete_transaction.execute(client)
110+
assert_success(receipt, "Token delete")
111+
112+
print(f"Successfully deleted token {token_id}")
113+
114+
def token_pause():
115+
"""
116+
Demonstrates the token pause functionality by:
117+
1. Creating a fungible token with pause and delete capability
118+
2. Pausing the token
119+
3. Verifying pause status
120+
4. Attempting (and failing) to delete the paused token because it is paused
121+
"""
122+
client, operator_id, operator_key = setup_client()
123+
124+
pause_key = operator_key # for token pause
125+
admin_key = operator_key # for token delete
126+
127+
# Create token with required keys for pause and delete.
128+
token_id = create_token(client, operator_id, admin_key, pause_key)
129+
130+
# Pause token using pause key – should succeed
131+
pause_token(client, token_id, pause_key)
132+
133+
# Verify it is paused
134+
check_pause_status(client, token_id)
135+
136+
# Try deleting token with admin key – should fail with TOKEN_IS_PAUSED
137+
try:
138+
delete_token(client, token_id, admin_key)
139+
print("❌ Whoops, delete succeeded—but it should have failed on a paused token!")
140+
except RuntimeError as e:
141+
print(f"✅ Unable to delete token as expected as it is paused: {e}")
142+
143+
if __name__ == "__main__":
144+
token_pause()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from .token_create_transaction import TokenCreateTransaction
2+
from .token_pause_transaction import TokenPauseTransaction
3+
from .token_id import TokenId
4+
from .token_type import TokenType
5+
from .supply_type import SupplyType

src/hiero_sdk_python/tokens/token_create_transaction.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ class TokenKeys:
178178
supply_key: The supply key for the token to mint and burn.
179179
freeze_key: The freeze key for the token to freeze and unfreeze.
180180
wipe_key: The wipe key for the token to wipe tokens from an account.
181+
pause_key: The pause key for the token to be paused.
181182
metadata_key: The metadata key for the token to update NFT metadata.
182183
"""
183184

@@ -186,6 +187,7 @@ class TokenKeys:
186187
freeze_key: Optional[PrivateKey] = None
187188
wipe_key: Optional[PrivateKey] = None
188189
metadata_key: Optional[PrivateKey] = None
190+
pause_key: Optional[PrivateKey] = None
189191

190192
class TokenCreateTransaction(Transaction):
191193
"""
@@ -327,6 +329,11 @@ def set_metadata_key(self, key):
327329
self._keys.metadata_key = key
328330
return self
329331

332+
def set_pause_key(self, key):
333+
self._require_not_frozen()
334+
self._keys.pause_key = key
335+
return self
336+
330337
def build_transaction_body(self):
331338
"""
332339
Builds and returns the protobuf transaction body for token creation.
@@ -369,6 +376,11 @@ def build_transaction_body(self):
369376
metadata_public_key_bytes = self._keys.metadata_key.public_key().to_bytes_raw()
370377
metadata_key_proto = basic_types_pb2.Key(ed25519=metadata_public_key_bytes)
371378

379+
pause_key_proto = None
380+
if self._keys.pause_key:
381+
pause_public_key_bytes = self._keys.pause_key.public_key().to_bytes_raw()
382+
pause_key_proto = basic_types_pb2.Key(ed25519=pause_public_key_bytes)
383+
372384
# Ensure token type is correctly set with default to fungible
373385
if self._token_params.token_type is None:
374386
token_type_value = 0 # default FUNGIBLE_COMMON
@@ -400,7 +412,8 @@ def build_transaction_body(self):
400412
supplyKey=supply_key_proto,
401413
freezeKey=freeze_key_proto,
402414
wipeKey=wipe_key_proto,
403-
metadata_key=metadata_key_proto
415+
metadata_key=metadata_key_proto,
416+
pause_key=pause_key_proto,
404417
)
405418
# Build the base transaction body and attach the token creation details
406419
transaction_body = self.build_base_transaction_body()

src/hiero_sdk_python/tokens/token_info.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ def set_auto_renew_period(self, autoRenewPeriod: Duration):
7575
def set_expiry(self, expiry: Timestamp):
7676
self.expiry = expiry
7777

78-
def set_pause_key(self, pauseKey: PublicKey):
79-
self.pause_key = pauseKey
78+
def set_pause_key(self, pause_key: PublicKey):
79+
self.pause_key = pause_key
8080

8181
def set_pause_status(self, pauseStatus: TokenPauseStatus):
8282
self.pause_status = pauseStatus

0 commit comments

Comments
 (0)