Skip to content

Conversation

@MonaaEid
Copy link
Contributor

@MonaaEid MonaaEid commented Jan 23, 2026

This pull request introduces a new TCK (Test Compatibility Kit) JSON-RPC server to the codebase

Related issue(s):
Fixes #1388

Notes for reviewer:

Checklist

  • Documented (Code comments)
  • Tested (unit, integration, etc.)

@codecov
Copy link

codecov bot commented Jan 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1576      +/-   ##
==========================================
+ Coverage   93.28%   93.34%   +0.05%     
==========================================
  Files         141      141              
  Lines        9100     9100              
==========================================
+ Hits         8489     8494       +5     
+ Misses        611      606       -5     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…anagement

Signed-off-by: MonaaEid <monaa_eid@hotmail.com>
@MonaaEid MonaaEid force-pushed the feat/1388-TCK-JSON-RPC-server branch from 5aedd08 to 9210bc4 Compare January 23, 2026 13:57
@MonaaEid MonaaEid changed the title feat: implement TCK JSON-RPC server with request handling and error m… feat: implement TCK JSON-RPC server Jan 23, 2026
@exploreriii exploreriii requested review from a team and Dosik13 January 24, 2026 00:35
@github-actions
Copy link

Hi, this is MergeConflictBot.
Your pull request cannot be merged because it contains merge conflicts.

Please resolve these conflicts locally and push the changes.

To assist you, please read:

Thank you for contributing!

Copy link
Contributor

@prajeeta15 prajeeta15 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall it looks good to me, but the code coverage is still 0% so that needs resolving.

https://app.codecov.io/gh/hiero-ledger/hiero-sdk-python/pull/1576

@Mounil2005
Copy link
Contributor

Nice implementation @MonaaEid! Clean architecture with good separation of concerns. Found a few issues to fix:

There is a Missing dependency:
Flask needs to be added to pyproject.toml:

dependencies = [
    # ... existing deps
    "flask>=3.0.0",
]

@aceppaluni
Copy link
Contributor

@MonaaEid This is great work!

I concur with @Mounil2005 and @prajeeta15. If you have any questions, let us know. We're happy to assist!

@MonaaEid
Copy link
Contributor Author

Thanks @aceppaluni, @Mounil2005, and @prajeeta15 for the review
I’ll write the tests and reach out again for your feedback

Copy link
Contributor

@Dosik13 Dosik13 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall, good work. I also think that the tck folder should be outside the src folder as it is a different service

