Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
- Fix `TopicInfo.__str__()` to format `expiration_time` in UTC so unit tests pass in non-UTC environments. (#1800)
- Resolve CodeQL `reflected-XSS` warning in TCK JSON-RPC endpoint
- Improve `keccak256` docstring formatting for better readability and consistency (#1624)
- Added `wait_for_receipt` parameter for `Transaction.execute()` to support optional receipt waiting, and `get_receipt_query`, `get_record_query` and `get_record` to `TransactionResponse`.

### Examples
- Refactor `examples/file/file_create_transaction.py` to remove `os`,`dotenv`,`AccountId`,`PrivateKey`,`Network` imports that are no longer needed and updated setup-client() (#1610)
Expand Down
80 changes: 80 additions & 0 deletions examples/transaction/transaction_without_wait_for_receipt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""
Demonstrate creating, executing, and retrieving an account creation transaction
without immediately waiting for the receipt.

uv run examples/transaction/transaction_without_wait_for_receipt.py
python examples/transaction/transaction_without_wait_for_receipt.py
"""

import sys

from hiero_sdk_python import (
Client,
AccountCreateTransaction,
PrivateKey,
ResponseCode
)


def build_transaction():
"""
Build a new AccountCreateTransaction with a generated private key
and a minimal initial balance.
"""
key = PrivateKey.generate()
return AccountCreateTransaction().set_key_without_alias(key).set_initial_balance(1)


def print_transaction_record(record):
"""Print the transaction record."""
print(f"Transaction ID: {record.transaction_id}")
print(f"Transaction Fee: {record.transaction_fee}")
print(f"Transaction Hash: {record.transaction_hash.hex()}")
print(f"Transaction Memo: {record.transaction_memo}")
print(f"Transaction Account ID: {record.receipt.account_id}")


def print_transaction_receipt(receipt):
"""Print the transaction receipt."""
if receipt.status != ResponseCode.SUCCESS:
raise RuntimeError(f"Receipt Query failed with status: {ResponseCode(receipt.status).name}")

print(f"Transaction Receipt Status: {ResponseCode(receipt.status).name}")
print(f"Transaction Account ID: {receipt.account_id}")


def main():
"""
1. Initialize a client from environment variables (operator required in env).
2. Build an AccountCreateTransaction.
3. Execute the transaction (without waiting for receipt).
4. Retrieve the receipt and record after execution.
"""
try:
client = Client.from_env()
tx = build_transaction()

print("Executing transaction...")
# Execute the transaction without waiting for receipt immediately
response = tx.execute(client, wait_for_receipt=False)

print("Transaction executed successfully!")
print(f"Transaction submitted with ID: {response.transaction_id}")

# Retrieve receipt and record after submission
print("\n1. Getting Transaction Receipt using Transaction Response...")
receipt = response.get_receipt(client)
print_transaction_receipt(receipt)


print("\n2. Getting Transaction Record using Transaction Response...")
record = response.get_record(client)
print_transaction_record(record)

except Exception as err:
print(f"Error during transaction: {err}")
sys.exit(1)


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import math
from typing import List, Optional, Union
from typing import List, Literal, Optional, Union, overload
from hiero_sdk_python.client.client import Client
from hiero_sdk_python.consensus.topic_id import TopicId
from hiero_sdk_python.crypto.private_key import PrivateKey
Expand All @@ -13,6 +13,8 @@
from hiero_sdk_python.channels import _Channel
from hiero_sdk_python.executable import _Method
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


class TopicMessageSubmitTransaction(Transaction):
Expand Down Expand Up @@ -282,25 +284,92 @@ def freeze_with(self, client: "Client") -> "TopicMessageSubmitTransaction":
self._transaction_ids.append(chunk_transaction_id)

return super().freeze_with(client)

@overload
def execute(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: Literal[True] = True,
) -> "TransactionReceipt":
...

@overload
def execute(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: Literal[False] = False,
) -> "TransactionResponse":
...


def execute(self, client: "Client", timeout: Optional[Union[int, float]] = None):
def execute(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: bool = True
) -> TransactionReceipt | TransactionResponse:
"""
Executes the topic message submit transaction.

For multi-chunk transactions, this method will execute all chunks sequentially.
For multi-chunk transactions, this method will execute all chunks sequentially and return first response.

Args:
client: The client to execute the transaction with.
timeout (Optional[Union[int, float]): The total execution timeout (in seconds) for this execution.
timeout (int | float | None, optional): The total execution timeout (in seconds) for this execution.
wait_for_receipt (bool, optional): Whether to wait for consensus and return the receipt.
If False, the method returns a TransactionResponse immediately after submission.

Returns:
TransactionReceipt: The receipt from the first chunk execution.
TransactionReceipt: If wait_for_receipt is True (default)
TransactionResponse: If wait_for_receipt is False
"""
# Return the first response as the JS SDK does
return self.execute_all(client, timeout, wait_for_receipt)[0]

@overload
def execute_all(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: Literal[True] = True,
) -> List["TransactionReceipt"]:
...

@overload
def execute_all(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: Literal[False] = False,
) -> List["TransactionResponse"]:
...

def execute_all(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: bool = True
) -> List["TransactionReceipt"] | List["TransactionResponse"]:
"""
Executes the topic message submit transaction.

This method will execute all chunks sequentially and return list of all responses.

Args:
client: The client to execute the transaction with.
timeout (int | float | None, optional): The total execution timeout (in seconds) for this execution.
wait_for_receipt (bool, optional): Whether to wait for consensus and return the receipt.
If False, the method returns a TransactionResponse immediately after submission.

Returns:
List[TransactionReceipt]: If wait_for_receipt is True (default)
List[TransactionResponse]: If wait_for_receipt is False
"""
self._validate_chunking()

if self.get_required_chunks() == 1:
return super().execute(client, timeout)
return [super().execute(client, timeout, wait_for_receipt)]

# Multi-chunk transaction - execute all chunks
responses = []
Expand All @@ -320,11 +389,11 @@ def execute(self, client: "Client", timeout: Optional[Union[int, float]] = None)
super().sign(signing_key)

# Execute the chunk
response = super().execute(client, timeout)
response = super().execute(client, timeout, wait_for_receipt)
responses.append(response)

# Return the first response as the JS SDK does
return responses[0] if responses else None
return responses


def sign(self, private_key: "PrivateKey"):
"""
Expand Down
91 changes: 79 additions & 12 deletions src/hiero_sdk_python/file/file_append_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"""

import math
from typing import TYPE_CHECKING, Any, List, Optional, Union
from typing import TYPE_CHECKING, Any, List, Literal, Optional, Union, overload
from hiero_sdk_python.file.file_id import FileId
from hiero_sdk_python.hbar import Hbar
from hiero_sdk_python.transaction.transaction import Transaction
Expand All @@ -27,10 +27,11 @@
# Use TYPE_CHECKING to avoid circular import errors
if TYPE_CHECKING:
from hiero_sdk_python.client import Client
from hiero_sdk_python.keys import PrivateKey
from hiero_sdk_python.crypto.private_key import PrivateKey
from hiero_sdk_python.channels import _Channel
from hiero_sdk_python.executable import _Method
from hiero_sdk_python.transaction_receipt import TransactionReceipt
from hiero_sdk_python.transaction.transaction import TransactionReceipt
from hiero_sdk_python.transaction.transaction_response import TransactionResponse


# pylint: disable=too-many-instance-attributes
Expand Down Expand Up @@ -320,25 +321,92 @@ def freeze_with(self, client: "Client") -> FileAppendTransaction:

return self


def execute(self, client: "Client", timeout: Optional[Union[int, float]] = None) -> Any:
@overload
def execute(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: Literal[True] = True,
) -> "TransactionReceipt":
...

@overload
def execute(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: Literal[False] = False,
) -> "TransactionResponse":
...

def execute(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: bool = True
) -> "TransactionReceipt" | "TransactionResponse":
"""
Executes the file append transaction.

For multi-chunk transactions, this method will execute all chunks sequentially and return first response.

Args:
client: The client to execute the transaction with.
timeout (int | float | None, optional): The total execution timeout (in seconds) for this execution.
wait_for_receipt (bool, optional): Whether to wait for consensus and return the receipt.
If False, the method returns a TransactionResponse immediately after submission.

Returns:
TransactionReceipt: If wait_for_receipt is True (default)
TransactionResponse: If wait_for_receipt is False
"""
# Return the first response (as per JavaScript implementation)
return self.execute_all(client, timeout, wait_for_receipt)[0]

@overload
def execute_all(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: Literal[True] = True,
) -> List["TransactionReceipt"]:
...

@overload
def execute_all(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: Literal[False] = False,
) -> List["TransactionResponse"]:
...

def execute_all(
self,
client: "Client",
timeout: int | float | None = None,
wait_for_receipt: bool = True
) -> List["TransactionReceipt"] | List["TransactionResponse"]:
"""
Executes the file append transaction.

For multi-chunk transactions, this method will execute all chunks sequentially.
This method will execute all chunks sequentially and return list of response for each chunked

Args:
client: The client to execute the transaction with.
timeout (Optional[Union[int, float]): The total execution timeout (in seconds) for this execution.
timeout (int | float | None, optional): The total execution timeout (in seconds) for this execution.
wait_for_receipt (bool, optional): Whether to wait for consensus and return the receipt.
If False, the method returns a TransactionResponse immediately after submission.

Returns:
TransactionReceipt: The receipt from the first chunk execution.
List[TransactionReceipt]: If wait_for_receipt is True (default)
List[TransactionResponse]: If wait_for_receipt is False
"""
self._validate_chunking()

if self.get_required_chunks() == 1:
# Single chunk transaction
return super().execute(client, timeout)
return [super().execute(client, timeout, wait_for_receipt)]

# Multi-chunk transaction - execute all chunks
responses = []
Expand All @@ -362,11 +430,10 @@ def execute(self, client: "Client", timeout: Optional[Union[int, float]] = None)
super().sign(signing_key)

# Execute the chunk
response = super().execute(client, timeout)
response = super().execute(client, timeout, wait_for_receipt)
responses.append(response)

# Return the first response (as per JavaScript implementation)
return responses[0] if responses else None
return responses

def sign(self, private_key: "PrivateKey") -> FileAppendTransaction:
"""
Expand Down
Loading