Skip to content

Commit 9a655f3

Browse files
authored
feat: add add_token_id() and add_nft_id() to TokenRejectTransaction (#2439)
Signed-off-by: cheese-cakee <farzanaman99@gmail.com>
1 parent 2953918 commit 9a655f3

2 files changed

Lines changed: 155 additions & 4 deletions

File tree

src/hiero_sdk_python/tokens/token_reject_transaction.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ def __init__(
5252
"""
5353
super().__init__()
5454
self.owner_id: AccountId | None = owner_id
55-
self.token_ids: list[TokenId] = token_ids if token_ids else []
56-
self.nft_ids: list[NftId] = nft_ids if nft_ids else []
55+
self.token_ids: list[TokenId] = list(token_ids) if token_ids else []
56+
self.nft_ids: list[NftId] = list(nft_ids) if nft_ids else []
5757

5858
def set_owner_id(self, owner_id: AccountId) -> TokenRejectTransaction:
5959
"""Set the owner account ID for rejected tokens."""
@@ -64,13 +64,51 @@ def set_owner_id(self, owner_id: AccountId) -> TokenRejectTransaction:
6464
def set_token_ids(self, token_ids: list[TokenId]) -> TokenRejectTransaction:
6565
"""Set the list of fungible token IDs to reject."""
6666
self._require_not_frozen()
67-
self.token_ids = token_ids
67+
self.token_ids = list(token_ids)
68+
return self
69+
70+
def add_token_id(self, token_id: TokenId) -> TokenRejectTransaction:
71+
"""
72+
Appends a fungible token ID to the list of tokens to reject.
73+
74+
Args:
75+
token_id (TokenId): The fungible token ID to add.
76+
77+
Returns:
78+
TokenRejectTransaction: This transaction instance (for chaining).
79+
80+
Raises:
81+
TypeError: If token_id is not a TokenId instance.
82+
"""
83+
self._require_not_frozen()
84+
if not isinstance(token_id, TokenId):
85+
raise TypeError("token_id must be a TokenId instance.")
86+
self.token_ids.append(token_id)
6887
return self
6988

7089
def set_nft_ids(self, nft_ids: list[NftId]) -> TokenRejectTransaction:
7190
"""Set the list of NFT IDs to reject."""
7291
self._require_not_frozen()
73-
self.nft_ids = nft_ids
92+
self.nft_ids = list(nft_ids)
93+
return self
94+
95+
def add_nft_id(self, nft_id: NftId) -> TokenRejectTransaction:
96+
"""
97+
Appends an NFT ID to the list of NFTs to reject.
98+
99+
Args:
100+
nft_id (NftId): The NFT ID to add.
101+
102+
Returns:
103+
TokenRejectTransaction: This transaction instance (for chaining).
104+
105+
Raises:
106+
TypeError: If nft_id is not a NftId instance.
107+
"""
108+
self._require_not_frozen()
109+
if not isinstance(nft_id, NftId):
110+
raise TypeError("nft_id must be a NftId instance.")
111+
self.nft_ids.append(nft_id)
74112
return self
75113

76114
def _build_proto_body(self):

tests/unit/token_reject_transaction_test.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,119 @@ def test_set_methods_require_not_frozen(mock_account_ids, nft_id, mock_client):
142142
reject_tx.set_nft_ids(nft_ids)
143143

144144

145+
def test_add_token_id(mock_account_ids):
146+
"""Test appending fungible token IDs one at a time."""
147+
_, _, _, token_id_1, token_id_2 = mock_account_ids
148+
149+
reject_tx = TokenRejectTransaction()
150+
151+
# First append starts from the default empty list and returns self for chaining
152+
tx_after_add = reject_tx.add_token_id(token_id_1)
153+
assert tx_after_add is reject_tx
154+
assert reject_tx.token_ids == [token_id_1]
155+
156+
# Second append preserves the existing entry and keeps insertion order
157+
reject_tx.add_token_id(token_id_2)
158+
assert reject_tx.token_ids == [token_id_1, token_id_2]
159+
160+
161+
def test_add_token_id_appends_to_preset_list(mock_account_ids):
162+
"""Test that add_token_id appends onto a list provided via the constructor/setter."""
163+
_, _, _, token_id_1, token_id_2 = mock_account_ids
164+
165+
reject_tx = TokenRejectTransaction(token_ids=[token_id_1])
166+
reject_tx.add_token_id(token_id_2)
167+
168+
assert reject_tx.token_ids == [token_id_1, token_id_2]
169+
170+
171+
def test_add_nft_id(mock_account_ids):
172+
"""Test appending NFT IDs one at a time."""
173+
_, _, _, token_id, _ = mock_account_ids
174+
nft_id_1 = NftId(token_id=token_id, serial_number=1)
175+
nft_id_2 = NftId(token_id=token_id, serial_number=2)
176+
177+
reject_tx = TokenRejectTransaction()
178+
179+
# First append starts from the default empty list and returns self for chaining
180+
tx_after_add = reject_tx.add_nft_id(nft_id_1)
181+
assert tx_after_add is reject_tx
182+
assert reject_tx.nft_ids == [nft_id_1]
183+
184+
# Second append preserves the existing entry and keeps insertion order
185+
reject_tx.add_nft_id(nft_id_2)
186+
assert reject_tx.nft_ids == [nft_id_1, nft_id_2]
187+
188+
189+
def test_add_methods_require_not_frozen(mock_account_ids, nft_id, mock_client):
190+
"""Test that add_token_id and add_nft_id are rejected once the transaction is frozen."""
191+
_, _, _, token_id, _ = mock_account_ids
192+
193+
reject_tx = TokenRejectTransaction()
194+
reject_tx.freeze_with(mock_client)
195+
196+
with pytest.raises(Exception, match="Transaction is immutable; it has been frozen"):
197+
reject_tx.add_token_id(token_id)
198+
199+
with pytest.raises(Exception, match="Transaction is immutable; it has been frozen"):
200+
reject_tx.add_nft_id(nft_id)
201+
202+
203+
def test_add_token_id_rejects_invalid_type(mock_account_ids):
204+
"""Test that add_token_id rejects a value that is not a TokenId instance."""
205+
_, _, _, token_id, _ = mock_account_ids
206+
nft_id = NftId(token_id=token_id, serial_number=1)
207+
208+
reject_tx = TokenRejectTransaction()
209+
210+
with pytest.raises(TypeError, match="token_id must be a TokenId instance."):
211+
reject_tx.add_token_id(nft_id)
212+
213+
with pytest.raises(TypeError, match="token_id must be a TokenId instance."):
214+
reject_tx.add_token_id("0.0.100")
215+
216+
# The invalid inputs must not have been appended.
217+
assert reject_tx.token_ids == []
218+
219+
220+
def test_add_nft_id_rejects_invalid_type(mock_account_ids):
221+
"""Test that add_nft_id rejects a value that is not a NftId instance."""
222+
_, _, _, token_id, _ = mock_account_ids
223+
224+
reject_tx = TokenRejectTransaction()
225+
226+
with pytest.raises(TypeError, match="nft_id must be a NftId instance."):
227+
reject_tx.add_nft_id(token_id)
228+
229+
with pytest.raises(TypeError, match="nft_id must be a NftId instance."):
230+
reject_tx.add_nft_id("0.0.100")
231+
232+
# The invalid inputs must not have been appended.
233+
assert reject_tx.nft_ids == []
234+
235+
236+
def test_add_id_methods_do_not_mutate_caller_lists(mock_account_ids):
237+
"""Test that add_token_id/add_nft_id do not mutate lists passed to the constructor."""
238+
_, _, _, token_id_1, token_id_2 = mock_account_ids
239+
nft_id_1 = NftId(token_id=token_id_1, serial_number=1)
240+
nft_id_2 = NftId(token_id=token_id_1, serial_number=2)
241+
242+
token_ids = [token_id_1]
243+
nft_ids = [nft_id_1]
244+
245+
reject_tx = TokenRejectTransaction(token_ids=token_ids, nft_ids=nft_ids)
246+
reject_tx.add_token_id(token_id_2)
247+
reject_tx.add_nft_id(nft_id_2)
248+
249+
# The transaction reflects the appended IDs.
250+
assert reject_tx.token_ids == [token_id_1, token_id_2]
251+
assert reject_tx.nft_ids == [nft_id_1, nft_id_2]
252+
253+
# The caller's original lists remain untouched.
254+
assert token_ids == [token_id_1]
255+
assert nft_ids == [nft_id_1]
256+
257+
145258
def test_reject_transaction_can_execute(mock_account_ids):
146259
"""Test that a reject transaction can be executed successfully."""
147260
account_id, owner_account_id, _, token_id, _ = mock_account_ids

0 commit comments

Comments
 (0)