Skip to content

Commit 96c4232

Browse files
authored
feat: add ScheduleDeleteTransaction (#358)
* feat: add ScheduleDeleteTransaction Signed-off-by: dosi <[email protected]> * feat: add schedule delete integration tests Signed-off-by: dosi <[email protected]> * test: add ScheduleDeleteTransaction unit tests Signed-off-by: dosi <[email protected]> * docs: add schedule delete example Signed-off-by: dosi <[email protected]> * docs: add ScheduleDelete to running_example Signed-off-by: dosi <[email protected]> * chore: update changelog Signed-off-by: dosi <[email protected]> * chore: add ScheduleDeleteTransaction to __init__.py Signed-off-by: dosi <[email protected]> * chore: address PR feedback Signed-off-by: dosi <[email protected]> --------- Signed-off-by: dosi <[email protected]>
1 parent 7975ad4 commit 96c4232

File tree

8 files changed

+941
-0
lines changed

8 files changed

+941
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
1010
- Convert camelCase to snake_case in integration tests (#318)
1111

1212
### Added
13+
- ScheduleDeleteTransaction class
1314
- prng_number and prng_bytes properties in TransactionRecord
1415
- PrngTransaction class
1516
- ScheduleInfoQuery class

docs/sdk_users/running_examples.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ You can choose either syntax or even mix both styles in your projects.
6868
- [Schedule Transactions](#schedule-transactions)
6969
- [Creating a Schedule](#creating-a-schedule)
7070
- [Querying Schedule Info](#querying-schedule-info)
71+
- [Deleting a Schedule](#deleting-a-schedule)
7172
- [Node Transactions](#node-transactions)
7273
- [Creating a Node](#creating-a-node)
7374
- [Miscellaneous Queries](#miscellaneous-queries)
@@ -1641,6 +1642,29 @@ schedule_info = (
16411642
print(schedule_info)
16421643
```
16431644

1645+
### Deleting a Schedule
1646+
1647+
#### Pythonic Syntax:
1648+
```python
1649+
transaction = ScheduleDeleteTransaction(
1650+
schedule_id=schedule_id
1651+
).freeze_with(client)
1652+
1653+
transaction.sign(admin_key) # Admin key must have been set during schedule creation
1654+
receipt = transaction.execute(client)
1655+
```
1656+
1657+
#### Method Chaining:
1658+
```python
1659+
receipt = (
1660+
ScheduleDeleteTransaction()
1661+
.set_schedule_id(schedule_id)
1662+
.freeze_with(client)
1663+
.sign(admin_key) # Admin key must have been set during schedule creation
1664+
.execute(client)
1665+
)
1666+
```
1667+
16441668
## Node Transactions
16451669

16461670
### Creating a Node

examples/schedule_delete.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
"""
2+
Example demonstrating schedule deletion on the network.
3+
"""
4+
5+
import datetime
6+
import os
7+
import sys
8+
9+
from dotenv import load_dotenv
10+
11+
from hiero_sdk_python.account.account_create_transaction import AccountCreateTransaction
12+
from hiero_sdk_python.account.account_id import AccountId
13+
from hiero_sdk_python.client.client import Client
14+
from hiero_sdk_python.client.network import Network
15+
from hiero_sdk_python.crypto.private_key import PrivateKey
16+
from hiero_sdk_python.hbar import Hbar
17+
from hiero_sdk_python.response_code import ResponseCode
18+
from hiero_sdk_python.schedule.schedule_delete_transaction import (
19+
ScheduleDeleteTransaction,
20+
)
21+
from hiero_sdk_python.schedule.schedule_info_query import ScheduleInfoQuery
22+
from hiero_sdk_python.timestamp import Timestamp
23+
from hiero_sdk_python.transaction.transfer_transaction import TransferTransaction
24+
25+
load_dotenv()
26+
27+
28+
def setup_client():
29+
"""Initialize and set up the client with operator account"""
30+
network = Network(network="testnet")
31+
client = Client(network)
32+
33+
operator_id = AccountId.from_string(os.getenv("OPERATOR_ID"))
34+
operator_key = PrivateKey.from_string(os.getenv("OPERATOR_KEY"))
35+
client.set_operator(operator_id, operator_key)
36+
37+
return client
38+
39+
40+
def create_account(client):
41+
"""Create a test account"""
42+
account_private_key = PrivateKey.generate_ed25519()
43+
account_public_key = account_private_key.public_key()
44+
45+
receipt = (
46+
AccountCreateTransaction()
47+
.set_key(account_public_key)
48+
.set_initial_balance(Hbar(2))
49+
.set_account_memo("Test account for schedule")
50+
.freeze_with(client)
51+
.sign(account_private_key)
52+
.execute(client)
53+
)
54+
55+
if receipt.status != ResponseCode.SUCCESS:
56+
print(
57+
f"Account creation failed with status: {ResponseCode(receipt.status).name}"
58+
)
59+
sys.exit(1)
60+
61+
account_id = receipt.account_id
62+
print(f"\nAccount created with ID: {account_id}")
63+
64+
return account_id, account_private_key
65+
66+
67+
def create_schedule(client, account_id, account_private_key):
68+
"""Create a scheduled transaction"""
69+
# Amount to transfer in tinybars
70+
amount = Hbar(1).to_tinybars()
71+
72+
# Create a transfer transaction
73+
transfer_tx = (
74+
TransferTransaction()
75+
.add_hbar_transfer(account_id, -amount)
76+
.add_hbar_transfer(client.operator_account_id, amount)
77+
)
78+
79+
# Convert the transfer transaction into a scheduled transaction
80+
schedule_tx = transfer_tx.schedule()
81+
82+
# Set expiration time for the scheduled transaction (90 seconds from now)
83+
expiration_time = datetime.datetime.now() + datetime.timedelta(seconds=90)
84+
85+
receipt = (
86+
schedule_tx.set_payer_account_id(
87+
client.operator_account_id
88+
) # payer of the transaction fee
89+
.set_admin_key(
90+
client.operator_private_key.public_key()
91+
) # delete/modify the transaction
92+
.set_expiration_time(Timestamp.from_date(expiration_time))
93+
.set_wait_for_expiry(True) # wait to expire to execute
94+
.freeze_with(client)
95+
.sign(
96+
account_private_key
97+
) # sign with the account private key as it transfers money
98+
.execute(client)
99+
)
100+
101+
if receipt.status != ResponseCode.SUCCESS:
102+
print(
103+
f"Schedule creation failed with status: {ResponseCode(receipt.status).name}"
104+
)
105+
sys.exit(1)
106+
107+
print(f"Schedule created with ID: {receipt.schedule_id}")
108+
109+
return receipt.schedule_id
110+
111+
112+
def schedule_delete():
113+
"""
114+
Demonstrates schedule deletion functionality by:
115+
1. Setting up client with operator account
116+
2. Creating a test account
117+
3. Creating a scheduled transaction
118+
4. Deleting the scheduled transaction
119+
"""
120+
client = setup_client()
121+
122+
# Create an account first
123+
account_id, account_private_key = create_account(client)
124+
125+
# Create a schedule
126+
schedule_id = create_schedule(client, account_id, account_private_key)
127+
128+
# Delete the schedule
129+
print("\nDeleting schedule...")
130+
receipt = ScheduleDeleteTransaction().set_schedule_id(schedule_id).execute(client)
131+
132+
if receipt.status != ResponseCode.SUCCESS:
133+
print(
134+
f"Schedule deletion failed with status: {ResponseCode(receipt.status).name}"
135+
)
136+
sys.exit(1)
137+
138+
info = ScheduleInfoQuery().set_schedule_id(schedule_id).execute(client)
139+
print(f"Schedule {info.schedule_id} deleted at {info.deleted_at}")
140+
141+
142+
if __name__ == "__main__":
143+
schedule_delete()

examples/schedule_sign.py

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
"""
2+
Example demonstrating schedule sign transaction functionality.
3+
"""
4+
5+
import datetime
6+
import os
7+
import sys
8+
9+
from dotenv import load_dotenv
10+
11+
from hiero_sdk_python import AccountId, Client, Hbar, Network, PrivateKey
12+
from hiero_sdk_python.account.account_create_transaction import AccountCreateTransaction
13+
from hiero_sdk_python.response_code import ResponseCode
14+
from hiero_sdk_python.schedule.schedule_info_query import ScheduleInfoQuery
15+
from hiero_sdk_python.schedule.schedule_sign_transaction import ScheduleSignTransaction
16+
from hiero_sdk_python.timestamp import Timestamp
17+
from hiero_sdk_python.transaction.transfer_transaction import TransferTransaction
18+
19+
load_dotenv()
20+
21+
22+
def setup_client():
23+
"""Initialize and set up the client with operator account"""
24+
network = Network(network="testnet")
25+
client = Client(network)
26+
27+
operator_id = AccountId.from_string(os.getenv("OPERATOR_ID"))
28+
operator_key = PrivateKey.from_string(os.getenv("OPERATOR_KEY"))
29+
client.set_operator(operator_id, operator_key)
30+
31+
return client
32+
33+
34+
def create_account(client):
35+
"""Create a test account"""
36+
account_private_key = PrivateKey.generate_ed25519()
37+
account_public_key = account_private_key.public_key()
38+
39+
receipt = (
40+
AccountCreateTransaction()
41+
.set_key(account_public_key)
42+
.set_initial_balance(Hbar(2))
43+
.set_account_memo("Test account for schedule sign")
44+
.freeze_with(client)
45+
.sign(account_private_key)
46+
.execute(client)
47+
)
48+
49+
if receipt.status != ResponseCode.SUCCESS:
50+
print(
51+
f"Account creation failed with status: {ResponseCode(receipt.status).name}"
52+
)
53+
sys.exit(1)
54+
55+
account_id = receipt.account_id
56+
print(f"\nAccount created with ID: {account_id}")
57+
58+
return account_id, account_private_key
59+
60+
61+
def create_schedule(client, account_id):
62+
"""Create a scheduled transaction"""
63+
# Amount to transfer in tinybars
64+
amount = Hbar(1).to_tinybars()
65+
66+
# Create a transfer transaction
67+
transfer_tx = (
68+
TransferTransaction()
69+
.add_hbar_transfer(account_id, -amount)
70+
.add_hbar_transfer(client.operator_account_id, amount)
71+
)
72+
73+
# Convert the transfer transaction into a scheduled transaction
74+
schedule_tx = transfer_tx.schedule()
75+
76+
# Set expiration time for the scheduled transaction (90 seconds from now)
77+
expiration_time = datetime.datetime.now() + datetime.timedelta(seconds=90)
78+
79+
receipt = (
80+
schedule_tx.set_payer_account_id(
81+
client.operator_account_id
82+
) # payer of the transaction fee
83+
.set_admin_key(
84+
client.operator_private_key.public_key()
85+
) # delete/modify the transaction
86+
.set_expiration_time(Timestamp.from_date(expiration_time))
87+
.set_wait_for_expiry(False) # don't wait for expiry, execute when signed
88+
.set_schedule_memo("Test schedule for signing")
89+
.execute(client)
90+
)
91+
92+
if receipt.status != ResponseCode.SUCCESS:
93+
print(
94+
f"Schedule creation failed with status: {ResponseCode(receipt.status).name}"
95+
)
96+
sys.exit(1)
97+
98+
print(f"Schedule created with ID: {receipt.schedule_id}")
99+
100+
return receipt.schedule_id
101+
102+
103+
def query_schedule_info(client, schedule_id):
104+
"""Query and display schedule information"""
105+
info = ScheduleInfoQuery().set_schedule_id(schedule_id).execute(client)
106+
107+
print("\nSchedule Info:")
108+
print(f"Schedule ID: {info.schedule_id}")
109+
print(f"Creator Account ID: {info.creator_account_id}")
110+
print(f"Payer Account ID: {info.payer_account_id}")
111+
print(f"Executed At: {info.executed_at}")
112+
print(f"Expiration Time: {info.expiration_time}")
113+
print(f"Schedule Memo: {info.schedule_memo}")
114+
print(f"Admin Key: {info.admin_key}")
115+
print(f"Wait For Expiry: {info.wait_for_expiry}")
116+
print(f"Signers: {len(info.signers)} signer(s)")
117+
for i, signer in enumerate(info.signers):
118+
print(f" Signer {i+1}: {signer}")
119+
120+
121+
def schedule_sign():
122+
"""
123+
Demonstrates schedule sign functionality by:
124+
1. Setting up client with operator account
125+
2. Creating a test account
126+
3. Creating a scheduled transfer transaction
127+
4. Querying the schedule info before signing
128+
5. Signing the scheduled transaction to execute it
129+
6. Querying the schedule info after signing to verify execution
130+
"""
131+
client = setup_client()
132+
133+
# Create an account first
134+
account_id, account_private_key = create_account(client)
135+
136+
# Create a schedule
137+
schedule_id = create_schedule(client, account_id)
138+
139+
# Query schedule info before signing
140+
print("\nSchedule Info Before Signing:")
141+
query_schedule_info(client, schedule_id)
142+
143+
# Sign the scheduled transaction to execute it
144+
print("\nSigning Schedule...")
145+
receipt = (
146+
ScheduleSignTransaction()
147+
.set_schedule_id(schedule_id)
148+
.freeze_with(client)
149+
.sign(account_private_key)
150+
.execute(client)
151+
)
152+
153+
if receipt.status != ResponseCode.SUCCESS:
154+
print(f"Schedule sign failed with status: {ResponseCode(receipt.status).name}")
155+
sys.exit(1)
156+
157+
print("Schedule signed successfully!")
158+
159+
# Query schedule info after signing to verify execution
160+
print("\nSchedule Info After Signing:")
161+
query_schedule_info(client, schedule_id)
162+
163+
164+
if __name__ == "__main__":
165+
schedule_sign()

src/hiero_sdk_python/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
from .schedule.schedule_id import ScheduleId
113113
from .schedule.schedule_info import ScheduleInfo
114114
from .schedule.schedule_info_query import ScheduleInfoQuery
115+
from .schedule.schedule_delete_transaction import ScheduleDeleteTransaction
115116

116117
# Nodes
117118
from .nodes.node_create_transaction import NodeCreateTransaction
@@ -230,6 +231,7 @@
230231
"ScheduleId",
231232
"ScheduleInfoQuery",
232233
"ScheduleInfo",
234+
"ScheduleDeleteTransaction",
233235

234236
# Nodes
235237
"NodeCreateTransaction",

0 commit comments

Comments
 (0)