Skip to content

Commit c354f0c

Browse files
feat(tck): implement deleteFile JSON-RPC method (hiero-ledger#2571)
Signed-off-by: Siddhartha Ganguly <gangulysiddhartha22@gmail.com>
1 parent 23e1a69 commit c354f0c

5 files changed

Lines changed: 61 additions & 25 deletions

File tree

src/hiero_sdk_python/file/file_delete_transaction.py

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from hiero_sdk_python.hapi.services.schedulable_transaction_body_pb2 import (
1010
SchedulableTransactionBody,
1111
)
12+
from hiero_sdk_python.hapi.services.transaction_pb2 import TransactionBody
1213
from hiero_sdk_python.hbar import Hbar
1314
from hiero_sdk_python.transaction.transaction import Transaction
1415

@@ -19,17 +20,14 @@
1920
class FileDeleteTransaction(Transaction):
2021
"""
2122
Represents a file deletion transaction on the network.
22-
2323
This transaction deletes a specified file, rendering it inactive.
24-
2524
Inherits from the base Transaction class and implements the required methods
2625
to build and execute a file deletion transaction.
2726
"""
2827

2928
def __init__(self, file_id: FileId | None = None):
3029
"""
3130
Initializes a new FileDeleteTransaction instance with optional file_id.
32-
3331
Args:
3432
file_id (FileId, optional): The ID of the file to be deleted.
3533
"""
@@ -40,36 +38,27 @@ def __init__(self, file_id: FileId | None = None):
4038
def set_file_id(self, file_id: FileId) -> FileDeleteTransaction:
4139
"""
4240
Sets the ID of the file to be deleted.
43-
4441
Args:
4542
file_id (FileId): The ID of the file to be deleted.
46-
4743
Returns:
4844
FileDeleteTransaction: Returns self for method chaining.
4945
"""
5046
self._require_not_frozen()
5147
self.file_id = file_id
5248
return self
5349

54-
def _build_proto_body(self):
50+
def _build_proto_body(self) -> FileDeleteTransactionBody:
5551
"""
5652
Returns the protobuf body for the file delete transaction.
5753
5854
Returns:
5955
FileDeleteTransactionBody: The protobuf body for this transaction.
60-
61-
Raises:
62-
ValueError: If file_id is not set.
6356
"""
64-
if self.file_id is None:
65-
raise ValueError("Missing required FileID")
57+
return FileDeleteTransactionBody(fileID=self.file_id._to_proto() if self.file_id is not None else None)
6658

67-
return FileDeleteTransactionBody(fileID=self.file_id._to_proto())
68-
69-
def build_transaction_body(self):
59+
def build_transaction_body(self) -> TransactionBody:
7060
"""
7161
Builds and returns the protobuf transaction body for file deletion.
72-
7362
Returns:
7463
TransactionBody: The protobuf transaction body containing the file deletion details.
7564
"""
@@ -81,7 +70,6 @@ def build_transaction_body(self):
8170
def build_scheduled_body(self) -> SchedulableTransactionBody:
8271
"""
8372
Builds the scheduled transaction body for this file delete transaction.
84-
8573
Returns:
8674
SchedulableTransactionBody: The built scheduled transaction body.
8775
"""
@@ -93,13 +81,10 @@ def build_scheduled_body(self) -> SchedulableTransactionBody:
9381
def _get_method(self, channel: _Channel) -> _Method:
9482
"""
9583
Gets the method to execute the file delete transaction.
96-
9784
This internal method returns a _Method object containing the appropriate gRPC
9885
function to call when executing this transaction on the network.
99-
10086
Args:
10187
channel (_Channel): The channel containing service stubs
102-
10388
Returns:
10489
_Method: An object containing the transaction function to delete a file.
10590
"""

tck/handlers/file.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from hiero_sdk_python.file.file_contents_query import FileContentsQuery
44
from hiero_sdk_python.file.file_create_transaction import FileCreateTransaction
5+
from hiero_sdk_python.file.file_delete_transaction import FileDeleteTransaction
56
from hiero_sdk_python.file.file_id import FileId
67
from hiero_sdk_python.file.file_info import FileInfo
78
from hiero_sdk_python.file.file_info_query import FileInfoQuery
@@ -11,8 +12,8 @@
1112
from hiero_sdk_python.transaction.transaction_receipt import TransactionReceipt
1213
from tck.errors import JsonRpcError
1314
from tck.handlers.registry import rpc_method
14-
from tck.param.file import CreateFileParams, GetFileContentsParams, GetFileInfoParams
15-
from tck.response.file import CreateFileResponse, GetFileContentsResponse, GetFileInfoResponse
15+
from tck.param.file import CreateFileParams, DeleteFileParams, GetFileContentsParams, GetFileInfoParams
16+
from tck.response.file import CreateFileResponse, DeleteFileResponse, GetFileContentsResponse, GetFileInfoResponse
1617
from tck.util.client_utils import get_client
1718
from tck.util.constants import DEFAULT_GRPC_TIMEOUT
1819
from tck.util.key_utils import get_key_from_string, key_to_string
@@ -106,3 +107,22 @@ def get_file_info(params: GetFileInfoParams) -> GetFileInfoResponse:
106107

107108
info = query.execute(client)
108109
return _build_file_info_response(info)
110+
111+
112+
@rpc_method("deleteFile")
113+
def delete_file(params: DeleteFileParams) -> DeleteFileResponse:
114+
"""Delete a file."""
115+
client = get_client(params.sessionId)
116+
117+
transaction = FileDeleteTransaction().set_grpc_deadline(DEFAULT_GRPC_TIMEOUT)
118+
119+
if params.fileId is not None:
120+
transaction.set_file_id(FileId.from_string(params.fileId))
121+
122+
if params.commonTransactionParams is not None:
123+
params.commonTransactionParams.apply_common_params(transaction, client)
124+
125+
response = transaction.execute(client, wait_for_receipt=False)
126+
receipt: TransactionReceipt = response.get_receipt(client, validate_status=True)
127+
128+
return DeleteFileResponse(ResponseCode(receipt.status).name)

tck/param/file.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class GetFileContentsParams(BaseParams):
4545

4646
@classmethod
4747
def parse_json_params(cls, params: dict) -> GetFileContentsParams:
48+
"""Parse JSON-RPC params into a GetFileContentsParams instance."""
4849
return cls(
4950
sessionId=parse_session_id(params),
5051
fileId=params.get("fileId"),
@@ -63,3 +64,19 @@ class GetFileInfoParams(BaseParams):
6364
def parse_json_params(cls, params: dict) -> GetFileInfoParams:
6465
"""Parse JSON-RPC params into a GetFileInfoParams instance."""
6566
return cls(fileId=params.get("fileId"), sessionId=parse_session_id(params))
67+
68+
69+
@dataclass
70+
class DeleteFileParams(BaseTransactionParams):
71+
"""Parameters for deleting a file. Extends BaseTransactionParams to include common transaction parameters."""
72+
73+
fileId: str | None = None
74+
75+
@classmethod
76+
def parse_json_params(cls, params: dict) -> DeleteFileParams:
77+
78+
return cls(
79+
fileId=params.get("fileId"),
80+
sessionId=parse_session_id(params),
81+
commonTransactionParams=parse_common_transaction_params(params),
82+
)

tck/response/file.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
from dataclasses import dataclass, field
44

5+
from tck.response.base import StatusOnlyResponse
6+
57

68
@dataclass
79
class CreateFileResponse:
@@ -20,10 +22,17 @@ class GetFileContentsResponse:
2022

2123
@dataclass
2224
class GetFileInfoResponse:
25+
"""Response payload for getFileInfo."""
26+
2327
fileId: str | None = None
2428
size: str | None = None
2529
expirationTime: str | None = None
2630
isDeleted: bool | None = None
2731
keys: list[str] = field(default_factory=list)
2832
memo: str | None = None
2933
ledgerId: str | None = None
34+
35+
36+
@dataclass
37+
class DeleteFileResponse(StatusOnlyResponse):
38+
"""Response payload for deleteFile."""

tests/unit/file_delete_transaction_test.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,17 @@ def test_build_transaction_body(mock_account_ids, file_id):
2929
assert transaction_body.fileDelete.fileID == file_id._to_proto()
3030

3131

32-
def test_missing_file_id():
33-
"""Test that building a transaction without setting FileID raises a ValueError."""
32+
def test_missing_file_id(mock_account_ids):
33+
"""Test that building without FileID leaves fileID unset instead of raising."""
34+
account_id, _, node_account_id, _, _ = mock_account_ids
3435
delete_tx = FileDeleteTransaction()
36+
delete_tx.set_node_account_ids([node_account_id])
37+
delete_tx.operator_account_id = account_id
38+
39+
transaction_body = delete_tx.build_transaction_body()
3540

36-
with pytest.raises(ValueError, match="Missing required FileID"):
37-
delete_tx.build_transaction_body()
41+
assert transaction_body.HasField("fileDelete")
42+
assert not transaction_body.fileDelete.HasField("fileID")
3843

3944

4045
def test_set_file_id(file_id):

0 commit comments

Comments
 (0)