Skip to content

Commit ee68f3c

Browse files
authored
feat: Added TokenUnpauseTransaction (#643)
Signed-off-by: Manish Dait <[email protected]>
1 parent a27b26c commit ee68f3c

File tree

7 files changed

+597
-1
lines changed

7 files changed

+597
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
1313
- Added comprehensive Google-style docstrings to the `Logger` class and all utility functions in `src/hiero_sdk_python/logger/logger.py` (#639).
1414
- add AccountRecordsQuery class
1515
- Transaction bytes serialization support: `Transaction.freeze()`, `Transaction.to_bytes()`, and `Transaction.from_bytes()` methods for offline signing and transaction storage
16-
1716
- docs: Add Google-style docstrings to `ContractId` class and methods in `contract_id.py`.
17+
- Added TokenUnpauseTransaction class
1818

1919
### Changed
2020
- chore: validate that token airdrop transactions require an available token service on the channel (#632)

docs/sdk_users/running_examples.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ You can choose either syntax or even mix both styles in your projects.
3737
- [Burning a Non-Fungible Token](#burning-a-non-fungible-token)
3838
- [Token Update NFTs](#token-update-nfts)
3939
- [Pausing a Token](#pausing-a-token)
40+
- [Unpausing a Token](#unpausing-a-token)
4041
- [Token Grant KYC](#token-grant-kyc)
4142
- [Token Revoke KYC](#token-revoke-kyc)
4243
- [Updating a Token](#updating-a-token)
@@ -839,6 +840,29 @@ transaction.execute(client)
839840
840841
```
841842

843+
### Unpausing a Token
844+
845+
#### Pythonic Syntax:
846+
```
847+
transaction = TokenUnpauseTransaction(
848+
token_id=token_id
849+
).freeze_with(client)
850+
851+
transaction.sign(pause_key)
852+
transaction.execute(client)
853+
```
854+
855+
#### Method Chaining:
856+
```
857+
transaction = (
858+
TokenUnpauseTransaction()
859+
.set_token_id(token_id)
860+
.freeze_with(client)
861+
.sign(pause_key)
862+
)
863+
transaction.execute(client)
864+
```
865+
842866
### Token Grant KYC
843867

844868
#### Pythonic Syntax:

examples/token_unpause.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
"""
2+
uv run examples/token_unpause.py
3+
python examples/token_unpause.py
4+
5+
"""
6+
import os
7+
import sys
8+
from dotenv import load_dotenv
9+
10+
from hiero_sdk_python import (
11+
Client,
12+
AccountId,
13+
PrivateKey,
14+
Network,
15+
ResponseCode,
16+
TokenId,
17+
TokenType,
18+
TokenCreateTransaction,
19+
TokenUnpauseTransaction,
20+
TokenPauseTransaction,
21+
TokenInfoQuery
22+
)
23+
24+
load_dotenv()
25+
26+
def setup_client():
27+
"""Initialize and set up the client with operator account"""
28+
print("Connecting to Hedera testnet...")
29+
30+
try:
31+
network = Network(os.getenv('NETWORK'))
32+
client = Client(network)
33+
34+
operator_id = AccountId.from_string(os.getenv('OPERATOR_ID'))
35+
operator_key = PrivateKey.from_string(os.getenv('OPERATOR_KEY'))
36+
client.set_operator(operator_id, operator_key)
37+
38+
return client, operator_id, operator_key
39+
except (TypeError, ValueError):
40+
print("❌ Error: Creating client, Please check your .env file")
41+
sys.exit(1)
42+
43+
def create_token(client: Client, operator_id: AccountId, pause_key: PrivateKey,):
44+
"""Create a fungible token"""
45+
print("\nCreating a token...")
46+
47+
try:
48+
token_tx = (
49+
TokenCreateTransaction()
50+
.set_token_name("Token A")
51+
.set_token_symbol("TKA")
52+
.set_initial_supply(1)
53+
.set_treasury_account_id(operator_id)
54+
.set_token_type(TokenType.FUNGIBLE_COMMON)
55+
.set_pause_key(pause_key) # Required for pausing tokens
56+
.freeze_with(client)
57+
)
58+
59+
receipt = token_tx.sign(pause_key).execute(client)
60+
61+
token_id = receipt.token_id
62+
print(f"✅ Success! Created token: {token_id}")
63+
check_pause_status(client, token_id)
64+
65+
return token_id
66+
except Exception as e:
67+
print(f"❌ Error creating token: {e}")
68+
sys.exit(1)
69+
70+
def pause_token(client: Client, token_id: TokenId, pause_key: PrivateKey):
71+
"""Pause token"""
72+
print("\nAttempting to pause the token...")
73+
74+
try:
75+
pause_tx = (
76+
TokenPauseTransaction()
77+
.set_token_id(token_id)
78+
.freeze_with(client)
79+
.sign(pause_key)
80+
)
81+
82+
receipt = pause_tx.execute(client)
83+
84+
if receipt.status == ResponseCode.SUCCESS:
85+
print(f"✅ Successfully paused token: {token_id}")
86+
check_pause_status(client, token_id)
87+
else:
88+
print(f"❌ Transaction completed, but status is: {receipt.status.name}")
89+
sys.exit(1)
90+
except Exception as e:
91+
print(f"❌ Error pausing token: {e}")
92+
sys.exit(1)
93+
94+
def check_pause_status(client, token_id: TokenId):
95+
"""Query and print the current paused/unpaused status of a token."""
96+
info = TokenInfoQuery().set_token_id(token_id).execute(client)
97+
print(f"Token status is now: {info.pause_status.name}")
98+
99+
100+
def unpause_token():
101+
pause_key = PrivateKey.generate()
102+
client, operator_id, _ = setup_client()
103+
104+
token_id = create_token(client, operator_id, pause_key)
105+
106+
pause_token(client, token_id, pause_key)
107+
108+
print("\nAttempting to Unpause the token...")
109+
110+
unpause_tx = (
111+
TokenUnpauseTransaction()
112+
.set_token_id(token_id)
113+
.freeze_with(client)
114+
.sign(pause_key)
115+
)
116+
receipt = unpause_tx.execute(client)
117+
118+
try:
119+
if receipt.status == ResponseCode.SUCCESS:
120+
print(f"✅ Successfully unpaused token: {token_id}")
121+
check_pause_status(client, token_id)
122+
else:
123+
print(f"❌ Transaction completed, but status is: {receipt.status.name}")
124+
sys.exit(1)
125+
except Exception as e:
126+
print(f"❌ Error pausing token: {e}")
127+
sys.exit(1)
128+
129+
if __name__ == "__main__":
130+
unpause_token()

src/hiero_sdk_python/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
from .tokens.token_nft_allowance import TokenNftAllowance
4848
from .tokens.hbar_allowance import HbarAllowance
4949
from .tokens.hbar_transfer import HbarTransfer
50+
from .tokens.token_unpause_transaction import TokenUnpauseTransaction
51+
from .tokens.token_pause_transaction import TokenPauseTransaction
5052

5153
# Transaction
5254
from .transaction.transaction import Transaction
@@ -187,6 +189,8 @@
187189
"TokenNftAllowance",
188190
"HbarAllowance",
189191
"HbarTransfer",
192+
"TokenPauseTransaction",
193+
"TokenUnpauseTransaction",
190194

191195
# Transaction
192196
"Transaction",
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
"""
2+
hiero_sdk_python.tokens.token_unpause_transaction.py
3+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4+
5+
Provides the TokenUnpauseTransaction class a subclass of Transaction that
6+
facilitates unpausing a specified token on the Hedera network using the
7+
Hedera Token Service (HTS) API.
8+
"""
9+
from typing import Optional
10+
from hiero_sdk_python.hapi.services.schedulable_transaction_body_pb2 import (
11+
SchedulableTransactionBody
12+
)
13+
from hiero_sdk_python.hapi.services.token_unpause_pb2 import TokenUnpauseTransactionBody
14+
from hiero_sdk_python.hapi.services.transaction_pb2 import TransactionBody
15+
16+
from hiero_sdk_python.channels import _Channel
17+
from hiero_sdk_python.executable import _Method
18+
from hiero_sdk_python.client.client import Client
19+
from hiero_sdk_python.tokens.token_id import TokenId
20+
from hiero_sdk_python.transaction.transaction import Transaction
21+
22+
class TokenUnpauseTransaction(Transaction):
23+
"""
24+
Represents a token unpause transaction on the Hedera network.
25+
26+
This transaction unpauses specified tokens.
27+
28+
Inherits from the base Transaction class and implements the required methods
29+
to build and execute a token unpause transaction.
30+
"""
31+
32+
def __init__(self, token_id: Optional[TokenId] = None) -> None:
33+
"""
34+
Initializes a new TokenUnpauseTransaction instance with default values.
35+
36+
Args:
37+
token_id (Optional[TokenId]): The ID of the token to unpause.
38+
"""
39+
super().__init__()
40+
self.token_id: Optional[TokenId] = None
41+
42+
if token_id is not None:
43+
self.set_token_id(token_id)
44+
45+
def set_token_id(self, token_id: TokenId) -> "TokenUnpauseTransaction":
46+
"""
47+
Sets the token ID for this unpause transaction.
48+
49+
Args:
50+
token_id (TokenId): The ID of the token to unpause.
51+
52+
Returns:
53+
TokenUnpauseTransaction: This current instance of transaction.
54+
"""
55+
self._require_not_frozen()
56+
57+
#Check if the tokenId is instance of TokenId
58+
if not isinstance(token_id, TokenId):
59+
raise TypeError("token_id must be an instance of TokenId")
60+
61+
self.token_id = token_id
62+
return self
63+
64+
def _validate_checksum(self, client: "Client") -> None:
65+
"""
66+
Validates the checksum for the token ID associated with this transaction.
67+
68+
Args:
69+
client (Client): The client instance used for validation.
70+
"""
71+
if self.token_id is not None:
72+
self.token_id.validate_checksum(client)
73+
74+
@classmethod
75+
def _from_proto(cls, proto: TokenUnpauseTransactionBody) -> "TokenUnpauseTransaction":
76+
"""
77+
Construct TokenUnpauseTransaction from TokenUnpauseTransactionBody.
78+
79+
Args:
80+
proto (TokenUnpauseTransactionBody): The protobuf body of TokenUnpauseTransaction
81+
82+
Returns:
83+
TokenUnpauseTransaction: A new instance of TokenUnpauseTransaction
84+
"""
85+
token_id = TokenId._from_proto(proto.token) if proto.token else None
86+
return cls(token_id=token_id)
87+
88+
def _build_proto_body(self) -> TokenUnpauseTransactionBody:
89+
"""
90+
Returns the protobuf body for the token unpause transaction.
91+
92+
Returns:
93+
TokenUnpauseTransactionBody: The protobuf body for this transaction.
94+
95+
Raises:
96+
ValueError: If account ID or token ID is not set.
97+
"""
98+
if self.token_id is None:
99+
raise ValueError("Missing token ID")
100+
101+
return TokenUnpauseTransactionBody(
102+
token=self.token_id._to_proto()
103+
)
104+
105+
def build_transaction_body(self) -> TransactionBody:
106+
"""
107+
Builds and returns the protobuf transaction body for token unpause.
108+
109+
Returns:
110+
TransactionBody: The protobuf transaction body containing the token unpause details.
111+
"""
112+
token_unpause_body = self._build_proto_body()
113+
transaction_body = self.build_base_transaction_body()
114+
transaction_body.token_unpause.CopyFrom(token_unpause_body)
115+
return transaction_body
116+
117+
def build_scheduled_body(self) -> SchedulableTransactionBody:
118+
"""
119+
Builds the scheduled transaction body for this token unpause transaction.
120+
121+
Returns:
122+
SchedulableTransactionBody: The built scheduled transaction body.
123+
"""
124+
token_unpause_body = self._build_proto_body()
125+
schedulable_body = self.build_base_scheduled_body()
126+
schedulable_body.token_unpause.CopyFrom(token_unpause_body)
127+
return schedulable_body
128+
129+
def _get_method(self, channel: _Channel) -> _Method:
130+
return _Method(
131+
transaction_func=channel.token.unpauseToken,
132+
query_func=None
133+
)

0 commit comments

Comments
 (0)