Skip to content

feat(tck): implement createFile JSON-RPC method #2488

Description

@exploreriii

Problem

Created with guidance of claude - please verify

The TCK driver has a full file-service test specification (6 methods), but the Python TCK server implements none of them, so none of those suites can run against this SDK. The SDK side is already complete under src/hiero_sdk_python/file/ — this is TCK plumbing only.

This issue is the first of six and blocks the other five: it creates tck/param/file.py, tck/response/file.py, and tck/handlers/file.py, which the follow-up methods (getFileContents, getFileInfo, updateFile, deleteFile, appendFile) all build on — and the driver needs createFile to produce a file ID for every other file test.

Solution

Add a createFile handler wrapping FileCreateTransaction, modelled on the existing createTopic handler in tck/handlers/topic.py.

Method contract (from the spec):

Input Type Required Notes
keys string[] optional DER-encoded hex private/public keys; KeyLists are hex of serialized protobuf bytes
contents string optional File contents
expirationTime string optional Seconds since epoch
memo string optional UTF-8, max 100 bytes
commonTransactionParams object optional Already supported via tck/param/common.py

Outputs: fileId (string), status (string, receipt status name).

Implementation steps:

  1. Create tck/param/file.py with CreateFileParams(BaseTransactionParams) holding keys: list[str] | None, contents: str | None, expirationTime: int | None, memo: str | None, and a parse_json_params() classmethod. Use the helpers in tck/util/param_utils.py (non_empty_string_list, to_int, parse_session_id, parse_common_transaction_params) — see CreateTopicParams in tck/param/topic.py for the exact pattern, including the isinstance(keys, list) validation before parsing.

  2. Create tck/response/file.py with:

    @dataclass
    class CreateFileResponse:
        fileId: str | None = None
        status: str | None = None
  3. Create tck/handlers/file.py with the handler:

    @rpc_method("createFile")
    def create_file(params: CreateFileParams) -> CreateFileResponse:
        client = get_client(params.sessionId)
        transaction = FileCreateTransaction().set_grpc_deadline(DEFAULT_GRPC_TIMEOUT)
    
        if params.keys is not None:
            transaction.set_keys([get_key_from_string(k) for k in params.keys])
        if params.contents is not None:
            transaction.set_contents(params.contents)
        if params.expirationTime is not None:
            transaction.set_expiration_time(Timestamp(params.expirationTime, 0))
        if params.memo is not None:
            transaction.set_file_memo(params.memo)
    
        if params.commonTransactionParams is not None:
            params.commonTransactionParams.apply_common_params(transaction, client)
    
        response = transaction.execute(client, wait_for_receipt=False)
        receipt = response.get_receipt(client, validate_status=True)
    
        file_id = ""
        if receipt.status == ResponseCode.SUCCESS and receipt.file_id is not None:
            file_id = str(receipt.file_id)
        return CreateFileResponse(file_id, ResponseCode(receipt.status).name)
  4. Register the module — easy to miss: add file to the import tuple in tck/handlers/__init__.py. That import is what triggers the @rpc_method decorators; without it the method silently won't register and the driver gets MethodNotFoundError.

  5. Add tests/tck/create_file_handler_test.py following the existing handler-test pattern (mock the client, assert param→setter mapping and response shape).

Details that matter:

  • Timestamp(seconds, nanos) takes positional ints — same epoch-seconds pattern as tck/handlers/account.py (Timestamp(params.expirationTime, 0)).
  • get_key_from_string() (tck/util/key_utils.py) handles both private and public DER hex per element.
  • Only call a setter when the param is not None — omitted vs. explicitly-set are distinct test cases in the spec.

Acceptance criteria

  • createFile registered and dispatchable (get_all_handlers() contains it)
  • All inputs mapped; omitted params leave SDK defaults untouched
  • Returns fileId + status; fileId is empty string on non-SUCCESS
  • file module added to tck/handlers/__init__.py
  • Unit test added; uv run pytest tests/tck -q passes

Spec: https://github.com/hiero-ledger/hiero-sdk-tck/blob/main/docs/test-specifications/file-service/FileCreateTransaction.md

JS reference: https://github.com/hiero-ledger/hiero-sdk-js/blob/main/tck/methods/file.ts (createFile)

Metadata

Metadata

Assignees

Labels

approvedIssue has been approved by team memberlang: pythonUses Python programming languagescope: TCKinvolves engineering for the implementation of TCK method and moduleskill: intermediaterequires some knowledge of the codebase with some defined steps to implement or examples

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions