Skip to content

Conversation

@mukundkumarjha
Copy link
Contributor

@mukundkumarjha mukundkumarjha commented Jan 28, 2026

Description:

Related issue(s):

Fixes #1512

Notes for reviewer:

Checklist

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

@github-actions
Copy link

[commit-verification-bot]
Hi, this is VerificationBot.
Your pull request cannot be merged as it has unverified commits.
View your commit verification status: Commits Tab.

To achieve verified status, please read:

Remember, you require a GPG key and each commit must be signed with:
git commit -S -s -m "Your message here"

Thank you for contributing!

From the Hiero Python SDK Team

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 28, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds optional child-record retrieval to TransactionRecordQuery via an include_children flag, maps protobuf child records into TransactionRecord instances (exposed as a children field), and includes an example, unit test, and changelog entry.

Changes

Cohort / File(s) Summary
Query Implementation
src/hiero_sdk_python/query/transaction_record_query.py
Added include_children constructor param and set_include_children(); _make_request() sets include_child_records; added _map_record_list() to convert proto responses; execute() maps child records and passes them to TransactionRecord._from_proto(); minor status/error mapping updates.
Data Model
src/hiero_sdk_python/transaction/transaction_record.py
Added public children: List[TransactionId] field; extended _from_proto() signature to accept and propagate children; minor (de)serialization formatting adjustments.
Examples
examples/transaction/transaction_record_with_children.py
New example demonstrating set_include_children(True), executing the query, and iterating over child records.
Tests
tests/unit/transaction_record_query_test.py
Added test_transaction_record_query_with_children_mapping verifying _map_record_list() maps proto child records into TransactionRecord objects.
Changelog
CHANGELOG.md
Added Unreleased entry documenting include_children support and updated maintainer guidelines link.

Sequence Diagram

sequenceDiagram
    participant Client as Client
    participant Query as TransactionRecordQuery
    participant Network as Network/Service
    participant Model as TransactionRecord

    Client->>Query: set_transaction_id(tx_id)
    Client->>Query: set_include_children(true)
    Client->>Query: execute(client)

    Query->>Query: _make_request()
    Query->>Network: getTxRecordByTxID(txID, include_child_records=true)
    Network-->>Query: response (parent + child records)

    Query->>Query: _map_record_list(child_records)
    Query->>Model: _from_proto(parent_proto, children=[...])
    Model-->>Query: TransactionRecord (with children)
    Query-->>Client: TransactionRecord (parent with children)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description references issue #1512 and mentions adding include_children support, but lacks detail about implementation specifics, changes made, testing results, or reviewer guidance. Provide more details about what was implemented, testing coverage, any issues encountered, and summary of key changes for reviewers.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: adding include_children support to TransactionRecordQuery. It is concise, clear, and specific.
Linked Issues check ✅ Passed The PR implements all primary coding requirements from issue #1512: include_children parameter with setter, children field in TransactionRecord, _map_record_list helper, request building, response parsing in execute(), and includes an example and unit tests.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the include_children feature as specified in issue #1512. The CHANGELOG.md entry and MAINTAINERS.md link update are standard maintenance items.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 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: 9

Caution

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

⚠️ Outside diff range comments (2)
src/hiero_sdk_python/transaction/transaction_record.py (1)

174-185: Critical bug: children parameter is ignored.

The children parameter passed to _from_proto (line 123) is completely overwritten by the local variable at line 174. This means child records passed from TransactionRecordQuery.execute() are never actually stored in the resulting TransactionRecord.