"""
session_id = None
if isinstance(params, dict) and 'sessionId' in params:
session_id = params.pop('sessionId')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it a good idea to pop the params as we change the original dict?

raise
except Exception as e:
error = JsonRpcError(INTERNAL_ERROR, 'Internal error', str(e))
return build_json_rpc_error_response(error, None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here we can raise error instead of returning the build_json_rpc_error_response(). It is handled anyways in the safe_dispatch()

MonaaEid and others added 4 commits January 31, 2026 18:42
…anagement

Signed-off-by: MonaaEid <monaa_eid@hotmail.com>
…anagement

Signed-off-by: MonaaEid <monaa_eid@hotmail.com>
Signed-off-by: MontyPokemon <59332150+MonaaEid@users.noreply.github.com>
…anagement

Signed-off-by: MonaaEid <monaa_eid@hotmail.com>
@exploreriii exploreriii marked this pull request as ready for review February 1, 2026 00:20
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 1, 2026

Warning

Rate limit exceeded

@MonaaEid has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 16 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

Adds a TCK JSON-RPC 2.0 server and supporting infrastructure: Flask HTTP endpoint, protocol parsing and response builders, JSON-RPC error types, handler registry with SDK handlers (setup/reset), session-scoped client management, CLI entry, docs, and unit tests.

Changes

Cohort / File(s) Summary
Server & Entry
tck/server.py, tck/__init__.py, tck/__main__.py, tck/README.md, CHANGELOG.md
Adds Flask app, ServerConfig, JSON-RPC POST endpoint, start_server() entry point, module CLI (python -m tck), and documentation/changelog updates.
Protocol & Errors
tck/protocol.py, tck/errors.py
Implements JSON-RPC 2.0 parsing/validation, normalization, success/error response builders, JsonRpcError and standard JSON-RPC / HIERO error factories and constants.
Handler Registry & SDK Handlers
tck/handlers/registry.py, tck/handlers/__init__.py, tck/handlers/sdk.py
Adds decorator-based handler registry, dispatch / safe_dispatch with exception→JSON-RPC error mapping, request param validation, and setup/reset handlers that create/reset per-session SDK clients.
Client Management
tck/client_manager.py
Adds thread-safe in-memory session-keyed client registry with store_client, get_client, and remove_client, ensuring proper resource cleanup (close on replace/remove).
Packaging & Dev deps
pyproject.toml
Adds optional/dev tck dependency group including flask>=3.0.0 for running the TCK server.
Tests
tests/unit/tck/client_manager_test.py, tests/unit/tck/conftest.py, tests/unit/tck/handlers_test.py, tests/unit/tck/protocol_test.py
Adds unit tests and fixtures covering client manager lifecycle, protocol parsing/response formatting, handler registry registration/dispatch/safe_dispatch behavior, parameter validation, and error mapping.

Sequence Diagram(s)

sequenceDiagram
    participant TestDriver as Test Driver
    participant FlaskServer as Flask Server
    participant Protocol as Protocol Layer
    participant Registry as Handler Registry
    participant Handler as Handler (setup/reset)
    participant ClientStore as Client Manager

    TestDriver->>FlaskServer: POST JSON-RPC request
    FlaskServer->>Protocol: parse_json_rpc_request(raw)
    alt parse/structure error
        Protocol-->>FlaskServer: JsonRpcError (PARSE/INVALID_REQUEST)
        FlaskServer-->>TestDriver: JSON-RPC error response
    else valid request
        Protocol-->>FlaskServer: {method, params, id, sessionId}
        FlaskServer->>Registry: safe_dispatch(method, params, sessionId, id)
        Registry->>Handler: invoke handler(params, sessionId)
        alt setup
            Handler->>ClientStore: store_client(sessionId, client)
            ClientStore-->>Handler: stored
            Handler-->>Registry: result (sessionId)
        else reset
            Handler->>ClientStore: remove_client(sessionId)
            ClientStore-->>Handler: removed (client closed)
            Handler-->>Registry: result
        end
        Registry-->>FlaskServer: result or error dict
        FlaskServer->>Protocol: build_json_rpc_success_response / build_json_rpc_error_response
        Protocol-->>FlaskServer: response dict
        FlaskServer-->>TestDriver: JSON-RPC response
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 74.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: implement TCK JSON-RPC server' directly and clearly summarizes the main change, which is implementing a TCK JSON-RPC server infrastructure as required by issue #1388.
Description check ✅ Passed The description mentions introducing a TCK JSON-RPC server and references the related issue #1388, which is directly relevant to the changeset implementing this server infrastructure.
Linked Issues check ✅ Passed The PR implements all core objectives from issue #1388: HTTP server with configurable port, JSON-RPC 2.0 protocol layer, registry-based routing, session support, setup/reset handlers, error handling with required codes, and runnable as python -m tck.
Out of Scope Changes check ✅ Passed All changes align with issue #1388 scope: server infrastructure, protocol handling, client management, and core utility methods. No unrelated features or changes detected beyond the TCK server implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 27

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pyproject.toml (1)

40-54: ⚠️ Potential issue | 🟠 Major

Add [project.optional-dependencies] to expose Flask for TCK via pip extras.

The current project uses [dependency-groups] (PEP 735), which is for development tools only and is not recognized by pip. End users cannot install Flask with pip install hiero-sdk-python[tck]. To make the TCK server available as an optional dependency, add the following to pyproject.toml:

[project.optional-dependencies]
tck = ["flask>=3.0.0"]

This allows end users to run pip install hiero-sdk-python[tck] to get Flask, as documented in the comment.

Copilot AI review requested due to automatic review settings February 1, 2026 15:19
@MonaaEid MonaaEid marked this pull request as draft February 1, 2026 15:19
@MonaaEid MonaaEid review requested due to automatic review settings February 1, 2026 15:20
…anagement

Signed-off-by: MonaaEid <monaa_eid@hotmail.com>
Copy link
Contributor

@aceppaluni aceppaluni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MonaaEid This is looking great!!

The few coderabbit suggestions are good. I left a thumbs up on the ones I thought.

If you have questions let us know, we'd be happy to help!

Thank you!

@exploreriii exploreriii added the status: needs developer revision PR has requested changes that the developer needs to implement label Feb 6, 2026
@MonaaEid MonaaEid removed the status: needs developer revision PR has requested changes that the developer needs to implement label Feb 8, 2026
@MonaaEid MonaaEid requested a review from a team as a code owner February 8, 2026 21:27
@MonaaEid MonaaEid requested review from PavelSBorisov, nadineloepfe and stoqnkpL and removed request for Copilot February 8, 2026 21:27
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

…anagement

Signed-off-by: MonaaEid <monaa_eid@hotmail.com>
Copilot AI review requested due to automatic review settings February 9, 2026 00:08
@MonaaEid MonaaEid review requested due to automatic review settings February 9, 2026 00:11
Signed-off-by: MontyPokemon <59332150+MonaaEid@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 9, 2026 00:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces an initial TCK JSON-RPC 2.0 server implementation (Flask-based) plus supporting protocol/dispatch/client-management modules and unit tests, aiming to enable the Python SDK to participate in the Hiero SDK TCK infrastructure (Issue #1388).

Changes:

  • Added a Flask JSON-RPC server entrypoint and configuration (tck/server.py, tck/__main__.py).
  • Implemented JSON-RPC protocol parsing/response helpers, handler registry/dispatch, and per-session client management (tck/protocol.py, tck/handlers/*, tck/client_manager.py, tck/errors.py).
  • Added unit tests for protocol, handler dispatch/registry, and client manager; added Flask dependency/extras and updated changelog.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tck/server.py Flask JSON-RPC endpoint + server startup/config.
tck/protocol.py JSON-RPC request parsing/validation and response builders.
tck/errors.py JSON-RPC error codes + JsonRpcError helper class.
tck/client_manager.py Thread-safe per-session client storage/lifecycle management.
tck/handlers/registry.py Handler registration + dispatch/safe_dispatch + param validation.
tck/handlers/sdk.py Implements core TCK handlers (setup, reset) and client creation.
tck/handlers/__init__.py Auto-imports handler modules to trigger registration decorators.
tck/__init__.py Exposes start_server.
tck/__main__.py Enables python -m tck startup.
tck/README.md Minimal run instructions for the server.
tests/unit/tck/conftest.py Test fixtures for protocol parsing tests.
tests/unit/tck/protocol_test.py Unit tests for protocol parsing and response formatting.
tests/unit/tck/handlers_test.py Unit tests for handler registry/dispatch and error translation.
tests/unit/tck/client_manager_test.py Unit tests for client storage/retrieval/removal behavior.
tests/unit/tck/__init__.py Marks the test package.
pyproject.toml Adds Flask to dev deps and a tck optional dependency group.
CHANGELOG.md Adds changelog entry referencing the new TCK JSON-RPC server work.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +39 to +42
try:
if session_id is not None:
return handler(params, session_id)
return handler(params)
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dispatch() changes the call signature based on whether session_id is present. Since the TCK driver includes sessionId for parallel execution, many requests will have a non-None session_id, and any handler defined as def handler(params): ... will start failing with a TypeError that gets converted to INTERNAL_ERROR. Consider enforcing a consistent handler signature (e.g., always call handler(params, session_id) and require handlers to accept session_id: Optional[str] = None, or wrap handlers at registration time to accept an optional second argument).

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +53
# TCK dependencies are only needed for running the test server, not for SDK usage
tck = ["flask>=3.0.0"]
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tck/ is added at repo root, but the build is configured with [tool.pdm.build] package-dir = "src", so this package won't be included in the installed distribution. As a result, python -m tck (and any downstream import) will only work from a source checkout where . is on PYTHONPATH. Consider moving the TCK server under src/hiero_sdk_python/tck/ (and updating imports/tests/docs accordingly) or adjusting the build config to include the top-level tck package.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +22
for idx, node_address in enumerate(node_addresses):
account_id = AccountId(0, 0, 3 + idx)
node_obj = _Node(account_id, node_address, None)
node_objects.append(node_obj)
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Custom-network nodes are created with address_book=None, but _Node._get_channel() raises ValueError("No certificate available.") when transport security is enabled and no address book is present (because _fetch_server_certificate_pem() returns None). Since Network() defaults to network='testnet' (TLS enabled), any custom network configured via setup is likely to fail at first use. Consider constructing Network(network="local", nodes=...) / disabling transport security for custom networks, or providing the needed address-book/cert information for TLS.

Copilot uses AI. Check for mistakes.
Comment on lines +54 to +55
# If the response is already an error response, return it directly
if isinstance(response, dict) and 'error' in response:
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

response is treated as an error response solely by checking for an 'error' key. This will incorrectly bypass success-wrapping if a handler legitimately returns a result object that contains an error field (common in domain payloads). Consider detecting JSON-RPC error responses more strictly (e.g., require jsonrpc + id + error keys, or have safe_dispatch return a distinct sentinel/type for errors).

Suggested change
# If the response is already an error response, return it directly
if isinstance(response, dict) and 'error' in response:
# If the response is already a JSON-RPC 2.0 error response, return it directly
if (
isinstance(response, dict)
and response.get("jsonrpc") == "2.0"
and "id" in response
and "error" in response
):

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +23
if isinstance(request_in, str):
try:
return json.loads(request_in)
except json.JSONDecodeError:
return JsonRpcError(PARSE_ERROR, 'Parse error')

if isinstance(request_in, dict):
return request_in

return JsonRpcError(INVALID_REQUEST, 'Invalid Request')
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_normalize_request_input() treats any non-string, non-dict input as an invalid request, which means JSON-RPC batch requests (where the body is a list of request objects) will be rejected. If the goal is JSON-RPC 2.0 compliance (as described in the linked issue), consider adding batch support (parse/validate each element, and return an array of responses; for an empty batch return a single -32600 error).

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +45
if 'id' not in request:
return JsonRpcError(INVALID_REQUEST, 'Invalid Request')

method = request.get('method')
if not isinstance(method, str):
return JsonRpcError(INVALID_REQUEST, 'Invalid Request')
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id is only checked for presence, but JSON-RPC 2.0 restricts id to string/number/null (and disallows objects/arrays; booleans are also problematic since bool is an int in Python). Without validating the type, the server may echo back non-compliant IDs and confuse clients. Consider validating id type explicitly and returning INVALID_REQUEST when it's not a valid JSON-RPC id.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Comment on lines +10 to +43
def _create_node_objects(node_addresses: List[str]) -> List[_Node]:
"""Convert node addresses to _Node objects with generated AccountIds.
Args:
node_addresses: List of node address strings

