-
Notifications
You must be signed in to change notification settings - Fork 190
feat: implement TCK JSON-RPC server #1576
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: implement TCK JSON-RPC server #1576
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. @@ 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:
|
…anagement Signed-off-by: MonaaEid <monaa_eid@hotmail.com>
5aedd08 to
9210bc4
Compare
|
Hi, this is MergeConflictBot. Please resolve these conflicts locally and push the changes. To assist you, please read: Thank you for contributing! |
prajeeta15
left a comment
There was a problem hiding this 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
|
Nice implementation @MonaaEid! Clean architecture with good separation of concerns. Found a few issues to fix: There is a Missing dependency: dependencies = [
# ... existing deps
"flask>=3.0.0",
] |
|
@MonaaEid This is great work! I concur with @Mounil2005 and @prajeeta15. If you have any questions, let us know. We're happy to assist! |
|
Thanks @aceppaluni, @Mounil2005, and @prajeeta15 for the review |
Dosik13
left a comment
There was a problem hiding this 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
src/hiero_sdk_python/tck/protocol.py
Outdated
| """ | ||
| session_id = None | ||
| if isinstance(params, dict) and 'sessionId' in params: | ||
| session_id = params.pop('sessionId') |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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()
…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>
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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. WalkthroughAdds 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
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this 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 | 🟠 MajorAdd
[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 withpip install hiero-sdk-python[tck]. To make the TCK server available as an optional dependency, add the following topyproject.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.
…anagement Signed-off-by: MonaaEid <monaa_eid@hotmail.com>
aceppaluni
left a comment
There was a problem hiding this 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!
There was a problem hiding this 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>
Signed-off-by: MontyPokemon <59332150+MonaaEid@users.noreply.github.com>
There was a problem hiding this 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.
| try: | ||
| if session_id is not None: | ||
| return handler(params, session_id) | ||
| return handler(params) |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
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).
| # TCK dependencies are only needed for running the test server, not for SDK usage | ||
| tck = ["flask>=3.0.0"] |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
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.
| 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) |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
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.
| # If the response is already an error response, return it directly | ||
| if isinstance(response, dict) and 'error' in response: |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
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).
| # 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 | |
| ): |
| 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') |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
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).
| 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') |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
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.
There was a problem hiding this 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
| 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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, find where _Node is defined
rg "class _Node" -A 10Repository: 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.pyRepository: 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 -20Repository: 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 2Repository: 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.
| parsed_request = parse_json_rpc_request(request_json) | ||
| if isinstance(parsed_request, JsonRpcError): | ||
| return build_json_rpc_error_response(parsed_request, None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you do this?
| """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 | ||
| } |
There was a problem hiding this comment.
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
jsonrpcversion (e.g.,"1.0") - A request whose
paramsinclude asessionId
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."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you do this?
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# Find ResponseCode enum definition
fd -t py -E node_modules | xargs grep -l "class ResponseCode" | head -5Repository: 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 -5Repository: 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 -100Repository: hiero-ledger/hiero-sdk-python
Length of output: 3466
🏁 Script executed:
# Get the complete ResponseCode enum
cat src/hiero_sdk_python/response_code.pyRepository: hiero-ledger/hiero-sdk-python
Length of output: 14350
🏁 Script executed:
# Search for PrecheckError class and its __init__ method
rg "class PrecheckError" -A 20Repository: 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)
| 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" |
There was a problem hiding this comment.
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>
| # Start TCK JSON-RPC Server | ||
| python -m tck |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
| dev = [ | ||
| "pytest>=8.3.4", | ||
| "pytest-cov>=7.0.0", | ||
| "flask>=3.0.0", |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what error occurs?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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"]
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
| # Start TCK JSON-RPC Server | ||
| python -m tck |
There was a problem hiding this comment.
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.
|
can't reply to the comment ..do what? @Dosik13 |
|
@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): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| def __init__(self, code, message, data=None): | |
| def __init__(self, code: int, message: str, data=None) -> None: |
There was a problem hiding this comment.
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
|
For the tck tests I suggest they can be moved from the folder - |
|
Hi @MonaaEid |


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