Skip to content

Commit 82ba211

Browse files
committed
rebase
Signed-off-by: emiliyank <e.kadiyski@gmail.com>
1 parent ae4d328 commit 82ba211

File tree

4 files changed

+590
-6
lines changed

4 files changed

+590
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
2828
- EvmAddress class
2929
- `alias`, `staked_account_id`, `staked_node_id` and `decline_staking_reward` fields to AccountCreateTransaction
3030
- `staked_account_id`, `staked_node_id` and `decline_staking_reward` fields to AccountInfo
31-
- Added `examples/token_create_transaction_supply_key.py` to demonstrate token creation with and without a supply key.
3231
- Added `examples/token_create_transaction_kyc_key.py` to demonstrate KYC key functionality, including creating tokens with/without KYC keys, granting/revoking KYC status, and understanding KYC requirements for token transfers.
3332
- Added BatchTransaction class
3433
- Add support for token metadata (bytes, max 100 bytes) in `TokenCreateTransaction`, including a new `set_metadata` setter, example, and tests. [#799]
3534
- Added `examples/token_create_transaction_token_fee_schedule.py` to demonstrate creating tokens with custom fee schedules and the consequences of not having it.
3635
- Added `examples/token_create_transaction_wipe_key.py` to demonstrate token wiping and the role of the wipe key.
3736
- Added `examples/account_allowance_approve_transaction_hbar.py` and `examples/account_allowance_delete_transaction_hbar.py`, deleted `examples/account_allowance_hbar.py`. [#775]
3837
- Added `docs\sdk_developers\training\receipts.md` as a training guide for users to understand hedera receipts.
38+
- Add `max_automatic_token_associations`, `staked_account_id`, `staked_node_id` and `decline_staking_reward` fields to `AccountUpdateTransaction` (#801)
3939

4040
### Changed
4141
- Upgraded step-security/harden-runner v2.13.2

src/hiero_sdk_python/account/account_update_transaction.py

Lines changed: 152 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from dataclasses import dataclass
77
from typing import Optional
88

9-
from google.protobuf.wrappers_pb2 import BoolValue, StringValue
9+
from google.protobuf.wrappers_pb2 import BoolValue, Int32Value, StringValue
1010

1111
from hiero_sdk_python.account.account_id import AccountId
1212
from hiero_sdk_python.channels import _Channel
@@ -35,6 +35,14 @@ class AccountUpdateParams:
3535
account_memo (Optional[str]): The new memo for the account.
3636
receiver_signature_required (Optional[bool]): Whether receiver signature is required.
3737
expiration_time (Optional[Timestamp]): The new expiration time for the account.
38+
max_automatic_token_associations (Optional[int]): The maximum number of tokens that
39+
can be auto-associated with this account. Use -1 for unlimited, 0 for none.
40+
staked_account_id (Optional[AccountId]): The account to which this account is staking
41+
its balances. Mutually exclusive with staked_node_id.
42+
staked_node_id (Optional[int]): The node ID to which this account is staking
43+
its balances. Mutually exclusive with staked_account_id.
44+
decline_staking_reward (Optional[bool]): If true, the account declines receiving
45+
staking rewards.
3846
"""
3947

4048
account_id: Optional[AccountId] = None
@@ -43,6 +51,10 @@ class AccountUpdateParams:
4351
account_memo: Optional[str] = None
4452
receiver_signature_required: Optional[bool] = None
4553
expiration_time: Optional[Timestamp] = None
54+
max_automatic_token_associations: Optional[int] = None
55+
staked_account_id: Optional[AccountId] = None
56+
staked_node_id: Optional[int] = None
57+
decline_staking_reward: Optional[bool] = None
4658

4759

4860
class AccountUpdateTransaction(Transaction):
@@ -70,6 +82,10 @@ def __init__(self, account_params: Optional[AccountUpdateParams] = None):
7082
self.account_memo = params.account_memo
7183
self.receiver_signature_required = params.receiver_signature_required
7284
self.expiration_time = params.expiration_time
85+
self.max_automatic_token_associations = params.max_automatic_token_associations
86+
self.staked_account_id = params.staked_account_id
87+
self.staked_node_id = params.staked_node_id
88+
self.decline_staking_reward = params.decline_staking_reward
7389

7490
def set_account_id(self, account_id: Optional[AccountId]) -> "AccountUpdateTransaction":
7591
"""
@@ -161,6 +177,121 @@ def set_expiration_time(
161177
self.expiration_time = expiration_time
162178
return self
163179

180+
def set_max_automatic_token_associations(
181+
self, max_automatic_token_associations: Optional[int]
182+
) -> "AccountUpdateTransaction":
183+
"""
184+
Sets the maximum number of tokens that can be auto-associated with this account.
185+
186+
Args:
187+
max_automatic_token_associations (Optional[int]): The maximum number of tokens
188+
that can be auto-associated. Use -1 for unlimited, 0 for none.
189+
Must be >= -1.
190+
191+
Returns:
192+
AccountUpdateTransaction: This transaction instance.
193+
194+
Raises:
195+
ValueError: If max_automatic_token_associations is less than -1.
196+
"""
197+
self._require_not_frozen()
198+
if max_automatic_token_associations is not None and max_automatic_token_associations < -1:
199+
raise ValueError(
200+
"max_automatic_token_associations must be -1 (unlimited) or a non-negative integer."
201+
)
202+
self.max_automatic_token_associations = max_automatic_token_associations
203+
return self
204+
205+
def set_staked_account_id(
206+
self, staked_account_id: Optional[AccountId]
207+
) -> "AccountUpdateTransaction":
208+
"""
209+
Sets the account to which this account is staking its balances.
210+
211+
This field is mutually exclusive with staked_node_id. Setting this will
212+
clear any previously set staked_node_id. Passing ``None`` (or calling
213+
:func:`clear_staked_account_id`) removes staking and sends the sentinel
214+
AccountId (0.0.0) to the network.
215+
216+
Args:
217+
staked_account_id (Optional[AccountId]): The account to which this account
218+
will stake its balances. ``None`` clears the staking configuration.
219+
220+
Returns:
221+
AccountUpdateTransaction: This transaction instance.
222+
"""
223+
self._require_not_frozen()
224+
if staked_account_id is None:
225+
return self.clear_staked_account_id()
226+
self.staked_account_id = staked_account_id
227+
self.staked_node_id = None # Clear the other field in the oneOf
228+
return self
229+
230+
def set_staked_node_id(
231+
self, staked_node_id: Optional[int]
232+
) -> "AccountUpdateTransaction":
233+
"""
234+
Sets the node ID to which this account is staking its balances.
235+
236+
This field is mutually exclusive with staked_account_id. Setting this will
237+
clear any previously set staked_account_id. Passing ``None`` (or calling
238+
:func:`clear_staked_node_id`) removes staking and sends the sentinel value (-1).
239+
240+
Args:
241+
staked_node_id (Optional[int]): The node ID to which this account will stake
242+
its balances. ``None`` clears the staking configuration.
243+
244+
Returns:
245+
AccountUpdateTransaction: This transaction instance.
246+
"""
247+
self._require_not_frozen()
248+
if staked_node_id is None:
249+
return self.clear_staked_node_id()
250+
self.staked_node_id = staked_node_id
251+
self.staked_account_id = None # Clear the other field in the oneOf
252+
return self
253+
254+
def clear_staked_account_id(self) -> "AccountUpdateTransaction":
255+
"""
256+
Clears staking to an account by setting the sentinel AccountId (0.0.0).
257+
258+
Returns:
259+
AccountUpdateTransaction: This transaction instance.
260+
"""
261+
self._require_not_frozen()
262+
self.staked_account_id = AccountId(0, 0, 0)
263+
self.staked_node_id = None
264+
return self
265+
266+
def clear_staked_node_id(self) -> "AccountUpdateTransaction":
267+
"""
268+
Clears staking to a node by setting the sentinel node ID (-1).
269+
270+
Returns:
271+
AccountUpdateTransaction: This transaction instance.
272+
"""
273+
self._require_not_frozen()
274+
self.staked_node_id = -1
275+
self.staked_account_id = None
276+
return self
277+
278+
def set_decline_staking_reward(
279+
self, decline_staking_reward: Optional[bool]
280+
) -> "AccountUpdateTransaction":
281+
"""
282+
Sets whether the account declines receiving staking rewards.
283+
284+
Args:
285+
decline_staking_reward (Optional[bool]): If True, the account declines receiving
286+
staking rewards. If False or None, the account will receive rewards.
287+
288+
Returns:
289+
AccountUpdateTransaction: This transaction instance.
290+
"""
291+
self._require_not_frozen()
292+
self.decline_staking_reward = decline_staking_reward
293+
return self
294+
164295
def _build_proto_body(self):
165296
"""
166297
Returns the protobuf body for the account update transaction.
@@ -174,7 +305,7 @@ def _build_proto_body(self):
174305
if self.account_id is None:
175306
raise ValueError("Missing required AccountID to update")
176307

177-
return CryptoUpdateTransactionBody(
308+
proto_body = CryptoUpdateTransactionBody(
178309
accountIDToUpdate=self.account_id._to_proto(),
179310
key=self.key._to_proto() if self.key else None,
180311
memo=StringValue(value=self.account_memo) if self.account_memo is not None else None,
@@ -187,8 +318,26 @@ def _build_proto_body(self):
187318
if self.receiver_signature_required is not None
188319
else None
189320
),
321+
max_automatic_token_associations=(
322+
Int32Value(value=self.max_automatic_token_associations)
323+
if self.max_automatic_token_associations is not None
324+
else None
325+
),
326+
decline_reward=(
327+
BoolValue(value=self.decline_staking_reward)
328+
if self.decline_staking_reward is not None
329+
else None
330+
),
190331
)
191332

333+
# Handle staked_id oneOf: only one can be set
334+
if self.staked_account_id is not None:
335+
proto_body.staked_account_id.CopyFrom(self.staked_account_id._to_proto())
336+
elif self.staked_node_id is not None:
337+
proto_body.staked_node_id = self.staked_node_id
338+
339+
return proto_body
340+
192341
def build_transaction_body(self):
193342
"""
194343
Builds the transaction body for this account update transaction.
@@ -227,3 +376,4 @@ def _get_method(self, channel: _Channel) -> _Method:
227376
_Method: An object containing the transaction function to update an account.
228377
"""
229378
return _Method(transaction_func=channel.crypto.updateAccount, query_func=None)
379+

0 commit comments

Comments
 (0)