hiero-sdk-python 0.0.2.dev3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hedera_sdk_python/__init__.py +93 -0
- hedera_sdk_python/account/__init__.py +0 -0
- hedera_sdk_python/account/account_balance.py +44 -0
- hedera_sdk_python/account/account_create_transaction.py +173 -0
- hedera_sdk_python/account/account_id.py +62 -0
- hedera_sdk_python/client/__init__.py +0 -0
- hedera_sdk_python/client/client.py +139 -0
- hedera_sdk_python/client/network.py +143 -0
- hedera_sdk_python/consensus/__init__.py +0 -0
- hedera_sdk_python/consensus/topic_create_transaction.py +83 -0
- hedera_sdk_python/consensus/topic_delete_transaction.py +67 -0
- hedera_sdk_python/consensus/topic_id.py +44 -0
- hedera_sdk_python/consensus/topic_info.py +91 -0
- hedera_sdk_python/consensus/topic_message.py +61 -0
- hedera_sdk_python/consensus/topic_message_submit_transaction.py +87 -0
- hedera_sdk_python/consensus/topic_update_transaction.py +173 -0
- hedera_sdk_python/crypto/__init__.py +0 -0
- hedera_sdk_python/crypto/private_key.py +196 -0
- hedera_sdk_python/crypto/public_key.py +162 -0
- hedera_sdk_python/hbar.py +33 -0
- hedera_sdk_python/query/__init__.py +0 -0
- hedera_sdk_python/query/account_balance_query.py +100 -0
- hedera_sdk_python/query/query.py +138 -0
- hedera_sdk_python/query/topic_info_query.py +105 -0
- hedera_sdk_python/query/topic_message_query.py +105 -0
- hedera_sdk_python/query/transaction_get_receipt_query.py +128 -0
- hedera_sdk_python/response_code.py +587 -0
- hedera_sdk_python/timestamp.py +166 -0
- hedera_sdk_python/tokens/__init__.py +0 -0
- hedera_sdk_python/tokens/token_associate_transaction.py +85 -0
- hedera_sdk_python/tokens/token_create_transaction.py +144 -0
- hedera_sdk_python/tokens/token_delete_transaction.py +84 -0
- hedera_sdk_python/tokens/token_dissociate_transaction.py +81 -0
- hedera_sdk_python/tokens/token_id.py +44 -0
- hedera_sdk_python/tokens/token_mint_transaction.py +143 -0
- hedera_sdk_python/transaction/__init__.py +0 -0
- hedera_sdk_python/transaction/query_payment.py +32 -0
- hedera_sdk_python/transaction/transaction.py +267 -0
- hedera_sdk_python/transaction/transaction_id.py +140 -0
- hedera_sdk_python/transaction/transaction_receipt.py +78 -0
- hedera_sdk_python/transaction/transfer_transaction.py +119 -0
- hedera_sdk_python/utils/key_format.py +22 -0
- hiero_sdk_python-0.0.2.dev3.dist-info/METADATA +822 -0
- hiero_sdk_python-0.0.2.dev3.dist-info/RECORD +47 -0
- hiero_sdk_python-0.0.2.dev3.dist-info/WHEEL +4 -0
- hiero_sdk_python-0.0.2.dev3.dist-info/entry_points.txt +4 -0
- hiero_sdk_python-0.0.2.dev3.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
from datetime import datetime, timedelta, timezone
|
|
2
|
+
import random
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
from hiero-sdk-python.hapi.services.timestamp_pb2 import Timestamp as TimestampProto
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Timestamp:
|
|
9
|
+
"""
|
|
10
|
+
Represents a specific moment in time with nanosecond precision.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
MAX_NS = 1_000_000_000
|
|
14
|
+
|
|
15
|
+
def __init__(self, seconds: int, nanos: int):
|
|
16
|
+
"""
|
|
17
|
+
Initialize a new `Timestamp` instance.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
seconds (int): Number of seconds since epoch.
|
|
21
|
+
nanos (int): Number of nanoseconds past the last second.
|
|
22
|
+
"""
|
|
23
|
+
self.seconds = seconds
|
|
24
|
+
self.nanos = nanos
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def generate(has_jitter=True) -> "Timestamp":
|
|
28
|
+
"""
|
|
29
|
+
Generate a `Timestamp` with optional jitter.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
has_jitter (bool): Whether to introduce random jitter. Default is True.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Timestamp: A new `Timestamp` instance.
|
|
36
|
+
"""
|
|
37
|
+
jitter = random.randint(3000, 8000) if has_jitter else 0
|
|
38
|
+
now_ms = int(round(time.time() * 1000)) - jitter
|
|
39
|
+
seconds = now_ms // 1000
|
|
40
|
+
nanos = (now_ms % 1000) * 1_000_000 + random.randint(0, 999_999)
|
|
41
|
+
|
|
42
|
+
return Timestamp(seconds, nanos)
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def from_date(date) -> "Timestamp":
|
|
46
|
+
"""
|
|
47
|
+
Create a `Timestamp` from a Python `datetime` object, timestamp, or string.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
date (datetime | int | str): A `datetime`, timestamp (int), or ISO 8601 string.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Timestamp: A `Timestamp` instance.
|
|
54
|
+
"""
|
|
55
|
+
if isinstance(date, datetime):
|
|
56
|
+
seconds = int(date.timestamp())
|
|
57
|
+
nanos = int((date.timestamp() % 1) * Timestamp.MAX_NS)
|
|
58
|
+
elif isinstance(date, int):
|
|
59
|
+
seconds = date
|
|
60
|
+
nanos = 0
|
|
61
|
+
elif isinstance(date, str):
|
|
62
|
+
parsed_date = datetime.fromisoformat(date)
|
|
63
|
+
seconds = int(parsed_date.timestamp())
|
|
64
|
+
nanos = int((parsed_date.timestamp() % 1) * Timestamp.MAX_NS)
|
|
65
|
+
else:
|
|
66
|
+
raise ValueError("Invalid type for 'date'. Must be datetime, int, or str.")
|
|
67
|
+
|
|
68
|
+
return Timestamp(seconds, nanos)
|
|
69
|
+
|
|
70
|
+
def to_date(self) -> datetime:
|
|
71
|
+
"""
|
|
72
|
+
Convert the `Timestamp` to a Python `datetime` object.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
datetime: A `datetime` instance.
|
|
76
|
+
"""
|
|
77
|
+
return datetime.fromtimestamp(self.seconds, tz=timezone.utc) + timedelta(
|
|
78
|
+
microseconds=self.nanos // 1000
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
def plus_nanos(self, nanos: int) -> "Timestamp":
|
|
82
|
+
"""
|
|
83
|
+
Add nanoseconds to the current `Timestamp`.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
nanos (int): The number of nanoseconds to add.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Timestamp: A new `Timestamp` instance.
|
|
90
|
+
"""
|
|
91
|
+
total_nanos = self.nanos + nanos
|
|
92
|
+
new_seconds = self.seconds + total_nanos // Timestamp.MAX_NS
|
|
93
|
+
new_nanos = total_nanos % Timestamp.MAX_NS
|
|
94
|
+
|
|
95
|
+
return Timestamp(new_seconds, new_nanos)
|
|
96
|
+
|
|
97
|
+
def to_protobuf(self) -> TimestampProto:
|
|
98
|
+
"""
|
|
99
|
+
Convert the `Timestamp` to corresponding protobuf object.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
dict: A protobuf representation of the `Timestamp`.
|
|
103
|
+
"""
|
|
104
|
+
return TimestampProto(seconds=self.seconds, nanos=self.nanos)
|
|
105
|
+
|
|
106
|
+
@staticmethod
|
|
107
|
+
def from_protobuf(pb_obj: TimestampProto) -> "Timestamp":
|
|
108
|
+
"""
|
|
109
|
+
Create a `Timestamp` from a protobuf object.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
pb_obj (timestamp_pb2.Timestamp): A protobuf Timestamp object.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Timestamp: A `Timestamp` instance.
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
return Timestamp(pb_obj.seconds, pb_obj.nanos)
|
|
119
|
+
|
|
120
|
+
def __str__(self) -> str:
|
|
121
|
+
"""
|
|
122
|
+
Get a string representation of the `Timestamp`.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
str: The string representation in the format `seconds.nanos`.
|
|
126
|
+
"""
|
|
127
|
+
return f"{self.seconds}.{str(self.nanos).zfill(9)}"
|
|
128
|
+
|
|
129
|
+
def compare(self, other: "Timestamp") -> int:
|
|
130
|
+
"""
|
|
131
|
+
Compare the current `Timestamp` with another.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
other (Timestamp): The `Timestamp` to compare with.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
int: -1 if this `Timestamp` is earlier, 1 if later, 0 if equal.
|
|
138
|
+
"""
|
|
139
|
+
if self.seconds != other.seconds:
|
|
140
|
+
return -1 if self.seconds < other.seconds else 1
|
|
141
|
+
if self.nanos != other.nanos:
|
|
142
|
+
return -1 if self.nanos < other.nanos else 1
|
|
143
|
+
return 0
|
|
144
|
+
|
|
145
|
+
def __eq__(self, other: object) -> bool:
|
|
146
|
+
"""
|
|
147
|
+
Check equality with another object.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
other (object): The object to compare with.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
bool: True if equal, False otherwise.
|
|
154
|
+
"""
|
|
155
|
+
if not isinstance(other, Timestamp):
|
|
156
|
+
return False
|
|
157
|
+
return self.seconds == other.seconds and self.nanos == other.nanos
|
|
158
|
+
|
|
159
|
+
def __hash__(self) -> int:
|
|
160
|
+
"""
|
|
161
|
+
Get the hash value of the `Timestamp`.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
int: The hash value.
|
|
165
|
+
"""
|
|
166
|
+
return hash((self.seconds, self.nanos))
|
|
File without changes
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
from hiero-sdk-python.transaction.transaction import Transaction
|
|
2
|
+
from hiero-sdk-python.hapi.services import token_associate_pb2
|
|
3
|
+
from hiero-sdk-python.response_code import ResponseCode
|
|
4
|
+
|
|
5
|
+
class TokenAssociateTransaction(Transaction):
|
|
6
|
+
"""
|
|
7
|
+
Represents a token associate transaction on the Hedera network.
|
|
8
|
+
|
|
9
|
+
This transaction associates the specified tokens with an account,
|
|
10
|
+
allowing the account to hold and transact with those tokens.
|
|
11
|
+
|
|
12
|
+
Inherits from the base Transaction class and implements the required methods
|
|
13
|
+
to build and execute a token association transaction.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, account_id=None, token_ids=None):
|
|
17
|
+
"""
|
|
18
|
+
Initializes a new TokenAssociateTransaction instance with optional keyword arguments.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
account_id (AccountId, optional): The account to associate tokens with.
|
|
22
|
+
token_ids (list of TokenId, optional): The tokens to associate with the account.
|
|
23
|
+
"""
|
|
24
|
+
super().__init__()
|
|
25
|
+
self.account_id = account_id
|
|
26
|
+
self.token_ids = token_ids or []
|
|
27
|
+
|
|
28
|
+
self._default_transaction_fee = 500_000_000
|
|
29
|
+
|
|
30
|
+
def set_account_id(self, account_id):
|
|
31
|
+
self._require_not_frozen()
|
|
32
|
+
self.account_id = account_id
|
|
33
|
+
return self
|
|
34
|
+
|
|
35
|
+
def add_token_id(self, token_id):
|
|
36
|
+
self._require_not_frozen()
|
|
37
|
+
self.token_ids.append(token_id)
|
|
38
|
+
return self
|
|
39
|
+
|
|
40
|
+
def build_transaction_body(self):
|
|
41
|
+
"""
|
|
42
|
+
Builds and returns the protobuf transaction body for token association.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
TransactionBody: The protobuf transaction body containing the token association details.
|
|
46
|
+
|
|
47
|
+
Raises:
|
|
48
|
+
ValueError: If account ID or token IDs are not set.
|
|
49
|
+
"""
|
|
50
|
+
if not self.account_id or not self.token_ids:
|
|
51
|
+
raise ValueError("Account ID and token IDs must be set.")
|
|
52
|
+
|
|
53
|
+
token_associate_body = token_associate_pb2.TokenAssociateTransactionBody(
|
|
54
|
+
account=self.account_id.to_proto(),
|
|
55
|
+
tokens=[token_id.to_proto() for token_id in self.token_ids]
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
transaction_body = self.build_base_transaction_body()
|
|
59
|
+
transaction_body.tokenAssociate.CopyFrom(token_associate_body)
|
|
60
|
+
|
|
61
|
+
return transaction_body
|
|
62
|
+
|
|
63
|
+
def _execute_transaction(self, client, transaction_proto):
|
|
64
|
+
"""
|
|
65
|
+
Executes the token association transaction using the provided client.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
client (Client): The client instance to use for execution.
|
|
69
|
+
transaction_proto (Transaction): The protobuf Transaction message.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
TransactionReceipt: The receipt from the network after transaction execution.
|
|
73
|
+
|
|
74
|
+
Raises:
|
|
75
|
+
Exception: If the transaction submission fails or receives an error response.
|
|
76
|
+
"""
|
|
77
|
+
response = client.token_stub.associateTokens(transaction_proto)
|
|
78
|
+
|
|
79
|
+
if response.nodeTransactionPrecheckCode != ResponseCode.OK:
|
|
80
|
+
error_code = response.nodeTransactionPrecheckCode
|
|
81
|
+
error_message = ResponseCode.get_name(error_code)
|
|
82
|
+
raise Exception(f"Error during transaction submission: {error_code} ({error_message})")
|
|
83
|
+
|
|
84
|
+
receipt = self.get_receipt(client)
|
|
85
|
+
return receipt
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
from hiero-sdk-python.transaction.transaction import Transaction
|
|
2
|
+
from hiero-sdk-python.hapi.services import token_create_pb2, basic_types_pb2
|
|
3
|
+
from hiero-sdk-python.response_code import ResponseCode
|
|
4
|
+
from cryptography.hazmat.primitives import serialization
|
|
5
|
+
|
|
6
|
+
class TokenCreateTransaction(Transaction):
|
|
7
|
+
"""
|
|
8
|
+
Represents a token creation transaction on the Hedera network.
|
|
9
|
+
|
|
10
|
+
This transaction creates a new token with specified properties, such as
|
|
11
|
+
name, symbol, decimals, initial supply, and treasury account.
|
|
12
|
+
|
|
13
|
+
Inherits from the base Transaction class and implements the required methods
|
|
14
|
+
to build and execute a token creation transaction.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, token_name=None, token_symbol=None, decimals=None, initial_supply=None,
|
|
18
|
+
treasury_account_id=None, admin_key=None, supply_key=None):
|
|
19
|
+
"""
|
|
20
|
+
Initializes a new TokenCreateTransaction instance with optional keyword arguments.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
token_name (str, optional): The name of the token.
|
|
24
|
+
token_symbol (str, optional): The symbol of the token.
|
|
25
|
+
decimals (int, optional): The number of decimals for the token.
|
|
26
|
+
initial_supply (int, optional): The initial supply of the token.
|
|
27
|
+
treasury_account_id (AccountId, optional): The treasury account ID.
|
|
28
|
+
admin_key (PrivateKey, optional): The admin key for the token.
|
|
29
|
+
supply_key (PrivateKey, optional): The supply key for the token.
|
|
30
|
+
|
|
31
|
+
"""
|
|
32
|
+
super().__init__()
|
|
33
|
+
self.token_name = token_name
|
|
34
|
+
self.token_symbol = token_symbol
|
|
35
|
+
self.decimals = decimals
|
|
36
|
+
self.initial_supply = initial_supply
|
|
37
|
+
self.treasury_account_id = treasury_account_id
|
|
38
|
+
self.admin_key = admin_key
|
|
39
|
+
self.supply_key = supply_key
|
|
40
|
+
|
|
41
|
+
self._default_transaction_fee = 3_000_000_000
|
|
42
|
+
|
|
43
|
+
def set_token_name(self, name):
|
|
44
|
+
self._require_not_frozen()
|
|
45
|
+
self.token_name = name
|
|
46
|
+
return self
|
|
47
|
+
|
|
48
|
+
def set_token_symbol(self, symbol):
|
|
49
|
+
self._require_not_frozen()
|
|
50
|
+
self.token_symbol = symbol
|
|
51
|
+
return self
|
|
52
|
+
|
|
53
|
+
def set_decimals(self, decimals):
|
|
54
|
+
self._require_not_frozen()
|
|
55
|
+
self.decimals = decimals
|
|
56
|
+
return self
|
|
57
|
+
|
|
58
|
+
def set_initial_supply(self, initial_supply):
|
|
59
|
+
self._require_not_frozen()
|
|
60
|
+
self.initial_supply = initial_supply
|
|
61
|
+
return self
|
|
62
|
+
|
|
63
|
+
def set_treasury_account_id(self, account_id):
|
|
64
|
+
self._require_not_frozen()
|
|
65
|
+
self.treasury_account_id = account_id
|
|
66
|
+
return self
|
|
67
|
+
|
|
68
|
+
def set_admin_key(self, admin_key):
|
|
69
|
+
self._require_not_frozen()
|
|
70
|
+
self.admin_key = admin_key
|
|
71
|
+
return self
|
|
72
|
+
|
|
73
|
+
def set_supply_key(self, supply_key):
|
|
74
|
+
self._require_not_frozen()
|
|
75
|
+
self.supply_key = supply_key
|
|
76
|
+
return self
|
|
77
|
+
|
|
78
|
+
def build_transaction_body(self):
|
|
79
|
+
"""
|
|
80
|
+
Builds and returns the protobuf transaction body for token creation.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
TransactionBody: The protobuf transaction body containing the token creation details.
|
|
84
|
+
|
|
85
|
+
Raises:
|
|
86
|
+
ValueError: If required fields are missing.
|
|
87
|
+
"""
|
|
88
|
+
if not all([
|
|
89
|
+
self.token_name,
|
|
90
|
+
self.token_symbol,
|
|
91
|
+
self.decimals is not None,
|
|
92
|
+
self.initial_supply is not None,
|
|
93
|
+
self.treasury_account_id
|
|
94
|
+
]):
|
|
95
|
+
raise ValueError("Missing required fields")
|
|
96
|
+
|
|
97
|
+
admin_key_proto = None
|
|
98
|
+
if self.admin_key:
|
|
99
|
+
admin_public_key_bytes = self.admin_key.public_key().to_bytes_raw()
|
|
100
|
+
admin_key_proto = basic_types_pb2.Key(ed25519=admin_public_key_bytes)
|
|
101
|
+
|
|
102
|
+
supply_key_proto = None
|
|
103
|
+
if self.supply_key:
|
|
104
|
+
supply_public_key_bytes = self.supply_key.public_key().to_bytes_raw()
|
|
105
|
+
supply_key_proto = basic_types_pb2.Key(ed25519=supply_public_key_bytes)
|
|
106
|
+
|
|
107
|
+
token_create_body = token_create_pb2.TokenCreateTransactionBody(
|
|
108
|
+
name=self.token_name,
|
|
109
|
+
symbol=self.token_symbol,
|
|
110
|
+
decimals=self.decimals,
|
|
111
|
+
initialSupply=self.initial_supply,
|
|
112
|
+
treasury=self.treasury_account_id.to_proto(),
|
|
113
|
+
adminKey=admin_key_proto,
|
|
114
|
+
supplyKey=supply_key_proto
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
transaction_body = self.build_base_transaction_body()
|
|
118
|
+
transaction_body.tokenCreation.CopyFrom(token_create_body)
|
|
119
|
+
|
|
120
|
+
return transaction_body
|
|
121
|
+
|
|
122
|
+
def _execute_transaction(self, client, transaction_proto):
|
|
123
|
+
"""
|
|
124
|
+
Executes the token creation transaction using the provided client.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
client (Client): The client instance to use for execution.
|
|
128
|
+
transaction_proto (Transaction): The protobuf Transaction message.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
TransactionReceipt: The receipt from the network after transaction execution.
|
|
132
|
+
|
|
133
|
+
Raises:
|
|
134
|
+
Exception: If the transaction submission fails or receives an error response.
|
|
135
|
+
"""
|
|
136
|
+
response = client.token_stub.createToken(transaction_proto)
|
|
137
|
+
|
|
138
|
+
if response.nodeTransactionPrecheckCode != ResponseCode.OK:
|
|
139
|
+
error_code = response.nodeTransactionPrecheckCode
|
|
140
|
+
error_message = ResponseCode.get_name(error_code)
|
|
141
|
+
raise Exception(f"Error during transaction submission: {error_code} ({error_message})")
|
|
142
|
+
|
|
143
|
+
receipt = self.get_receipt(client)
|
|
144
|
+
return receipt
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from hiero-sdk-python.transaction.transaction import Transaction
|
|
2
|
+
from hiero-sdk-python.hapi.services import token_delete_pb2
|
|
3
|
+
from hiero-sdk-python.response_code import ResponseCode
|
|
4
|
+
|
|
5
|
+
class TokenDeleteTransaction(Transaction):
|
|
6
|
+
"""
|
|
7
|
+
Represents a token deletion transaction on the Hedera network.
|
|
8
|
+
|
|
9
|
+
This transaction deletes a specified token, rendering it inactive.
|
|
10
|
+
|
|
11
|
+
Inherits from the base Transaction class and implements the required methods
|
|
12
|
+
to build and execute a token deletion transaction.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, token_id=None):
|
|
16
|
+
"""
|
|
17
|
+
Initializes a new TokenDeleteTransaction instance with optional token_id.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
token_id (TokenId, optional): The ID of the token to be deleted.
|
|
21
|
+
"""
|
|
22
|
+
super().__init__()
|
|
23
|
+
self.token_id = token_id
|
|
24
|
+
self._default_transaction_fee = 3_000_000_000
|
|
25
|
+
|
|
26
|
+
def set_token_id(self, token_id):
|
|
27
|
+
"""
|
|
28
|
+
Sets the ID of the token to be deleted.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
token_id (TokenId): The ID of the token to be deleted.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
TokenDeleteTransaction: Returns self for method chaining.
|
|
35
|
+
"""
|
|
36
|
+
self._require_not_frozen()
|
|
37
|
+
self.token_id = token_id
|
|
38
|
+
return self
|
|
39
|
+
|
|
40
|
+
def build_transaction_body(self):
|
|
41
|
+
"""
|
|
42
|
+
Builds and returns the protobuf transaction body for token deletion.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
TransactionBody: The protobuf transaction body containing the token deletion details.
|
|
46
|
+
|
|
47
|
+
Raises:
|
|
48
|
+
ValueError: If the token ID is missing.
|
|
49
|
+
"""
|
|
50
|
+
if not self.token_id:
|
|
51
|
+
raise ValueError("Missing required TokenID.")
|
|
52
|
+
|
|
53
|
+
token_delete_body = token_delete_pb2.TokenDeleteTransactionBody(
|
|
54
|
+
token=self.token_id.to_proto()
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
transaction_body = self.build_base_transaction_body()
|
|
58
|
+
transaction_body.tokenDeletion.CopyFrom(token_delete_body)
|
|
59
|
+
|
|
60
|
+
return transaction_body
|
|
61
|
+
|
|
62
|
+
def _execute_transaction(self, client, transaction_proto):
|
|
63
|
+
"""
|
|
64
|
+
Executes the token deletion transaction using the provided client.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
client (Client): The client instance to use for execution.
|
|
68
|
+
transaction_proto (Transaction): The protobuf Transaction message.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
TransactionReceipt: The receipt from the network after transaction execution.
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
Exception: If the transaction submission fails or receives an error response.
|
|
75
|
+
"""
|
|
76
|
+
response = client.token_stub.deleteToken(transaction_proto)
|
|
77
|
+
|
|
78
|
+
if response.nodeTransactionPrecheckCode != ResponseCode.OK:
|
|
79
|
+
error_code = response.nodeTransactionPrecheckCode
|
|
80
|
+
error_message = ResponseCode.get_name(error_code)
|
|
81
|
+
raise Exception(f"Error during transaction submission: {error_code} ({error_message})")
|
|
82
|
+
|
|
83
|
+
receipt = self.get_receipt(client)
|
|
84
|
+
return receipt
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from hiero-sdk-python.transaction.transaction import Transaction
|
|
2
|
+
from hiero-sdk-python.hapi.services import token_dissociate_pb2
|
|
3
|
+
from hiero-sdk-python.response_code import ResponseCode
|
|
4
|
+
|
|
5
|
+
class TokenDissociateTransaction(Transaction):
|
|
6
|
+
"""
|
|
7
|
+
Represents a token dissociate transaction on the Hedera network.
|
|
8
|
+
|
|
9
|
+
This transaction dissociates the specified tokens with an account,
|
|
10
|
+
meaning the account can no longer hold or transact with those tokens.
|
|
11
|
+
|
|
12
|
+
Inherits from the base Transaction class and implements the required methods
|
|
13
|
+
to build and execute a token dissociate transaction.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, account_id=None, token_ids=None):
|
|
17
|
+
"""
|
|
18
|
+
Initializes a new TokenDissociateTransaction instance with default values.
|
|
19
|
+
"""
|
|
20
|
+
super().__init__()
|
|
21
|
+
self.account_id = account_id
|
|
22
|
+
self.token_ids = token_ids or []
|
|
23
|
+
|
|
24
|
+
self._default_transaction_fee = 500_000_000
|
|
25
|
+
|
|
26
|
+
def set_account_id(self, account_id):
|
|
27
|
+
self._require_not_frozen()
|
|
28
|
+
self.account_id = account_id
|
|
29
|
+
return self
|
|
30
|
+
|
|
31
|
+
def add_token_id(self, token_id):
|
|
32
|
+
self._require_not_frozen()
|
|
33
|
+
self.token_ids.append(token_id)
|
|
34
|
+
return self
|
|
35
|
+
|
|
36
|
+
def build_transaction_body(self):
|
|
37
|
+
"""
|
|
38
|
+
Builds and returns the protobuf transaction body for token dissociation.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
TransactionBody: The protobuf transaction body containing the token dissociation details.
|
|
42
|
+
|
|
43
|
+
Raises:
|
|
44
|
+
ValueError: If account ID or token IDs are not set.
|
|
45
|
+
"""
|
|
46
|
+
if not self.account_id or not self.token_ids:
|
|
47
|
+
raise ValueError("Account ID and token IDs must be set.")
|
|
48
|
+
|
|
49
|
+
token_dissociate_body = token_dissociate_pb2.TokenDissociateTransactionBody(
|
|
50
|
+
account=self.account_id.to_proto(),
|
|
51
|
+
tokens=[token_id.to_proto() for token_id in self.token_ids]
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
transaction_body = self.build_base_transaction_body()
|
|
55
|
+
transaction_body.tokenDissociate.CopyFrom(token_dissociate_body)
|
|
56
|
+
|
|
57
|
+
return transaction_body
|
|
58
|
+
|
|
59
|
+
def _execute_transaction(self, client, transaction_proto):
|
|
60
|
+
"""
|
|
61
|
+
Executes the token dissociation transaction using the provided client.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
client (Client): The client instance to use for execution.
|
|
65
|
+
transaction_proto (Transaction): The protobuf Transaction message.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
TransactionReceipt: The receipt from the network after transaction execution.
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
Exception: If the transaction submission fails or receives an error response.
|
|
72
|
+
"""
|
|
73
|
+
response = client.token_stub.dissociateTokens(transaction_proto)
|
|
74
|
+
|
|
75
|
+
if response.nodeTransactionPrecheckCode != ResponseCode.OK:
|
|
76
|
+
error_code = response.nodeTransactionPrecheckCode
|
|
77
|
+
error_message = ResponseCode.get_name(error_code)
|
|
78
|
+
raise Exception(f"Error during transaction submission: {error_code} ({error_message})")
|
|
79
|
+
|
|
80
|
+
receipt = self.get_receipt(client)
|
|
81
|
+
return receipt
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from hiero-sdk-python.hapi.services import basic_types_pb2
|
|
2
|
+
|
|
3
|
+
class TokenId:
|
|
4
|
+
def __init__(self, shard=0, realm=0, num=0):
|
|
5
|
+
self.shard = shard
|
|
6
|
+
self.realm = realm
|
|
7
|
+
self.num = num
|
|
8
|
+
|
|
9
|
+
@classmethod
|
|
10
|
+
def from_proto(cls, token_id_proto):
|
|
11
|
+
"""
|
|
12
|
+
Creates a TokenId instance from a protobuf TokenID object.
|
|
13
|
+
"""
|
|
14
|
+
return cls(
|
|
15
|
+
shard=token_id_proto.shardNum,
|
|
16
|
+
realm=token_id_proto.realmNum,
|
|
17
|
+
num=token_id_proto.tokenNum
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
def to_proto(self):
|
|
21
|
+
"""
|
|
22
|
+
Converts the TokenId instance to a protobuf TokenID object.
|
|
23
|
+
"""
|
|
24
|
+
token_id_proto = basic_types_pb2.TokenID()
|
|
25
|
+
token_id_proto.shardNum = self.shard
|
|
26
|
+
token_id_proto.realmNum = self.realm
|
|
27
|
+
token_id_proto.tokenNum = self.num
|
|
28
|
+
return token_id_proto
|
|
29
|
+
|
|
30
|
+
def __str__(self):
|
|
31
|
+
"""
|
|
32
|
+
Returns the string representation of the TokenId in the format 'shard.realm.num'.
|
|
33
|
+
"""
|
|
34
|
+
return f"{self.shard}.{self.realm}.{self.num}"
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def from_string(cls, token_id_str):
|
|
38
|
+
"""
|
|
39
|
+
Parses a string in the format 'shard.realm.num' to create a TokenId instance.
|
|
40
|
+
"""
|
|
41
|
+
parts = token_id_str.strip().split('.')
|
|
42
|
+
if len(parts) != 3:
|
|
43
|
+
raise ValueError("Invalid TokenId format. Expected 'shard.realm.num'")
|
|
44
|
+
return cls(shard=int(parts[0]), realm=int(parts[1]), num=int(parts[2]))
|