Skip to content

Commit a9cc775

Browse files
tannaya7danielmarv
andauthored
feat(tck): implement appendFile JSON-RPC method (#2631)
Signed-off-by: tannaya7 <234580934+tannaya7@users.noreply.github.com> Signed-off-by: Ntege Daniel <danientege785@gmail.com> Co-authored-by: tannaya7 <234580934+tannaya7@users.noreply.github.com> Co-authored-by: Daniel Ntege <danientege785@gmail.com>
1 parent 19e7f37 commit a9cc775

2 files changed

Lines changed: 70 additions & 2 deletions

File tree

tck/handlers/file.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
from hiero_sdk_python.file.file_append_transaction import FileAppendTransaction
34
from hiero_sdk_python.file.file_contents_query import FileContentsQuery
45
from hiero_sdk_python.file.file_create_transaction import FileCreateTransaction
56
from hiero_sdk_python.file.file_delete_transaction import FileDeleteTransaction
@@ -9,9 +10,17 @@
910
from hiero_sdk_python.hbar import Hbar
1011
from hiero_sdk_python.response_code import ResponseCode
1112
from hiero_sdk_python.timestamp import Timestamp
13+
from hiero_sdk_python.transaction.transaction_receipt import TransactionReceipt
1214
from tck.errors import JsonRpcError
1315
from tck.handlers.registry import rpc_method
14-
from tck.param.file import CreateFileParams, DeleteFileParams, GetFileContentsParams, GetFileInfoParams
16+
from tck.param.file import (
17+
AppendFileParams,
18+
CreateFileParams,
19+
DeleteFileParams,
20+
GetFileContentsParams,
21+
GetFileInfoParams,
22+
)
23+
from tck.response.base import StatusOnlyResponse
1524
from tck.response.file import CreateFileResponse, DeleteFileResponse, GetFileContentsResponse, GetFileInfoResponse
1625
from tck.util.client_utils import get_client
1726
from tck.util.constants import DEFAULT_GRPC_TIMEOUT
@@ -60,6 +69,40 @@ def create_file(params: CreateFileParams) -> CreateFileResponse:
6069
return CreateFileResponse(file_id, ResponseCode(receipt.status).name)
6170

6271

72+
def _build_append_file_transaction(params: AppendFileParams) -> FileAppendTransaction:
73+
transaction = FileAppendTransaction().set_grpc_deadline(DEFAULT_GRPC_TIMEOUT)
74+
75+
# Default to 0.0.0 so a missing fileId is rejected by the network with
76+
# INVALID_FILE_ID rather than raising a client-side ValueError (TCK FileId #5).
77+
transaction.set_file_id(FileId.from_string(params.fileId) if params.fileId is not None else FileId())
78+
79+
if params.contents is not None:
80+
transaction.set_contents(params.contents)
81+
82+
if params.chunkSize is not None:
83+
transaction.set_chunk_size(params.chunkSize)
84+
85+
if params.maxChunks is not None:
86+
transaction.set_max_chunks(params.maxChunks)
87+
88+
return transaction
89+
90+
91+
@rpc_method("appendFile")
92+
def append_file(params: AppendFileParams) -> StatusOnlyResponse:
93+
"""Append contents to a file."""
94+
client = get_client(params.sessionId)
95+
96+
transaction = _build_append_file_transaction(params)
97+
98+
if params.commonTransactionParams is not None:
99+
params.commonTransactionParams.apply_common_params(transaction, client)
100+
101+
receipts: list[TransactionReceipt] = transaction.execute_all(client, wait_for_receipt=True, validate_status=True)
102+
103+
return StatusOnlyResponse(ResponseCode(receipts[-1].status).name)
104+
105+
63106
@rpc_method("getFileContents")
64107
def get_file_contents(params: GetFileContentsParams) -> GetFileContentsResponse:
65108
client = get_client(params.sessionId)

tck/param/file.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from dataclasses import dataclass
44

55
from tck.param.base import BaseParams, BaseTransactionParams
6-
from tck.util.param_utils import parse_common_transaction_params, parse_session_id
6+
from tck.util.param_utils import parse_common_transaction_params, parse_session_id, to_int
77

88

99
@dataclass
@@ -35,6 +35,31 @@ def parse_json_params(cls, params: dict) -> CreateFileParams:
3535
)
3636

3737

38+
@dataclass
39+
class AppendFileParams(BaseTransactionParams):
40+
"""Parameters for appending contents to a file. Extends BaseTransactionParams to include common transaction parameters."""
41+
42+
fileId: str | None = None
43+
contents: str | None = None
44+
maxChunks: int | None = None
45+
chunkSize: int | None = None
46+
47+
@classmethod
48+
def parse_json_params(cls, params: dict) -> AppendFileParams:
49+
contents = params.get("contents")
50+
if not isinstance(contents, str):
51+
raise ValueError("contents is required and must be a string")
52+
53+
return cls(
54+
fileId=params.get("fileId"),
55+
contents=contents,
56+
maxChunks=to_int(params.get("maxChunks")),
57+
chunkSize=to_int(params.get("chunkSize")),
58+
sessionId=parse_session_id(params),
59+
commonTransactionParams=parse_common_transaction_params(params),
60+
)
61+
62+
3863
@dataclass
3964
class GetFileContentsParams(BaseParams):
4065
"""Parameters for getting a file's contents."""

0 commit comments

Comments
 (0)