Skip to content

Commit 2b7c1bb

Browse files
committed
feat: very rough notes (temp hold while other transactions finish)
1 parent 70de9a5 commit 2b7c1bb

File tree

9 files changed

+532
-10
lines changed

9 files changed

+532
-10
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ Create a .env file in the root of your project with the following (replace with
9797
OPERATOR_ID=0.0.1234xx
9898
OPERATOR_KEY=302e020100300506032b657004220420...
9999
ADMIN_KEY=302a300506032b65700321009308ecfdf...
100-
SUPPLY_KEY =302a300506032b6570032100c5e4af5..."
100+
SUPPLY_KEY =302a300506032b6570032100c5e4af5...
101101
FREEZE_KEY=302a300306072b65700321009308ecfdf...
102+
PAUSE_KEY=302a300306072b6570032100af12b3c4d...
102103
RECIPIENT_ID=0.0.789xx
103104
TOKEN_ID=0.0.100xx
104105
TOPIC_ID=0.0.200xx
@@ -134,6 +135,7 @@ Token dissociation successful.
134135
Token minting successful.
135136
Token transfer successful.
136137
Token freeze successful.
138+
Token pause succesful.
137139
Token deletion successful.
138140
Topic creation successful.
139141
Topic Message submitted.

examples/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ You can choose either syntax or even mix both styles in your projects.
2020
- [Associating a Token](#associating-a-token)
2121
- [Dissociating a Token](#dissociating-a-token)
2222
- [Transferring Tokens](#transferring-tokens)
23+
- [Pausing a Token](#pausing-a-token)
2324
- [Deleting a Token](#deleting-a-token)
2425
- [Freezing a Token](#freezing-a-token)
2526
- [HBAR Transactions](#hbar-transactions)
@@ -256,6 +257,31 @@ transaction.execute(client)
256257
transaction.execute(client)
257258
```
258259

260+
### Pausing a Token
261+
262+
#### Pythonic Syntax:
263+
```
264+
transaction = TokenPauseTransaction(
265+
token_id=token_id
266+
).freeze_with(client)
267+
268+
transaction.sign(pause_key) # Pause key must have been set during token creation
269+
transaction.sign(operator_key)
270+
transaction.execute(client)
271+
```
272+
#### Method Chaining:
273+
```
274+
transaction = (
275+
TokenPauseTransaction()
276+
.set_token_id(token_id)
277+
.freeze_with(client)
278+
)
279+
280+
transaction.sign(pause_key) # Pause key must have been set during token creation
281+
transaction.sign(operator_key)
282+
transaction.execute(client)
283+
```
284+
259285
### Deleting a Token
260286

261287
#### Pythonic Syntax:

examples/token_create.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def create_token():
4646
admin_key = PrivateKey.from_string(os.getenv('ADMIN_KEY'))# Optional
4747
supply_key = PrivateKey.from_string(os.getenv('SUPPLY_KEY')) # Optional
4848
freeze_key = PrivateKey.from_string(os.getenv('FREEZE_KEY')) # Optional
49+
pause_key = PrivateKey.from_string(os.getenv('PAUSE_KEY')) # Optional
4950

5051
# Set the operator for the client
5152
client.set_operator(operator_id, operator_key)
@@ -63,6 +64,7 @@ def create_token():
6364
.set_admin_key(admin_key) # Optional
6465
.set_supply_key(supply_key) # Optional
6566
.set_freeze_key(freeze_key) # Optional
67+
.set_pause_key(pause_key) # Optional
6668
.freeze_with(client) # Freeze the transaction. Returns self so we can sign.
6769
.sign(operator_key) # Required signature of treasury account
6870
.sign(admin_key) if admin_key else None # Only sign if admin_key is present. No need to sign with the supply or freeze keys to create the token.

examples/token_pause.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"""
2+
pause_token.py
3+
4+
This script demonstrates how to pause an existing token.
5+
6+
It:
7+
1. Loads environment variables for operator and pause key
8+
2. Sets up a client
9+
3. Pauses the token specified by TOKEN_ID
10+
4. Prints the result or error
11+
12+
Required environment variables:
13+
- OPERATOR_ID, OPERATOR_KEY (mandatory)
14+
- TOKEN_ID (the ID of the token to pause)
15+
- PAUSE_KEY (the key authorized to pause this token)
16+
17+
Dependencies:
18+
- dotenv
19+
- hiero_sdk_python
20+
"""
21+
22+
import os
23+
import sys
24+
from dotenv import load_dotenv
25+
26+
# Hiero SDK imports
27+
from hiero_sdk_python.client.network import Network
28+
from hiero_sdk_python.client.client import Client
29+
from hiero_sdk_python.account.account_id import AccountId
30+
from hiero_sdk_python.crypto.private_key import PrivateKey
31+
from hiero_sdk_python.tokens.token_id import TokenId
32+
from hiero_sdk_python.tokens.token_pause_transaction import TokenPauseTransaction
33+
from hiero_sdk_python.response_code import ResponseCode
34+
35+
load_dotenv()
36+
37+
38+
def pause_token():
39+
"""Function to pause a token."""
40+
41+
# Network Setup
42+
network = Network(network='testnet')
43+
client = Client(network)
44+
45+
# Operator credentials (must be present)
46+
operator_id = AccountId.from_string(os.getenv('OPERATOR_ID'))
47+
operator_key = PrivateKey.from_string(os.getenv('OPERATOR_KEY'))
48+
49+
# Required Pause Key
50+
pause_key = PrivateKey.from_string(os.getenv('PAUSE_KEY')) # Optional
51+
52+
# Set the operator for the client
53+
client.set_operator(operator_id, operator_key)
54+
55+
# Create the token pause transaction
56+
transaction = TokenPauseTransaction(token_id=token_id)
57+
58+
transaction.freeze_with(client)
59+
60+
# The operator (fee payer) signs first
61+
transaction.sign(operator_key)
62+
63+
# The pause key must sign
64+
transaction.sign(pause_key)
65+
66+
try:
67+
68+
# Execute the transaction and get the receipt
69+
receipt = transaction.execute(client)
70+
71+
if receipt and receipt.tokenId:
72+
print(f"Token paused with ID: {receipt.tokenId}")
73+
else:
74+
print("Token paused failed: Token ID not returned in receipt.")
75+
sys.exit(1)
76+
77+
except Exception as e:
78+
print(f"Token paused failed: {str(e)}")
79+
sys.exit(1)
80+
81+
if __name__ == "__main__":
82+
pause_token()

src/hiero_sdk_python/tokens/token_create_transaction.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,13 @@ class TokenKeys:
146146
admin_key: The admin key for the token to update and delete.
147147
supply_key: The supply key for the token to mint and burn.
148148
freeze_key: The freeze key for the token to freeze and unfreeze.
149+
pause_key: The pause key for the token to pause and unpause.
149150
"""
150151

151152
admin_key: Optional[PrivateKey] = None
152153
supply_key: Optional[PrivateKey] = None
153154
freeze_key: Optional[PrivateKey] = None
155+
pause_key: Optional[PrivateKey] = None
154156

155157
class TokenCreateTransaction(Transaction):
156158
"""
@@ -265,7 +267,12 @@ def set_freeze_key(self, key):
265267
self._require_not_frozen()
266268
self._keys.freeze_key = key
267269
return self
268-
270+
271+
def set_pause_key(self, key):
272+
self._require_not_frozen()
273+
self._keys.pause_key = key
274+
return self
275+
269276
def freeze(self):
270277
"""Marks the transaction as frozen to prevent further modifications."""
271278
self._is_frozen = True
@@ -309,6 +316,11 @@ def build_transaction_body(self):
309316
freeze_public_key_bytes = self._keys.freeze_key.public_key().to_bytes_raw()
310317
freeze_key_proto = basic_types_pb2.Key(ed25519=freeze_public_key_bytes)
311318

319+
pause_key_proto = None
320+
if self._keys.pause_key:
321+
pause_public_key_bytes = self._keys.pause_key.public_key().to_bytes_raw()
322+
pause_key_proto = basic_types_pb2.Key(ed25519=pause_public_key_bytes)
323+
312324

313325
# Ensure token type is correctly set with default to fungible
314326
if self._token_params.token_type is None:
@@ -329,6 +341,7 @@ def build_transaction_body(self):
329341
adminKey=admin_key_proto,
330342
supplyKey=supply_key_proto,
331343
freezeKey=freeze_key_proto,
344+
pause_key=pause_key_proto,
332345
)
333346
# Build the base transaction body and attach the token creation details
334347
transaction_body = self.build_base_transaction_body()
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
from hiero_sdk_python.transaction.transaction import Transaction
2+
from hiero_sdk_python.hapi.services import token_pause_pb2
3+
from hiero_sdk_python.response_code import ResponseCode
4+
5+
class TokenPauseValidator:
6+
"""
7+
Validates prerequisites and constraints for a TokenPauseTransaction.
8+
"""
9+
10+
@staticmethod
11+
def validate_token_id(token_id):
12+
"""
13+
Ensures a valid token ID was provided.
14+
15+
Args:
16+
token_id (TokenId): The ID of the token to be paused.
17+
18+
Raises:
19+
ValueError: If the token ID is not provided.
20+
"""
21+
if not token_id:
22+
raise ValueError("Token ID is required for pausing a token.")
23+
24+
@staticmethod
25+
def validate_token_pause(token_info):
26+
"""
27+
Validate that the provided token can be paused.
28+
29+
Args:
30+
token_info (TokenInfo): A structure containing metadata about the token
31+
(e.g. whether the token is deleted, paused, or
32+
has a pause key, etc.).
33+
34+
Raises:
35+
ValueError: If the token is missing, already deleted, or has no valid pause key.
36+
"""
37+
TokenPauseValidator._validate_token_not_deleted(token_info)
38+
TokenPauseValidator._validate_has_pause_key(token_info)
39+
# It is NOT an error if the token is already paused
40+
41+
@staticmethod
42+
def _validate_token_not_deleted(token_info):
43+
"""
44+
Ensures the token is not already deleted.
45+
46+
Args:
47+
token_info (TokenInfo): Contains token metadata (including 'deleted' status).
48+
49+
Raises:
50+
ValueError: If the token is marked deleted.
51+
"""
52+
if getattr(token_info, "deleted", False):
53+
raise ValueError("Cannot pause a deleted token.")
54+
55+
@staticmethod
56+
def _validate_has_pause_key(token_info):
57+
"""
58+
Ensures the token has a valid pause key.
59+
60+
Args:
61+
token_info (TokenInfo): Contains token metadata (including 'pause_key').
62+
63+
Raises:
64+
ValueError: If the token has no pause key or the pause key is invalid/empty.
65+
"""
66+
if not hasattr(token_info, "pause_key") or not token_info.pause_key:
67+
raise ValueError("Token has no valid pause key and cannot be paused.")
68+
69+
70+
class TokenPauseTransaction(Transaction):
71+
"""
72+
Represents a token pause transaction.
73+
74+
This transaction pauses a specified token.
75+
76+
Inherits from the base Transaction class and implements the required methods
77+
to build and execute a token pause transaction.
78+
"""
79+
80+
def __init__(self, token_id=None):
81+
"""
82+
Initializes a new TokenPauseTransaction instance with optional token_id.
83+
84+
Args:
85+
token_id (TokenId, optional): The ID of the token to be paused.
86+
"""
87+
super().__init__()
88+
self.token_id = token_id
89+
self._default_transaction_fee = 3_000_000_000
90+
91+
def set_token_id(self, token_id):
92+
self._require_not_frozen()
93+
self.token_id = token_id
94+
return self
95+
96+
def build_transaction_body(self):
97+
"""
98+
Builds and returns the protobuf transaction body for token pause.
99+
100+
Returns:
101+
TransactionBody: The protobuf transaction body containing the token pause details.
102+
103+
Raises:
104+
ValueError: If the token ID is missing.
105+
"""
106+
107+
# Validation checks
108+
TokenPauseValidator.validate_token_id(self.token_id)
109+
110+
token_pause_body = token_pause_pb2.TokenPauseTransactionBody(
111+
token=self.token_id.to_proto(),
112+
)
113+
114+
transaction_body = self.build_base_transaction_body()
115+
transaction_body.token_pause.CopyFrom(token_pause_body)
116+
117+
return transaction_body
118+
119+
def _execute_transaction(self, client, transaction_proto):
120+
"""
121+
Executes the token pause transaction using the provided client.
122+
123+
Args:
124+
client (Client): The client instance to use for execution.
125+
transaction_proto (Transaction): The protobuf Transaction message.
126+
127+
Returns:
128+
TransactionReceipt: The receipt from the network after transaction execution.
129+
130+
Raises:
131+
Exception: If the transaction submission fails or receives an error response.
132+
"""
133+
# Retrieve token info and run pause-specific validations
134+
token_info = client.get_token_info(self.token_id)
135+
TokenPauseValidator.validate_token_pause(token_info)
136+
137+
# Log if the token is already paused:
138+
if getattr(token_info, "paused", False):
139+
print("Token is already paused.")
140+
pass
141+
142+
# Submit the token pause transaction
143+
response = client.token_stub.pauseToken(transaction_proto)
144+
145+
if response.nodeTransactionPrecheckCode != ResponseCode.OK:
146+
error_code = response.nodeTransactionPrecheckCode
147+
error_message = ResponseCode.get_name(error_code)
148+
raise Exception(f"Error during transaction submission: {error_code} ({error_message})")
149+
150+
receipt = self.get_receipt(client)
151+
return receipt

0 commit comments

Comments
 (0)