Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/00-good-first-issue-candidate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ body:
- The complete steps to implement the solution
- What the final result or output should look like
- Links to relevant documentation or code (if helpful)
For good first issues, please keep this as guided and clear as possible.
For Good First Issues, please keep this as guided and clear as possible.
value: |
<!-- Identify what to change in which files -->

Expand All @@ -95,7 +95,7 @@ body:
attributes:
label: 🧠 Good First Issue Developers — Prerequisites & Expectations
description: |
Adapt as needed. Concrete requirements before claiming this good first issue. Adapt as needed.
Adapt as needed. Concrete requirements before claiming this Good First Issue.
value: |
> [!IMPORTANT]
> **This issue does not require prior domain knowledge.**
Expand Down
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/01-good-first-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ body:
- The complete steps to implement the solution
- What the final result or output should look like
- Links to relevant documentation or code (if helpful)
For good first issues, please keep this as guided and clear as possible.
For Good First Issues, please keep this as guided and clear as possible.
value: |
<!-- Identify what to change in which files -->

Expand All @@ -82,7 +82,7 @@ body:
attributes:
label: 🧠 Good First Issue Developers — Prerequisites & Expectations
description: |
Adapt as needed. Concrete requirements before claiming this good first issue. Adapt as needed.
Adapt as needed. Concrete requirements before claiming this Good First Issue.
value: |
> [!IMPORTANT]
> **This issue does not require prior domain knowledge.**
Expand Down
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/02-beginner-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ body:
> **Beginner issues are low-risk but we expect a working solution.**

> [!IMPORTANT]
> We recommend completing at least 3 good first issues before attempting a beginner issue.
> We recommend completing at least 3 Good First Issues before attempting a beginner issue.

**Difficulty:**