-        children: Optional[List["TransactionRecord"]] = None
         return cls(
             transaction_id=transaction_id,
             ...
-            children=children,
+            children=children,  # Use the parameter, not a new local variable

The fix should remove line 174 entirely so that the children parameter from line 123 is used:

🐛 Proposed fix
         for pending_airdrop in proto.new_pending_airdrops:
             new_pending_airdrops.append(
                 PendingAirdropRecord._from_proto(pending_airdrop)
             )

-        children: Optional[List["TransactionRecord"]] = None
         return cls(
             transaction_id=transaction_id,
             transaction_hash=proto.transactionHash,
src/hiero_sdk_python/query/transaction_record_query.py (1)

90-92: Avoid print() statements in production code.

Using print() for error logging is not appropriate for library code. This can cause unexpected output for SDK users and doesn't integrate with their logging configuration.

Consider using Python's logging module or removing the print statement entirely since the exception is re-raised anyway.

         except Exception as e:
-            print(f"Exception in _make_request: {e}")
             raise

Comment on lines +98 to +118
def test_transaction_record_query_with_children_mapping(transaction_id):

child_proto = transaction_record_pb2.TransactionRecord(
memo="Child Record"
)
child_proto.transactionID.CopyFrom(transaction_id._to_proto())

record_response = transaction_get_record_pb2.TransactionGetRecordResponse()

record_response.header.nodeTransactionPrecheckCode = ResponseCode.OK

record_response.transactionRecord.memo = "Parent Record"
record_response.transactionRecord.transactionID.CopyFrom(transaction_id._to_proto())

record_response.child_transaction_records.extend([child_proto, child_proto])

query = TransactionRecordQuery(transaction_id)
children = query._map_record_list(record_response.child_transaction_records)

assert len(children) == 2
assert children[0].transaction_memo == "Child Record"
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

Test coverage gaps for the new include_children feature.

Per the coding guidelines, unit tests should verify:

  1. Fluent setters return self: Missing test for set_include_children returning self for chaining.
  2. Backward-compatible defaults: Missing test that include_children defaults to False.
  3. Constructor behavior: Missing test for TransactionRecordQuery(transaction_id, include_children=True).
  4. Request construction: Missing test that _make_request() correctly sets include_child_records on the protobuf.
💚 Suggested additional tests
def test_set_include_children_returns_self(transaction_id):
    """Test that set_include_children returns self for method chaining."""
    query = TransactionRecordQuery(transaction_id)
    result = query.set_include_children(True)
    assert result is query  # Fluent interface check

def test_include_children_default_is_false():
    """Test that include_children defaults to False."""
    query = TransactionRecordQuery()
    assert query.include_children is False

def test_constructor_with_include_children(transaction_id):
    """Test constructor accepts include_children parameter."""
    query = TransactionRecordQuery(transaction_id, include_children=True)
    assert query.include_children is True
    assert query.transaction_id == transaction_id

def test_make_request_includes_children_flag(transaction_id):
    """Test that _make_request sets include_child_records correctly."""
    query = TransactionRecordQuery(transaction_id, include_children=True)
    request = query._make_request()
    assert request.transactionGetRecord.include_child_records is True

Based on learnings: "Assert fluent setters return self", "Assert backward-compatible defaults are maintained", "Test constructor behavior with valid inputs".

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: 1

Caution

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

⚠️ Outside diff range comments (4)
src/hiero_sdk_python/account/account_info.py (2)

12-109: Fix staking_info wiring (wrong class + unused variable).
StakingInfo is imported from the protobuf module and then used with .from_proto(), which doesn’t exist. Additionally, the computed staking_info is never assigned to account_info, so it’s always lost. This will either raise at runtime or silently drop staking data.

🐛 Proposed fix
-from hiero_sdk_python.hapi.services.basic_types_pb2 import StakingInfo
+from hiero_sdk_python.staking_info import StakingInfo
...
-        account_info: "AccountInfo" = cls(
+        account_info: "AccountInfo" = cls(
             account_id=AccountId._from_proto(proto.accountID) if proto.accountID else None,
             contract_account_id=proto.contractAccountID,
             is_deleted=proto.deleted,
             proxy_received=Hbar.from_tinybars(proto.proxyReceived),
             key=PublicKey._from_proto(proto.key) if proto.key else None,
             balance=Hbar.from_tinybars(proto.balance),
             receiver_signature_required=proto.receiverSigRequired,
             expiration_time=(
                 Timestamp._from_protobuf(proto.expirationTime) if proto.expirationTime else None
             ),
             auto_renew_period=(
                 Duration._from_proto(proto.autoRenewPeriod) if proto.autoRenewPeriod else None
             ),
             token_relationships=[
                 TokenRelationship._from_proto(relationship)
                 for relationship in proto.tokenRelationships
             ],
             account_memo=proto.memo,
             owned_nfts=proto.ownedNfts,
             max_automatic_token_associations=proto.max_automatic_token_associations,
+            staking_info=(
+                StakingInfo._from_proto(proto.staking_info)
+                if proto.HasField("staking_info")
+                else None
+            ),
         )
-
-        staking_info=(
-           StakingInfo.from_proto(proto.staking_info)
-           if proto.HasField("staking_info")
-           else None
-         )

And in _to_proto:

-            staking_info=(
-            self.staking_info.to_proto()
-            if self.staking_info is not None
-            else None
-          ),
+            staking_info=(
+                self.staking_info._to_proto()
+                if self.staking_info is not None
+                else None
+            ),

161-199: Fix staking_info labels in str/repr.
Current output prints the whole staking_info object for “Staked Account ID”, “Staked Node ID”, and “Decline Staking Reward”. This is misleading.

💡 Suggested adjustment
-            (self.staking_info, "Staked Account ID"),
-            (self.staking_info, "Staked Node ID"),
+            (self.staking_info.staked_account_id if self.staking_info else None, "Staked Account ID"),
+            (self.staking_info.staked_node_id if self.staking_info else None, "Staked Node ID"),
...
-        if self.staking_info is not None:
-            lines.append(f"Decline Staking Reward: {self.staking_info}")
+        if self.staking_info is not None:
+            lines.append(
+                f"Decline Staking Reward: {self.staking_info.decline_reward}"
+            )
...
-            f"staked_node_id={self.staking_info!r}, "
-            f"staked_account_id={self.staking_info!r}"
+            f"staking_info={self.staking_info!r}"
src/hiero_sdk_python/transaction/transaction_record.py (1)

119-186: Children are discarded in _from_proto.
The method accepts children but immediately overwrites it with None, so include‑children never surfaces in returned records.

🐛 Proposed fix
-    def _from_proto(
+    def _from_proto(
         cls,
         proto: transaction_record_pb2.TransactionRecord,
         transaction_id: Optional[TransactionId] = None,
-        children=None,
+        children: Optional[list["TransactionRecord"]] = None,
     ) -> "TransactionRecord":
...
-        children: Optional[List["TransactionRecord"]] = None
         return cls(
             transaction_id=transaction_id,
             transaction_hash=proto.transactionHash,
             transaction_memo=proto.memo,
             transaction_fee=proto.transactionFee,
             receipt=TransactionReceipt._from_proto(proto.receipt, transaction_id),
             token_transfers=token_transfers,
             nft_transfers=nft_transfers,
             transfers=transfers,
             new_pending_airdrops=new_pending_airdrops,
-            children=children,
+            children=children,
             call_result=(
                 ContractFunctionResult._from_proto(proto.contractCallResult)
                 if proto.HasField("contractCallResult")
                 else None
             ),
             prng_number=proto.prng_number,
             prng_bytes=proto.prng_bytes,
         )
src/hiero_sdk_python/query/transaction_record_query.py (1)

90-92: Remove print statement from exception handler.

The print statement introduces a side effect that could clutter logs or leak sensitive information. Exception handling should rely on the caller or logging framework, not direct prints. As per coding guidelines (REVIEW FOCUS 6), side effects like logging/prints should be flagged.

Suggested fix
         except Exception as e:
-            print(f"Exception in _make_request: {e}")
             raise

CHANGELOG.md Outdated
Comment on lines 132 to 136
<<<<<<< HEAD
- Refactored AccountInfo class to use the staking_info
=======
- chore: format tests/unit/mock_server.py with black (#1542)
>>>>>>> upstream
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 | 🔴 Critical

Resolve the merge conflict block before release.
The changelog contains conflict markers, which will break rendering and automation. Please remove the markers and keep the correct entries.

🔧 Suggested resolution
-<<<<<<< HEAD
-- Refactored AccountInfo class to use the staking_info
-=======
-- chore: format tests/unit/mock_server.py with black (`#1542`)
->>>>>>> upstream
+- Refactored AccountInfo class to use the staking_info
+- chore: format tests/unit/mock_server.py with black (`#1542`)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<<<<<<< HEAD
- Refactored AccountInfo class to use the staking_info
=======
- chore: format tests/unit/mock_server.py with black (#1542)
>>>>>>> upstream
- Refactored AccountInfo class to use the staking_info
- chore: format tests/unit/mock_server.py with black (`#1542`)

jwagantall and others added 4 commits January 28, 2026 16:03
Signed-off-by: Jessica G <jwagantall@linuxfoundation.org>
Signed-off-by: mukundkumarjha <mukundiiitg@gmail.com>
Signed-off-by: mukundkumarjha <mukundiiitg@gmail.com>
Signed-off-by: mukundkumarjha <mukundiiitg@gmail.com>
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: 0

Caution

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

⚠️ Outside diff range comments (1)
src/hiero_sdk_python/transaction/transaction_record.py (1)

174-186: Preserve provided child records (currently overwritten to None).

Line 174 resets children to None, discarding the list passed from TransactionRecordQuery.execute(). This breaks the new include_children feature because the parent record will never retain its child records.

🐛 Proposed fix
-        children: Optional[List["TransactionRecord"]] = None
+        if children is None:
+            children = []
         return cls(
             transaction_id=transaction_id,
             transaction_hash=proto.transactionHash,
             transaction_memo=proto.memo,
             transaction_fee=proto.transactionFee,
             receipt=TransactionReceipt._from_proto(proto.receipt, transaction_id),
             token_transfers=token_transfers,
             nft_transfers=nft_transfers,
             transfers=transfers,
             new_pending_airdrops=new_pending_airdrops,
-            children=children,
+            children=children,
             call_result=(
                 ContractFunctionResult._from_proto(proto.contractCallResult)
                 if proto.HasField("contractCallResult")
                 else None
             ),
             prng_number=proto.prng_number,
             prng_bytes=proto.prng_bytes,
         )

@exploreriii exploreriii requested a review from a team January 28, 2026 12:27
return self

def set_include_children(self, include_children):
self.include_children = include_children
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor suggestion consider adding a docstring

self.transaction_id : Optional[TransactionId] = transaction_id

self.transaction_id: Optional[TransactionId] = transaction_id
self.include_children = include_children
Copy link
Contributor

Choose a reason for hiding this comment

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

missing type hint

Suggested change
self.include_children = include_children
self.include_children: Optional[bool] = include_children


def _map_record_list(
self,
proto_records: List[transaction_get_record_pb2.TransactionGetRecordResponse],
Copy link
Contributor

Choose a reason for hiding this comment

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

must be

Suggested change
proto_records: List[transaction_get_record_pb2.TransactionGetRecordResponse],
proto_records: List[transaction_record_pb2.TransactionRecord],

cls,
proto: transaction_record_pb2.TransactionRecord,
transaction_id: Optional[TransactionId] = None,
children=None,
Copy link
Contributor

Choose a reason for hiding this comment

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

add type hinting children: Optional[List["TransactionRecord"]]=[]

PendingAirdropRecord._from_proto(pending_airdrop)
)

children: Optional[List["TransactionRecord"]] = None
Copy link
Contributor

Choose a reason for hiding this comment

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

this line can be romove

Copy link
Contributor

@manishdait manishdait left a comment

Choose a reason for hiding this comment

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

@mukundkumarjha, Thanks for PR added some required changes

Copy link
Contributor

@manishdait manishdait left a comment

Choose a reason for hiding this comment

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

@mukundkumarjha, Thanks for PR added some required changes

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.

@mukundkumarjha Thank you for your contribution!

I concur with @manishdait with the suggested changes.
If you need assistance please reach out.

@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!

Signed-off-by: Mukund Jha <mukundiiitg@gmail.com>
@mukundkumarjha mukundkumarjha marked this pull request as ready for review January 30, 2026 09:18
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: 3

Caution

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

⚠️ Outside diff range comments (1)
src/hiero_sdk_python/transaction/transaction_record.py (1)

123-186: ⚠️ Potential issue | 🔴 Critical

children is discarded, so include_children always yields None.
Line 174 overwrites the children parameter with None, so TransactionRecordQuery.execute() can never populate children and the example will crash when it calls len(record.children).

🔧 Proposed fix
-        children: Optional[List["TransactionRecord"]] = None
+        if children is None:
+            children = []
         return cls(
@@
-            children=children,
+            children=children,

Comment on lines +23 to +31
record = query.execute(client)

# 3. Demonstrate accessing the children
print(f"Parent Transaction ID: {record.transaction_id}")
print(f"Number of child records found: {len(record.children)}")

for i, child in enumerate(record.children):
print(f"Child {i+1} Status: {child.receipt.status}")

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:

# First, find and read the file in question
fd "transaction_record_with_children.py" --type f

Repository: hiero-ledger/hiero-sdk-python

Length of output: 129


🏁 Script executed:

# Check if the file exists and read its content
if [ -f "examples/transaction/transaction_record_with_children.py" ]; then
  wc -l examples/transaction/transaction_record_with_children.py
  echo "---"
  cat -n examples/transaction/transaction_record_with_children.py
else
  echo "File not found"
fi

Repository: hiero-ledger/hiero-sdk-python

Length of output: 1383


🏁 Script executed:

# Verify ResponseCode exists in hiero_sdk_python
find . -type f -name "*.py" | xargs grep -l "class ResponseCode" | head -5

Repository: hiero-ledger/hiero-sdk-python

Length of output: 112


🏁 Script executed:

# Check how ResponseCode is imported in other example files
find examples -type f -name "*.py" -exec grep -l "ResponseCode" {} \; | head -5

Repository: hiero-ledger/hiero-sdk-python

Length of output: 3862


🏁 Script executed:

# Look for patterns of receipt.status usage in examples
rg "receipt\.status" examples --type py -B 2 -A 2 | head -40

Repository: hiero-ledger/hiero-sdk-python

Length of output: 3540


🏁 Script executed:

# Check how ResponseCode is imported in those example files
head -20 examples/tokens/token_fee_schedule_update_transaction_fungible.py | grep -E "^(import|from)" | head -10

Repository: hiero-ledger/hiero-sdk-python

Length of output: 498


🏁 Script executed:

# Check if there's a general pattern for error handling in examples
head -30 examples/tokens/token_create_transaction_token_fee_schedule_key.py | grep -E "^(import|from)" | head -10

Repository: hiero-ledger/hiero-sdk-python

Length of output: 454


🏁 Script executed:

# Verify the ResponseCode import path can be used as suggested
head -5 src/hiero_sdk_python/response_code.py

Repository: hiero-ledger/hiero-sdk-python

Length of output: 154


🏁 Script executed:

# Check other transaction_record examples for patterns
find examples -name "*transaction_record*" -type f

Repository: hiero-ledger/hiero-sdk-python

Length of output: 172


🏁 Script executed:

# Look at how examples handle query results without receipt checks (queries vs transactions)
rg "\.execute\(client\)" examples/query --type py -A 3 | head -20

Repository: hiero-ledger/hiero-sdk-python

Length of output: 988


🏁 Script executed:

# Check the other transaction_record query example
cat -n examples/query/transaction_record_query.py | head -40

Repository: hiero-ledger/hiero-sdk-python

Length of output: 1536


🏁 Script executed:

# Verify ResponseCode is used consistently in query examples
rg "ResponseCode" examples/query --type py -B 1 -A 1 | head -30

Repository: hiero-ledger/hiero-sdk-python

Length of output: 2088


Validate child receipt status using ResponseCode enum.

Line 30 prints the raw numeric status without converting to ResponseCode, making it unclear to users whether children succeeded or failed. This contradicts the pattern used throughout examples where all receipt statuses are validated against ResponseCode.SUCCESS.

✅ Suggested improvement
 from hiero_sdk_python.query.transaction_record_query import TransactionRecordQuery
+from hiero_sdk_python.response_code import ResponseCode
@@
     for i, child in enumerate(record.children):
-        print(f"Child {i+1} Status: {child.receipt.status}")
+        status = ResponseCode(child.receipt.status)
+        print(f"Child {i+1} Status: {status.name}")
+        if status != ResponseCode.SUCCESS:
+            print(f"Warning: Child {i+1} failed with status {status.name}")

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.

@mukundkumarjha please address all the coderabbitai issues before pushing code.

@aceppaluni
Copy link
Contributor

@mukundkumarjha
Thank you for your work!
If you have any questions on coderabbit suggestions please let us know so we may assist. We are happy to help!

@exploreriii
Copy link
Contributor

Hi @mukundkumarjha
Similarly could you please click to resolve the conversations to help speed up the review process?

@exploreriii exploreriii added the status: needs developer revision PR has requested changes that the developer needs to implement label Feb 6, 2026
Signed-off-by: Mukund Jha <mukundiiitg@gmail.com>
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: 5

Caution

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

⚠️ Outside diff range comments (4)
src/hiero_sdk_python/transaction/transaction_record.py (3)

106-132: ⚠️ Potential issue | 🔴 Critical

Unreachable dead code — duplicate return in __repr__.

The first return statement at lines 106–119 makes lines 120–132 unreachable. This appears to be merge-conflict residue where both the old and new versions of __repr__ were kept. Remove one of the two blocks (likely the one at lines 120–132, which includes the duplicates_count field from the other PR).

         return (
             f"TransactionRecord(transaction_id='{self.transaction_id}', "
             f"transaction_hash={self.transaction_hash}, "
             f"transaction_memo='{self.transaction_memo}', "
             f"transaction_fee={self.transaction_fee}, "
             f"receipt_status='{status}', "
             f"token_transfers={dict(self.token_transfers)}, "
             f"nft_transfers={dict(self.nft_transfers)}, "
             f"transfers={dict(self.transfers)}, "
             f"new_pending_airdrops={list(self.new_pending_airdrops)}, "
             f"call_result={self.call_result}, "
             f"prng_number={self.prng_number}, "
             f"prng_bytes={self.prng_bytes})"
         )
-        return (f"TransactionRecord(transaction_id='{self.transaction_id}', "
-                f"transaction_hash={self.transaction_hash}, "
-                f"transaction_memo='{self.transaction_memo}', "
-                f"transaction_fee={self.transaction_fee}, "
-                f"receipt_status='{status}', "
-                f"token_transfers={dict(self.token_transfers)}, "
-                f"nft_transfers={dict(self.nft_transfers)}, "
-                f"transfers={dict(self.transfers)}, "
-                f"new_pending_airdrops={list(self.new_pending_airdrops)}, "
-                f"call_result={self.call_result}, "
-                f"prng_number={self.prng_number}, "
-                f"prng_bytes={self.prng_bytes}, "
-                f"duplicates_count={len(self.duplicates)})")

134-200: ⚠️ Potential issue | 🔴 Critical

Merge-conflict residue: duplicate _from_proto signatures and body logic.

The method has two conflicting signatures (lines 135–140 vs 141–142) and two parallel implementations:

  • Lines 172–193: Inline parsing logic (old version)
  • Lines 194–200: Refactored helper-method calls (new version)

Both cannot coexist — this will produce syntax errors. The file needs to be cleaned up to keep only one version. The refactored helper version (lines 194–200) is cleaner and should be kept, but ensure the children parameter is properly integrated.


203-223: ⚠️ Potential issue | 🔴 Critical

Merge-conflict residue: duplicate constructor arguments in cls() call.

The return cls(...) block contains duplicate arguments from both the old and new implementations:

  • call_result appears twice (lines 214–218 and line 219)
  • children is passed (line 213) but was already overwritten to None (line 202)
  • Both children and duplicates keyword arguments are present, but the _from_proto signature can't have both without proper merging

This entire block needs to be reconciled into a single clean constructor call. Example of what the merged version should look like:

return cls(
    transaction_id=tx_id,
    transaction_hash=proto.transactionHash,
    transaction_memo=proto.memo,
    transaction_fee=proto.transactionFee,
    receipt=TransactionReceipt._from_proto(proto.receipt, tx_id),
    token_transfers=token_transfers,
    nft_transfers=nft_transfers,
    transfers=transfers,
    new_pending_airdrops=new_pending_airdrops,
    call_result=call_result,
    prng_number=proto.prng_number,
    prng_bytes=proto.prng_bytes,
    children=children or [],
    duplicates=duplicates or [],
)
src/hiero_sdk_python/query/transaction_record_query.py (1)

302-336: ⚠️ Potential issue | 🔴 Critical

execute() is missing timeout parameter and include_duplicates handling.

This version of execute (from the include_children branch) doesn't accept the timeout parameter, which is required by the base class contract (see existing entry at line 306). It also doesn't handle include_duplicates. The two execute implementations need to be merged into one that supports both features.

Merged execute suggestion
def execute(self, client: Client, timeout: Optional[Union[int, float]] = None):
    self._before_execute(client)
    response = self._execute(client, timeout)
    primary_proto = response.transactionGetRecord.transactionRecord

    children = self._map_record_list(
        response.transactionGetRecord.child_transaction_records
    ) if self.include_children else []

    duplicates = self._map_record_list(
        response.transactionGetRecord.duplicateTransactionRecords
    ) if self.include_duplicates else []

    return TransactionRecord._from_proto(
        primary_proto,
        transaction_id=self.transaction_id,
        children=children,
        duplicates=duplicates,
    )

As per coding guidelines, Review Focus 2: "All queries MUST use the base Query execution flow" and Review Focus 6: flag changes that "Alter base Query behavior".

Comment on lines +1 to 9
from typing import Optional, Any, Union, List
from typing import Optional, Any, Union
from hiero_sdk_python.hapi.services import (
query_header_pb2,
transaction_get_record_pb2,
query_pb2,
)
transaction_record_pb2,
)
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 | 🔴 Critical

File has unresolved merge-conflict residue — will not parse as valid Python.

The file contains duplicate/conflicting code from what appears to be an incomplete merge with the include_duplicates feature branch. Multiple constructs are duplicated:

  • Two typing imports (lines 1–2)
  • Two __init__ signatures (lines 27–33)
  • Two _make_request implementations (lines 102–143 vs 148–160)
  • Two _map_record_list definitions (lines 162–188 vs 292–300)
  • Two execute methods (lines 302–336 vs 306–347)
  • Two set_transaction_id definitions (lines 41–43 vs 74–96)

Ruff's static analysis confirms numerous syntax errors throughout the file. The entire file needs to be properly rebased/merged against main before it can be reviewed meaningfully. The two feature branches (include_children and include_duplicates) need to be combined into a single coherent implementation.

🧰 Tools
🪛 Ruff (0.14.14)

[warning] 8-8: Unexpected indentation

(invalid-syntax)


[warning] 9-9: Expected a statement

(invalid-syntax)

Comment on lines +98 to +100
def set_include_children(self, include_children):
self.include_children = include_children
return self
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 | 🟠 Major

set_include_children lacks input validation, inconsistent with set_include_duplicates.

set_include_duplicates (lines 57–72) validates its input with isinstance(include_duplicates, bool) and raises TypeError for invalid types. set_include_children does no validation at all, creating an inconsistency.

     def set_include_children(self, include_children):
+        if not isinstance(include_children, bool):
+            raise TypeError(
+                f"include_children must be a boolean, got {type(include_children).__name__}"
+            )
         self.include_children = include_children
         return self

As per coding guidelines, "Ensure naming matches existing query patterns" — the validation pattern used by set_include_duplicates should be followed here.

Comment on lines +117 to +143
try:
if not self.transaction_id:
raise ValueError(
"Transaction ID must be set before making the request."
)

query_header = self._make_request_header()
transaction_get_record = (
transaction_get_record_pb2.TransactionGetRecordQuery()
)
transaction_get_record.header.CopyFrom(query_header)

transaction_get_record.transactionID.CopyFrom(
self.transaction_id._to_proto()
)
transaction_get_record.include_child_records = self.include_children
query = query_pb2.Query()
if not hasattr(query, "transactionGetRecord"):
raise AttributeError(
"Query object has no attribute 'transactionGetRecord'"
)
query.transactionGetRecord.CopyFrom(transaction_get_record)

return query
except Exception as e:
print(f"Exception in _make_request: {e}")
raise
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 | 🔴 Critical

Remove try/except + print() from _make_request — introduces side effects.

Production query code must not use print() (per Review Focus 6: "Introduces side effects (logging, prints, stack traces)"). The try/except block at lines 141–143 catches all exceptions, prints to stdout, and re-raises — this adds no value and pollutes output. Additionally, the hasattr check at line 134 is unnecessary defensive coding for a well-known protobuf type.

Proposed simplified _make_request
     def _make_request(self):
-        try:
-            if not self.transaction_id:
-                raise ValueError(
-                    "Transaction ID must be set before making the request."
-                )
-
-            query_header = self._make_request_header()
-            transaction_get_record = (
-                transaction_get_record_pb2.TransactionGetRecordQuery()
-            )
-            transaction_get_record.header.CopyFrom(query_header)
-
-            transaction_get_record.transactionID.CopyFrom(
-                self.transaction_id._to_proto()
-            )
-            transaction_get_record.include_child_records = self.include_children
-            query = query_pb2.Query()
-            if not hasattr(query, "transactionGetRecord"):
-                raise AttributeError(
-                    "Query object has no attribute 'transactionGetRecord'"
-                )
-            query.transactionGetRecord.CopyFrom(transaction_get_record)
-
-            return query
-        except Exception as e:
-            print(f"Exception in _make_request: {e}")
-            raise
+        if self.transaction_id is None:
+            raise ValueError("Transaction ID must be set before making the request.")
+
+        query_header = self._make_request_header()
+        transaction_get_record = transaction_get_record_pb2.TransactionGetRecordQuery()
+        transaction_get_record.header.CopyFrom(query_header)
+        transaction_get_record.transactionID.CopyFrom(self.transaction_id._to_proto())
+        transaction_get_record.include_child_records = self.include_children
+        transaction_get_record.includeDuplicates = self.include_duplicates
+
+        query = query_pb2.Query()
+        query.transactionGetRecord.CopyFrom(transaction_get_record)
+        return query

As per coding guidelines, Review Focus 6: "Introduces side effects (logging, prints, stack traces)" should be flagged. Review Focus 3: "_make_request() MUST... Call _make_request_header() exactly once... Avoid manual QueryHeader mutation".

new_pending_airdrops = cls._parse_pending_airdrops(proto)
call_result = cls._parse_contract_call_result(proto)

children: Optional[List["TransactionRecord"]] = 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 | 🔴 Critical

Critical bug: children parameter is overwritten to None before use.

Line 202 declares children: Optional[List["TransactionRecord"]] = None, which shadows and discards the children parameter passed into _from_proto at line 139. This means the children field on the constructed TransactionRecord will always be None, completely breaking the include_children feature.

Remove this line so the children parameter flows through to the constructor:

-        children: Optional[List["TransactionRecord"]] = None
         return cls(
             transaction_id=tx_id,
             ...
             children=children,

query_pb2,
query_header_pb2,
)
from hiero_sdk_python.hapi.services import query_header_pb2
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

Remove duplicate import of query_header_pb2.

query_header_pb2 is already imported at line 15 within the block import (lines 8–16). This redefinition triggers Ruff F811.

-from hiero_sdk_python.hapi.services import query_header_pb2
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from hiero_sdk_python.hapi.services import query_header_pb2
🧰 Tools
🪛 Ruff (0.14.14)

[error] 17-17: Redefinition of unused query_header_pb2 from line 15: query_header_pb2 redefined here

Remove definition: query_header_pb2

(F811)

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.

@mukundkumarjha please address the recent coderabbitai issues

@exploreriii
Copy link
Contributor

@mukundkumarjha this thread is extremely long, please can you help us to review this by resolving each conversation that is resolved, thank you

@exploreriii exploreriii marked this pull request as draft February 10, 2026 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

Add support for include_children to the TransactionRecordQuery class

6 participants