Returns:
List of _Node objects with sequential AccountIds starting from 0.0.3
"""
node_objects = []
for idx, node_address in enumerate(node_addresses):
account_id = AccountId(0, 0, 3 + idx)
node_obj = _Node(account_id, node_address, None)
node_objects.append(node_obj)
return node_objects


def _create_custom_network_client(network_config: Dict[str, Any]) -> Client:
"""Create a client with custom network configuration.
Args:
network_config: Dictionary containing 'nodes' key with list of node addresses

Returns:
Configured Client instance

Raises:
JsonRpcError: If nodes configuration is invalid
"""
nodes = network_config.get('nodes')
if not isinstance(nodes, list) or len(nodes) == 0 or not all(isinstance(node, str) for node in nodes):
raise JsonRpcError(INVALID_PARAMS, 'Invalid params: nodes must be a non-empty list of strings')

node_objects = _create_node_objects(nodes)
network = Network(nodes=node_objects)
return Client(network)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, find where _Node is defined
rg "class _Node" -A 10

Repository: hiero-ledger/hiero-sdk-python

Length of output: 756


🏁 Script executed:

#!/bin/bash
# Check imports in the file to understand where _Node comes from
head -20 tck/handlers/sdk.py

Repository: hiero-ledger/hiero-sdk-python

Length of output: 872


🏁 Script executed:

#!/bin/bash
# Look for any existing tests related to this functionality
find tck -name "*.py" -type f | head -20

Repository: hiero-ledger/hiero-sdk-python

Length of output: 240


🏁 Script executed:

#!/bin/bash
# Search for _Node usage across the codebase
rg "_Node" -B 2 -A 2

Repository: hiero-ledger/hiero-sdk-python

Length of output: 27784


🏁 Script executed:

#!/bin/bash
# Check if there are tests for tck/handlers/sdk.py
find tck -name "*test*.py" -o -name "test_*.py" | xargs grep -l "handlers\|sdk" 2>/dev/null || echo "No tests found"

Repository: hiero-ledger/hiero-sdk-python

Length of output: 87


🏁 Script executed:

#!/bin/bash
# Check the third parameter's actual type annotation in _Node constructor
sed -n '/class _Node:/,/def __init__/p' src/hiero_sdk_python/node.py | head -20
cat src/hiero_sdk_python/node.py | sed -n '1,50p'

Repository: hiero-ledger/hiero-sdk-python

Length of output: 2092


Add test coverage for this handler or document the private API reliance.

The _Node constructor call is valid and matches the SDK's own usage pattern throughout the codebase, including in official documentation. However, the recommendation to add test coverage remains unaddressed—there are no tests for tck/handlers/sdk.py, meaning this code path could silently break on SDK updates. Consider adding a basic unit test that exercises _create_custom_network_client with valid node configurations, or at minimum add a comment noting the private API dependency and the need for smoke testing on SDK version upgrades.

Minor note: The type annotation for _Node's third parameter indicates NodeAddress, but the code (and SDK) pass None. This works but could be clarified with Optional[NodeAddress] in the SDK type hints.

Comment on lines +42 to +44
parsed_request = parse_json_rpc_request(request_json)
if isinstance(parsed_request, JsonRpcError):
return build_json_rpc_error_response(parsed_request, None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Include the request id in error responses when it's available.

Per JSON-RPC 2.0, the error response id must be Null only when the id could not be detected (e.g., parse error). When request_json is a valid dict with an id field but fails structural validation (e.g., missing method), the id should be propagated into the error response.

🛡️ Proposed fix
     # Parse and validate the JSON-RPC request
     parsed_request = parse_json_rpc_request(request_json)
     if isinstance(parsed_request, JsonRpcError):
-        return build_json_rpc_error_response(parsed_request, None)
+        # Use request id if available, else None per JSON-RPC 2.0 spec
+        req_id = request_json.get('id') if isinstance(request_json, dict) else None
+        return build_json_rpc_error_response(parsed_request, req_id)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you do this?

Comment on lines +1 to +26
"""Fixtures for JSON-RPC request tests."""
import pytest

@pytest.fixture
def valid_jsonrpc_request():
"""Returns a valid JSON-RPC request."""
return {
"jsonrpc": "2.0",
"method": "setup",
"params": {},
"id": 1,
}

@pytest.fixture
def invalid_json_request():
"""Returns a malformed JSON-RPC request."""
return '{"id": malformed}'

@pytest.fixture
def request_missing_fields():
"""Returns a JSON-RPC request missing the 'method' field."""
return {
"jsonrpc": "2.0",
"params": {},
"id": 1
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider expanding fixtures to cover more edge cases.

The current set covers the basics (valid, malformed JSON, missing method), but per the testing guidelines' emphasis on comprehensive coverage and edge cases, consider adding fixtures for:

  • A JSON-RPC notification (valid request without id)
  • A request with a string id (valid per JSON-RPC 2.0)
  • A request with an invalid jsonrpc version (e.g., "1.0")
  • A request whose params include a sessionId

These would benefit the dependent test files (protocol_test.py, handlers_test.py) and reduce inline duplication. As per coding guidelines, "Unit tests should be extensive" and should "Cover happy paths AND unhappy paths/edge cases" and "Test boundary conditions, null/None values, empty collections."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you do this?

Comment on lines +139 to +149
def test_dispatch_converts_precheck_error_to_hiero_error(self):
"""Test that dispatch converts PrecheckError to HIERO_ERROR."""
@register_handler("precheck_method")
def precheck_handler(_params):
raise PrecheckError(status=123, transaction_id="0.0.456", message="Account does not exist")

with pytest.raises(JsonRpcError) as excinfo:
dispatch("precheck_method", {}, None)

assert excinfo.value.code == HIERO_ERROR
assert "Hiero error" in excinfo.value.message
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find ResponseCode enum definition
fd -t py -E node_modules | xargs grep -l "class ResponseCode" | head -5

Repository: hiero-ledger/hiero-sdk-python

Length of output: 242


🏁 Script executed:

# Search for PrecheckError class
fd -t py -E node_modules | xargs grep -l "class PrecheckError" | head -5

Repository: hiero-ledger/hiero-sdk-python

Length of output: 242


🏁 Script executed:

# Look for ResponseCode enum members and their values
rg "class ResponseCode" -A 50 | head -100

Repository: hiero-ledger/hiero-sdk-python

Length of output: 3466


🏁 Script executed:

# Get the complete ResponseCode enum
cat src/hiero_sdk_python/response_code.py

Repository: hiero-ledger/hiero-sdk-python

Length of output: 14350


🏁 Script executed:

# Search for PrecheckError class and its __init__ method
rg "class PrecheckError" -A 20

Repository: hiero-ledger/hiero-sdk-python

Length of output: 1518


Use a known ResponseCode member for better test clarity, though the current code is technically safe.

The ResponseCode enum has a _missing_ classmethod that gracefully handles unknown integer values by creating dynamic enum members (e.g., UNKNOWN_CODE_123). So PrecheckError(status=123) will not fail—it creates a valid, though undocumented, status code. However, using an explicit ResponseCode member (e.g., ResponseCode.ACCOUNT_ID_DOES_NOT_EXIST = 60) makes the test intent clearer and less brittle to future enum changes.

🧰 Tools
🪛 Ruff (0.14.14)

[warning] 142-142: Missing return type annotation for private function precheck_handler

Add return type annotation: NoReturn

(ANN202)

Comment on lines +27 to +31
def test_response_formatting_success():
"""Test formatting of a successful JSON-RPC response."""
resp = build_json_rpc_success_response({"ok": True}, 1)
assert resp["jsonrpc"] == "2.0", "Expected jsonrpc version 2.0 in success response"
assert "result" in resp, "Expected 'result' key in success response"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Strengthen success response assertions.

The test verifies the response has jsonrpc and result keys, but doesn't assert the result value or id. This weakens the test's ability to detect regressions in response construction.

♻️ Proposed fix
 def test_response_formatting_success():
     """Test formatting of a successful JSON-RPC response."""
     resp = build_json_rpc_success_response({"ok": True}, 1)
     assert resp["jsonrpc"] == "2.0", "Expected jsonrpc version 2.0 in success response"
     assert "result" in resp, "Expected 'result' key in success response"
+    assert resp["result"] == {"ok": True}, "Expected result to match input"
+    assert resp["id"] == 1, "Expected id to match request_id"

As per coding guidelines, Assert public attributes exist and assert backward-compatible defaults are maintained.

…anagement

Signed-off-by: MonaaEid <monaa_eid@hotmail.com>
Comment on lines 1 to 2
# Start TCK JSON-RPC Server
python -m tck
Copy link
Contributor

@aceppaluni aceppaluni Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MonaaEid

From copilot:
tck/ is added at repo root, but the build is configured with [tool.pdm.build] package-dir = "src", so this package won't be included in the installed distribution. As a result, python -m tck (and any downstream import) will only work from a source checkout where . is on PYTHONPATH. Consider moving the TCK server under src/hiero_sdk_python/tck/ (and updating imports/tests/docs accordingly) or adjusting the build config to include the top-level tck package.

Which way do you want to go with tck?

@aceppaluni aceppaluni added the status: needs developer revision PR has requested changes that the developer needs to implement label Feb 9, 2026
dev = [
"pytest>=8.3.4",
"pytest-cov>=7.0.0",
"flask>=3.0.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need the flask here

Copy link
Contributor Author

@MonaaEid MonaaEid Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Dosik13 we need it for the unit tests, can't remove it until there's another suggestion

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what error occurs?

Copy link
Contributor Author

@MonaaEid MonaaEid Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need flask to be installed for the CI, I used it for the unit tests

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ohh ok, I will check it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the current changes, I’ll suggest removing flask from [dev] and adding a [tck] group to the default dependency groups.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@manishdait this should be optional, and the same issue will be existed too

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we add [tck] to default-groups, flask will be installed by default. Below is the example that i tested on my fork

[dependency-groups]
dev = [
    "pytest>=8.3.4",
    "pytest-cov>=7.0.0",
]
lint = [
    "ruff>=0.14.9",
    "mypy>=1.18.2",
    "typing-extensions>=4.15.0",
]

# TCK dependencies are only needed for running the test server, not for SDK usage
tck = ["flask>=3.0.0"]

[tool.uv]
default-groups = ["dev", "lint", "tck"]
image

Copy link
Contributor Author

@MonaaEid MonaaEid Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't pass here :D and I will keep it Optional/test‑only since it's not a source code not all users interested in tck server, I waited for your dependencies pr to be merged to move it under the optional dependencies

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, we can leave it there for now and make a new PR for the CI workflow. How about that?

Comment on lines 1 to 2
# Start TCK JSON-RPC Server
python -m tck
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me explain my logic behind tck being separate from the src/hiero_sdk_python/...
The thing is that the tck should be separate from the internal part of the SDK. It is a separate server that should use transaction/queries from the src code, but it should do it externally and not be part of the code. The one thing I can suggest is that the tests/unit/tck should go tests/tck and I think it should be done this way so everything is structured and separated nicely. I think the build is okay, for me it works fine.

@MonaaEid
Copy link
Contributor Author

can't reply to the comment ..do what? @Dosik13
image

@MonaaEid
Copy link
Contributor Author

@Dosik13 what is your suggestion for the tck unit tests?


class JsonRpcError(Exception):
"""Class representing a JSON-RPC error."""
def __init__(self, code, message, data=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def __init__(self, code, message, data=None):
def __init__(self, code: int, message: str, data=None) -> None:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is for the previous one

@Dosik13
Copy link
Contributor

Dosik13 commented Feb 10, 2026

For the tck tests I suggest they can be moved from the folder - tests/unit/tck to tests/tck

@MonaaEid
Copy link
Contributor Author

MonaaEid commented Feb 10, 2026

For the tck tests I suggest they can be moved from the folder - tests/unit/tck to tests/tck

I mean this one ...also we need it to be included in the test checks
image

@MonaaEid MonaaEid removed the status: needs triage review PR needs a review from the triage team label Feb 10, 2026
@exploreriii
Copy link
Contributor

Hi @MonaaEid
Could you please resolve all the conversations, either as completed, or with a reason why they are dismissed or oustanding
This will help us review this swifter
Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: needs committer review PR needs a review from the committer team status: needs developer revision PR has requested changes that the developer needs to implement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Advanced]: Implement TCK JSON-RPC Server Infrastructure for Python SDK

7 participants