Expand All @@ -113,7 +113,7 @@ body:
> - Keeping your fork up to date with main by [rebasing](https://github.com/hiero-ledger/sdk-collaboration-hub/blob/main/guides/issue-progression/for-developers/rebasing.md)
> - Looking things up on your own before asking for help

If any of that feels unfamiliar, good first issues might still be the most rewarding path for you right now — [find one here](https://github.com/issues?q=is%3Aopen%20is%3Aissue%20org%3Ahiero-ledger%20archived%3Afalse%20no%3Aassignee%20(label%3A%22good%20first%20issue%22%20OR%20label%3A%22skill%3A%20good%20first%20issue%22)%20(repo%3Ahiero-ledger%2Fhiero-sdk-cpp%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-swift%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-python%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-js%20OR%20repo%3Ahiero-ledger%2Fhiero-website)).
If any of that feels unfamiliar, Good First Issues might still be the most rewarding path for you right now — [find one here](https://github.com/issues?q=is%3Aopen%20is%3Aissue%20org%3Ahiero-ledger%20archived%3Afalse%20no%3Aassignee%20(label%3A%22good%20first%20issue%22%20OR%20label%3A%22skill%3A%20good%20first%20issue%22)%20(repo%3Ahiero-ledger%2Fhiero-sdk-cpp%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-swift%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-python%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-js%20OR%20repo%3Ahiero-ledger%2Fhiero-website)).
You can always come back when you are ready.

### ⚠️ AI Usage Policy
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/bot-gfi-assign-on-comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function commentRequestsAssignment(body) {
}

/**
* Returns true if the issue has the good first issue label.
* Returns true if the issue has the Good First Issue label.
*/
function issueIsGoodFirstIssue(issue) {
const labels = issue?.labels?.map(label => label.name) ?? [];
Expand Down
12 changes: 2 additions & 10 deletions .github/scripts/coderabbit_plan_trigger.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@

const CODERABBIT_MARKER = '<!-- CodeRabbit Plan Trigger -->';

async function triggerCodeRabbitPlan(github, owner, repo, issue, marker = CODERABBIT_MARKER, isDryRun = false) {
async function triggerCodeRabbitPlan(github, owner, repo, issue, marker = CODERABBIT_MARKER) {
const comment = `${marker} @coderabbitai plan`;

if (isDryRun) {
console.log(`[DRY RUN] Would trigger CodeRabbit plan for issue #${issue.number}`);
return true;
}

try {
await github.rest.issues.createComment({
owner,
Expand Down Expand Up @@ -105,11 +100,8 @@ async function main({ github, context }) {
return console.log(`CodeRabbit plan already triggered for #${issue.number}`);
}

// Check for dry run (default to true if not specified, for safety)
const isDryRun = (process.env.DRY_RUN || 'true').toLowerCase() === 'true';

// Post CodeRabbit plan trigger
await triggerCodeRabbitPlan(github, owner, repo, issue, CODERABBIT_MARKER, isDryRun);
await triggerCodeRabbitPlan(github, owner, repo, issue, CODERABBIT_MARKER);

logSummary(owner, repo, issue);
} catch (err) {
Expand Down
16 changes: 2 additions & 14 deletions .github/workflows/bot-coderabbit-plan-trigger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@ name: CodeRabbit Plan Trigger
on:
issues:
types: [labeled]
workflow_dispatch:
inputs:
dry_run:
description: "Run without posting comments"
required: false
default: "true"
type: choice
options:
- "true"
- "false"

permissions:
issues: write
Expand All @@ -28,10 +18,9 @@ jobs:
cancel-in-progress: false
# Only run when the newly added label is beginner, intermediate, or advanced (case-insensitive)
if: >
github.event_name == 'workflow_dispatch' ||
(github.event.action == 'labeled' &&
github.event.action == 'labeled' &&
github.event.issue.state == 'open' &&
contains(fromJson('["beginner","intermediate","advanced","Beginner","Intermediate","Advanced"]'), github.event.label.name))
contains(fromJson('["beginner","intermediate","advanced","Beginner","Intermediate","Advanced"]'), github.event.label.name)

steps:
- name: Harden the runner
Expand All @@ -45,7 +34,6 @@ jobs:
- name: Trigger CodeRabbit Plan
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || 'false' }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 #v9.0.0
with:
script: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from hiero_sdk_python.account.account_id import AccountId
from hiero_sdk_python.channels import _Channel
from hiero_sdk_python.crypto.key import Key
from hiero_sdk_python.Duration import Duration
from hiero_sdk_python.executable import _Method
from hiero_sdk_python.hapi.services import consensus_create_topic_pb2, transaction_pb2
Expand All @@ -19,7 +20,7 @@
)
from hiero_sdk_python.tokens.custom_fixed_fee import CustomFixedFee
from hiero_sdk_python.transaction.transaction import Transaction
from hiero_sdk_python.utils.key_utils import Key, key_to_proto
from hiero_sdk_python.utils.key_utils import key_to_proto


class TopicCreateTransaction(Transaction):
Expand Down
19 changes: 15 additions & 4 deletions src/hiero_sdk_python/query/transaction_get_receipt_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,17 +277,22 @@ def _map_status_error(self, response: response_pb2.Response) -> PrecheckError |
TransactionReceipt._from_proto(response.transactionGetReceipt.receipt, self.transaction_id),
)

def _map_receipt_list(self, receipts: list[transaction_receipt_pb2.TransactionReceipt]) -> list[TransactionReceipt]:
def _map_receipt_list(
self, receipts: list[transaction_receipt_pb2.TransactionReceipt], include_parent_tx_id: bool = False
) -> list[TransactionReceipt]:
"""
Maps a list of protobuf transaction receipts to TransactionReceipt objects.

Args:
receipts: A list of protobuf TransactionReceipt objects
include_parent_tx_id: If True, pass parent transaction_id to mapped receipts (for duplicates).
If False, pass None (for child receipts).

Returns:
A list of TransactionReceipt objects
"""
return [TransactionReceipt._from_proto(receipt_proto, self.transaction_id) for receipt_proto in receipts]
transaction_id = self.transaction_id if include_parent_tx_id else None
return [TransactionReceipt._from_proto(receipt_proto, transaction_id) for receipt_proto in receipts]

def execute(self, client: Client, timeout: int | float | None = None) -> TransactionReceipt:
"""
Expand Down Expand Up @@ -315,12 +320,18 @@ def execute(self, client: Client, timeout: int | float | None = None) -> Transac
parent = TransactionReceipt._from_proto(response.transactionGetReceipt.receipt, self.transaction_id)

if self.include_children:
children = self._map_receipt_list(response.transactionGetReceipt.child_transaction_receipts)
# Child receipts are sub-transactions; they don't need parent transaction_id
children = self._map_receipt_list(
response.transactionGetReceipt.child_transaction_receipts, include_parent_tx_id=False
)

parent._set_children(children)

if self.include_duplicates:
duplicates = self._map_receipt_list(response.transactionGetReceipt.duplicateTransactionReceipts)
# Duplicate receipts are related to parent; keep parent transaction_id for context
duplicates = self._map_receipt_list(
response.transactionGetReceipt.duplicateTransactionReceipts, include_parent_tx_id=True
)

parent._set_duplicates(duplicates)

Expand Down
3 changes: 2 additions & 1 deletion src/hiero_sdk_python/tokens/token_create_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from hiero_sdk_python.account.account_id import AccountId
from hiero_sdk_python.channels import _Channel
from hiero_sdk_python.crypto.key import Key
from hiero_sdk_python.Duration import Duration
from hiero_sdk_python.executable import _Method
from hiero_sdk_python.hapi.services import token_create_pb2, transaction_pb2
Expand All @@ -29,7 +30,7 @@
from hiero_sdk_python.tokens.supply_type import SupplyType
from hiero_sdk_python.tokens.token_type import TokenType
from hiero_sdk_python.transaction.transaction import Transaction
from hiero_sdk_python.utils.key_utils import Key, key_to_proto
from hiero_sdk_python.utils.key_utils import key_to_proto


AUTO_RENEW_PERIOD = Duration(7890000) # around 90 days in seconds
Expand Down
3 changes: 2 additions & 1 deletion src/hiero_sdk_python/tokens/token_update_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from hiero_sdk_python.account.account_id import AccountId
from hiero_sdk_python.channels import _Channel
from hiero_sdk_python.crypto.key import Key
from hiero_sdk_python.Duration import Duration
from hiero_sdk_python.executable import _Method
from hiero_sdk_python.hapi.services import token_update_pb2, transaction_pb2
Expand All @@ -25,7 +26,7 @@
from hiero_sdk_python.tokens.token_id import TokenId
from hiero_sdk_python.tokens.token_key_validation import TokenKeyValidation
from hiero_sdk_python.transaction.transaction import Transaction
from hiero_sdk_python.utils.key_utils import Key, key_to_proto
from hiero_sdk_python.utils.key_utils import key_to_proto


@dataclass
Expand Down
3 changes: 2 additions & 1 deletion src/hiero_sdk_python/transaction/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from hiero_sdk_python.account.account_id import AccountId
from hiero_sdk_python.client.client import Client
from hiero_sdk_python.crypto.key import Key
from hiero_sdk_python.exceptions import PrecheckError
from hiero_sdk_python.executable import _Executable, _ExecutionState
from hiero_sdk_python.hapi.services import basic_types_pb2, transaction_contents_pb2, transaction_pb2
Expand All @@ -15,7 +16,7 @@
from hiero_sdk_python.transaction.transaction_id import TransactionId
from hiero_sdk_python.transaction.transaction_receipt import TransactionReceipt
from hiero_sdk_python.transaction.transaction_response import TransactionResponse
from hiero_sdk_python.utils.key_utils import Key, key_to_proto
from hiero_sdk_python.utils.key_utils import key_to_proto


if TYPE_CHECKING:
Expand Down
17 changes: 12 additions & 5 deletions src/hiero_sdk_python/transaction/transaction_receipt.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,15 @@ def account_id(self) -> AccountId | None:
"""
Retrieves the AccountId associated with the transaction receipt, if available.

Unlike other ID properties (token_id, file_id, etc.), this returns the AccountId
even when accountNum is 0. This is intentional to support EVM auto-account creation
scenarios where the protobuf may contain an AccountID with num=0 to identify the
newly created account before it's fully initialized on-chain.

Returns:
AccountId or None: The AccountId if present; otherwise, None.
AccountId or None: The AccountId if present (including num=0); otherwise, None.
"""
if self._receipt_proto.HasField("accountID") and self._receipt_proto.accountID.accountNum != 0:
if self._receipt_proto.HasField("accountID"):
return AccountId._from_proto(self._receipt_proto.accountID)
return None

Expand All @@ -107,7 +112,9 @@ def serial_numbers(self) -> list[int]:

@property
def file_id(self) -> FileId | None:
"""Returns the file ID associated with this receipt."""
"""
Returns the file ID associated with this receipt.
"""
if self._receipt_proto.HasField("fileID") and self._receipt_proto.fileID.fileNum != 0:
return FileId._from_proto(self._receipt_proto.fileID)
return None
Expand Down Expand Up @@ -243,14 +250,14 @@ def _to_proto(self):

@classmethod
def _from_proto(
cls, proto: transaction_receipt_pb2.TransactionReceipt, transaction_id: TransactionId
cls, proto: transaction_receipt_pb2.TransactionReceipt, transaction_id: TransactionId | None
) -> TransactionReceipt:
"""
Creates a TransactionReceipt instance from a protobuf TransactionReceipt object.

Args:
proto (transaction_receipt_pb2.TransactionReceipt): The protobuf TransactionReceipt object.
transaction_id (TransactionId): The transaction ID associated with this receipt.
transaction_id (TransactionId | None): The transaction ID associated with this receipt. Can be None for child receipts.

Returns:
TransactionReceipt: A new instance of TransactionReceipt populated with data from the protobuf object.
Expand Down
15 changes: 9 additions & 6 deletions tests/integration/account_records_query_e2e_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ def test_integration_account_record_query_can_execute(env):
account = env.create_account()

# Perform transfer transaction
transfer_tx = TransferTransaction()
transfer_tx.transaction_fee = Hbar(2).to_tinybars()
transfer_receipt = (
TransferTransaction()
.add_hbar_transfer(account.id, Hbar(1).to_tinybars())
transfer_tx.add_hbar_transfer(account.id, Hbar(1).to_tinybars())
.add_hbar_transfer(env.operator_id, -Hbar(1).to_tinybars())
.execute(env.client)
)
Expand Down Expand Up @@ -50,9 +51,10 @@ def test_integration_account_record_query_get_cost(env):
"""Test that AccountRecordsQuery can calculate query costs."""
account = env.create_account()

transfer_tx = TransferTransaction()
transfer_tx.transaction_fee = Hbar(2).to_tinybars()
transfer_receipt = (
TransferTransaction()
.add_hbar_transfer(account.id, Hbar(1).to_tinybars())
transfer_tx.add_hbar_transfer(account.id, Hbar(1).to_tinybars())
.add_hbar_transfer(env.operator_id, -Hbar(1).to_tinybars())
.execute(env.client)
)
Expand All @@ -75,9 +77,10 @@ def test_integration_account_record_query_insufficient_payment(env):
"""Test that AccountRecordsQuery fails with insufficient payment."""
account = env.create_account()

transfer_tx = TransferTransaction()
transfer_tx.transaction_fee = Hbar(2).to_tinybars()
transfer_receipt = (
TransferTransaction()
.add_hbar_transfer(account.id, Hbar(1).to_tinybars())
transfer_tx.add_hbar_transfer(account.id, Hbar(1).to_tinybars())
.add_hbar_transfer(env.operator_id, -Hbar(1).to_tinybars())
.execute(env.client)
)
Expand Down
Loading