Skip to content

Commit 7c5c51f

Browse files
Merge branch 'main' into example-token-pause-key-clean
Signed-off-by: undefinedIsMyLife <shinetina169@gmail.com>
2 parents c408d2d + ae4d328 commit 7c5c51f

File tree

157 files changed

+4279
-428
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

157 files changed

+4279
-428
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: PythonBot - Verify PR Commits
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize]
6+
7+
permissions:
8+
contents: read
9+
pull-requests: write
10+
11+
concurrency:
12+
group: "verify-commits-${{ github.event.pull_request.number }}"
13+
cancel-in-progress: true
14+
15+
jobs:
16+
verify-commits:
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- name: Harden the runner (Audit all outbound calls)
21+
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
22+
with:
23+
egress-policy: audit
24+
25+
- name: Checkout repository
26+
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
27+
28+
- name: Check for unverified commits
29+
env:
30+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31+
run: |
32+
PR_NUMBER=${{ github.event.pull_request.number }}
33+
REPO="${{ github.repository }}"
34+
COMMITS_URL="https://github.com/$REPO/pull/${PR_NUMBER}/commits"
35+
36+
echo "Checking commits in PR #$PR_NUMBER for repository $REPO..."
37+
38+
COMMITS_JSON=$(gh api repos/$REPO/pulls/$PR_NUMBER/commits)
39+
UNVERIFIED_COUNT=$(echo "$COMMITS_JSON" | jq '[.[] | select(.commit.verification.verified == false)] | length')
40+
41+
echo "Unverified commits: $UNVERIFIED_COUNT"
42+
43+
if [ "$UNVERIFIED_COUNT" -gt 0 ]; then
44+
COMMENT=$(cat <<EOF
45+
Hi, this is VerificationBot.
46+
Your pull request cannot be merged as it has **unverified commits**.
47+
View your commit verification status: [Commits Tab]($COMMITS_URL).
48+
49+
To achieve verified status, please read:
50+
- [Signing guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/signing.md)
51+
- [README](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/README.md)
52+
- [Discord](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/discord.md)
53+
54+
Remember, you require a GPG key and each commit must be signed with:
55+
\`git commit -S -s -m "Your message here"\`
56+
57+
Thank you for contributing!
58+
59+
From the Hiero Python SDK Team
60+
EOF
61+
)
62+
63+
gh pr view $PR_NUMBER --repo $REPO --json comments --jq '.comments[].body' | grep -F "PythonBot" >/dev/null || \
64+
(gh pr comment $PR_NUMBER --repo $REPO --body "$COMMENT" && echo "Comment added to PR #$PR_NUMBER")
65+
else
66+
echo "All commits in PR #$PR_NUMBER are verified."
67+
fi
68+
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: PythonBot - Workflow Failure Notifier
2+
on:
3+
workflow_dispatch:
4+
workflow_run:
5+
workflows:
6+
- "PR Formatting"
7+
- "Hiero Solo Integration Tests"
8+
- "Run Examples"
9+
types:
10+
- completed
11+
permissions:
12+
contents: read
13+
pull-requests: write
14+
concurrency:
15+
group: "workflow-failure-${{ github.event.workflow_run.head_branch }}"
16+
cancel-in-progress: true
17+
jobs:
18+
notify-pr:
19+
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Harden the runner (Audit all outbound calls)
23+
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
24+
with:
25+
egress-policy: audit
26+
27+
- name: Get associated PR number
28+
id: get-pr
29+
env:
30+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31+
run: |
32+
# Get branch from the workflow run
33+
HEAD_BRANCH=$(gh run view ${{ github.event.workflow_run.id }} \
34+
--repo ${{ github.repository }} \
35+
--json headBranch --jq '.headBranch')
36+
37+
# Find the PR number for this branch
38+
PR_NUMBER=$(gh pr list --repo ${{ github.repository }} --state all --head "$HEAD_BRANCH" --json number --jq '.[0].number')
39+
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV
40+
41+
- name: Comment on PR
42+
if: env.PR_NUMBER != ''
43+
env:
44+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45+
run: |
46+
REPO="${{ github.repository }}"
47+
COMMENT=$(cat <<EOF
48+
Hi, this is WorkflowBot.
49+
Your pull request cannot be merged as it is not passing all our workflow checks.
50+
Please click on each check to review the logs and resolve issues so all checks pass.
51+
To help you:
52+
- [DCO signing guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/signing.md)
53+
- [Changelog guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/changelog_entry.md)
54+
- [Merge conflicts guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/merge_conflicts.md)
55+
- [Rebase guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/rebasing.md)
56+
- [Testing guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/testing.md)
57+
- [Discord](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/discord.md)
58+
- [Community Calls](https://zoom-lfx.platform.linuxfoundation.org/meetings/hiero?view=week)
59+
Thank you for contributing!
60+
From the Hiero Python SDK Team
61+
EOF
62+
)
63+
EXISTING_COMMENT=$(gh pr view "$PR_NUMBER" --repo "$REPO" --comments \
64+
--json comments --jq ".comments[] | select(.body == \"${COMMENT//\"/\\\"}\") | .id")
65+
66+
if [ -z "$EXISTING_COMMENT" ]; then
67+
gh pr comment "$PR_NUMBER" --repo "$REPO" --body "$COMMENT"
68+
else
69+
echo "Comment already exists, skipping."
70+
fi

.github/workflows/examples.yml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
egress-policy: audit
2020

2121
- name: Checkout repository
22-
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
22+
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
2323
with:
2424
fetch-depth: 0
2525

@@ -46,15 +46,16 @@ jobs:
4646
shell: bash
4747
run: |
4848
set -euo pipefail
49-
files=$(ls examples/*.py)
49+
export PYTHONPATH="$PWD"
5050
51-
for file in $files;
52-
do
51+
files=$(find examples -name "*.py" -type f ! -name "__init__.py")
52+
53+
for file in $files; do
5354
echo -e "\n************ ${file} ************"
5455
55-
module="examples.$(basename "$file" .py)"
56+
# Convert path to module name
57+
module=$(realpath --relative-to="$PWD" "$file" | sed 's|/|.|g' | sed 's|.py$||')
5658
57-
# Run the example and capture both stdout and stderr
5859
if ! output=$(uv run -m "$module" 2>&1); then
5960
echo -e "\n❌ Example failed: ${file}"
6061
echo "************ Error Output ************"

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
egress-policy: audit
2424

2525
- name: Checkout repository
26-
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
26+
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
2727

2828
- name: Set up Python
2929
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
egress-policy: audit
2828

2929
- name: Checkout repository
30-
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
30+
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
3131

3232
- name: Set up Python ${{ matrix.python-version }}
3333
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0

CHANGELOG.md

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
66

77
## [Unreleased]
88

9-
109
### Added
1110
- Add `examples/token_create_transaction_pause_key.py` example demonstrating token pause/unpause behavior and pause key usage (#820)
1211

@@ -20,7 +19,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
2019
- Add `examples/token_create_transaction_max_automatic_token_associations_0.py` to demonstrate how `max_automatic_token_associations=0` behaves.
2120
- Add `examples/topic_id.py` to demonstrate `TopicId` opeartions
2221
- Add `examples/topic_message.py` to demonstrate `TopicMessage` and `TopicMessageChunk` with local mock data.
23-
- Added missing validation logic `fee_schedule_key` in integration `token_create_transaction_e2e_test.py` and ``token_update_transaction_e2e_test.py`.
22+
- Added missing validation logic `fee_schedule_key` in integration `token_create_transaction_e2e_test.py` and ``token_update_transaction_e2e_test.py`.
2423
- Add `account_balance_query.py` example to demonstrate how to use the CryptoGetAccountBalanceQuery class.
2524
- Add `examples/token_create_transaction_admin_key.py` demonstrating admin key privileges for token management including token updates, key changes, and deletion (#798)
2625
- Add `examples/token_create_transaction_freeze_key.py` showcasing freeze key behavior, expected failures without the key, and the effect of freezing/unfreezing on transfers.
@@ -31,26 +30,39 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
3130
- `alias`, `staked_account_id`, `staked_node_id` and `decline_staking_reward` fields to AccountCreateTransaction
3231
- `staked_account_id`, `staked_node_id` and `decline_staking_reward` fields to AccountInfo
3332
- Added `examples/token_create_transaction_supply_key.py` to demonstrate token creation with and without a supply key.
33+
- Added `examples/token_create_transaction_kyc_key.py` to demonstrate KYC key functionality, including creating tokens with/without KYC keys, granting/revoking KYC status, and understanding KYC requirements for token transfers.
34+
- Added BatchTransaction class
35+
- Add support for token metadata (bytes, max 100 bytes) in `TokenCreateTransaction`, including a new `set_metadata` setter, example, and tests. [#799]
36+
- Added `examples/token_create_transaction_token_fee_schedule.py` to demonstrate creating tokens with custom fee schedules and the consequences of not having it.
37+
- Added `examples/token_create_transaction_wipe_key.py` to demonstrate token wiping and the role of the wipe key.
38+
- Added `examples/account_allowance_approve_transaction_hbar.py` and `examples/account_allowance_delete_transaction_hbar.py`, deleted `examples/account_allowance_hbar.py`. [#775]
39+
- Added `docs\sdk_developers\training\receipts.md` as a training guide for users to understand hedera receipts.
3440

3541
### Changed
42+
- Upgraded step-security/harden-runner v2.13.2
43+
- bumped actions/checkout from 5.0.0 to 6.0.0
44+
- Limit workflow bot to one message per PR
3645
- Refactored token-related example scripts (`token_delete.py`, `token_dissociate.py`, etc.) for improved readability and modularity. [#370]
3746
- upgrade: step security action upgraded from harden-runner-2.13.1 to harden-runner-2.13.1
3847
- chore: Split `examples/account_allowance_nft.py` into separate `account_allowance_approve_transaction_nft.py` and `account_allowance_delete_transaction_nft.py` examples.
3948
- chore: bump protobuf from 6.33.0 to 6.33.1 (#796)
4049
- fix: Allow `max_automatic_token_associations` to be set to -1 (unlimited) in `AccountCreateTransaction` and add field to `AccountInfo`.
4150
- Allow `PrivateKey` to be used for keys in `TopicCreateTransaction` for consistency.
4251
- Update github actions checkout from 5.0.0 to 5.0.1 (#814)
52+
- changed to add concurrency to workflow bot
4353

4454
### Fixed
55+
4556
- chore: fix test.yml workflow to log import errors (#740)
4657
- chore: fixed integration test names without a test prefix or postfix
4758
- Staked node ID id issue in the account_create_transationt_e2e_test
48-
59+
- workflow: verified commits syntax for verfication bot
4960

5061

5162
## [0.1.8] - 2025-11-07
5263

5364
### Added
65+
5466
- `is_unknown` property added to `src/hiero_sdk_python/response_code.py`
5567
- Example `response_code.py`
5668
- Add `TokenFeeScheduleUpdateTransaction` class to support updating custom fee schedules on tokens (#471).
@@ -75,15 +87,18 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
7587
- docs: Add `docs/sdk_developers/project_structure.md` to explain repository layout and import paths.
7688

7789
### Changed
90+
- chore: renamed examples to match src where possible
91+
- Moved examples/ to be inside subfiles to match src structure
92+
- changed example script workflow to run on new subdirectory structure
7893
- chore: bumped solo action from 14.0 to 15.0 (#764)
7994
- chore: replaced hardcoded 'testnet' messages with environment network name
80-
- chore: validate that token airdrop transactions require an available token service on the channel (#632)
95+
- chore: validate that token airdrop transactions require an available token service on the channel (#632)
8196
- chore: update local environment configuration in env.example (#649)
8297
- chore: Update env.example NETWORK to encourage testnet or local usage (#659)
8398
- chore: updated pyproject.toml with python 3.10 to 3.13 (#510, #449)
8499
- chore: fix type hint for TokenCancelAirdropTransaction pending_airdrops parameter
85100
- chore: Moved documentation file `common_issues.md` from `examples/sdk_developers/` to `docs/sdk_developers/` for unified documentation management (#516).
86-
- chore: Refactored the script of examples/custom_fee.py into modular functions
101+
- chore: Refactored the script of examples/custom_fee.py into modular functions
87102
- fix: Replaced `collections.namedtuple` with `typing.NamedTuple` in `client.py` for improved type checking.
88103
- chore: Refactored examples/custom_fee.py into three separate example files.
89104
- Expanded `docs/sdk_developers/checklist.md` with a self-review guide for all pull request submission requirements (#645).
@@ -93,6 +108,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
93108
- Refactor `AbstractTokenTransferTransaction` to unify Token/NFT transfer logic.
94109

95110
### Fixed
111+
96112
- Added explicit read permissions to examples.yml (#623)
97113
- Removed deprecated Logger.warn() method and legacy parameter swap logic from get_logger() (#673).
98114
- Improved type hinting in `file_append_transaction.py` to resolve 'mypy --strict` errors. ([#495](https://github.com/hiero-ledger/hiero-sdk-python/issues/495))
@@ -102,12 +118,13 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
102118
- Fixed incorrect `TokenType` import (protobuf vs. SDK enum) in 18 example files.
103119
- Update `schedule_sign_transaction_e2e_test` to check for key presence instead of relying on index.
104120
- Add `localhost` and `local` as network names
105-
121+
106122
### Breaking Changes
123+
107124
- chore: changed the file names airdrop classes (#631)
108-
{pending_airdrop_id.py -> token_airdrop_pending_id.py}
109-
{pending_airdrop_record.py -> token_airdrop_pending_record.py}
110-
{token_cancel_airdrop_transaction.py -> token_airdrop_transaction_cancel.py}
125+
{pending_airdrop_id.py -> token_airdrop_pending_id.py}
126+
{pending_airdrop_record.py -> token_airdrop_pending_record.py}
127+
{token_cancel_airdrop_transaction.py -> token_airdrop_transaction_cancel.py}
111128

112129
- In `TokenAirdropTransaction` the parameters of the following methods have been renamed:
113130
- add_nft_transfer(sender → sender_id, receiver → receiver_id)
@@ -137,9 +154,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
137154
- chore: fix the examples workflow to log error messages and run on import failure (#738)
138155
- Added `docs/discord.md` explaining how to join and navigate the Hiero community Discord (#614).
139156

140-
141157
### Changed
142-
143158
- Added direct links to Python SDK channel in Linux Foundation Decentralized Trust Discord back in
144159
- Updated all occurrences of non-functional Discord invite links throughout the documentation with the new, stable Hyperledger and Hedera invite links (#603).
145160
- Refactored TopicId class to use @dataclass decorator for reducing boilerplate code
@@ -170,6 +185,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
170185
- Type hinting for `Topic` related transactions.
171186

172187
### Removed
188+
173189
- Remove deprecated camelCase alias support and `_DeprecatedAliasesMixin`; SDK now only exposes snake_case attributes for `NftId`, `TokenInfo`, and `TransactionReceipt`. (Issue #428)
174190

175191
## [0.1.6] - 2025-10-21
@@ -210,8 +226,6 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
210226
- Improved `CONTRIBUTING.md` by explaining the /docs folder structure and fixing broken hyperlinks.(#431)
211227
- Converted class in `token_nft_info.py` to dataclass for simplicity.
212228

213-
214-
215229
### Fixed
216230

217231
- Incompatible Types assignment in token_transfer_list.py
@@ -513,4 +527,4 @@ contract_call_local_pb2.ContractLoginfo -> contract_types_pb2.ContractLoginfo
513527

514528
### Removed
515529

516-
- N/A
530+
- N/A
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# ReceiptStatusError
2+
3+
This guide explains `ReceiptStatusError` in the Hiero SDK, how it differs from other errors, and how to handle it effectively.
4+
5+
## Error Handling Overview
6+
7+
Many developers assume that if `execute()` doesn't throw an exception, the transaction or query succeeded. However, failures can occur at different stages:
8+
9+
1. **Precheck (Before Submission):**
10+
* Occurs if the transaction is malformed or fails initial validation by the node.
11+
* The SDK raises a `PrecheckError` (or similar) immediately.
12+
* The transaction never reaches consensus.
13+
14+
2. **Network/Node Retry Failures:**
15+
* Occurs if the SDK cannot reach a node or receives transient errors (e.g., `BUSY`).
16+
* The SDK automatically retries up to a limit.
17+
* If retries are exhausted, a `MaxAttemptsError` or `TimeoutError` is raised.
18+
19+
3. **Receipt Status Errors (Post-Consensus):**
20+
* Occurs **after** the network reaches consensus on the transaction.
21+
* The transaction was successfully submitted and processed, but the logic failed (e.g., insufficient funds, token supply full, invalid signature for the specific operation).
22+
* This is where `ReceiptStatusError` comes in.
23+
24+
## What is ReceiptStatusError?
25+
26+
`ReceiptStatusError` is an exception that represents a failure during the **consensus/execution** phase.
27+
28+
* **Timing:** It happens after the transaction is submitted and processed by the network.
29+
* **Content:** It contains the `transaction_receipt`, which holds the status code (e.g., `INSUFFICIENT_ACCOUNT_BALANCE`) and other metadata.
30+
* **Usage:** You must explicitly check the receipt status or configure your client/transaction to throw this error.
31+
32+
## Handling ReceiptStatusError
33+
34+
When you execute a transaction, you typically get a receipt. You should check the status of this receipt.
35+
36+
```python
37+
from hiero_sdk_python.response_code import ResponseCode
38+
from hiero_sdk_python.exceptions import ReceiptStatusError
39+
40+
# ... client and transaction setup ...
41+
42+
try:
43+
# Execute the transaction
44+
receipt = tx.execute(client)
45+
46+
# Check if the status is SUCCESS
47+
if receipt.status != ResponseCode.SUCCESS:
48+
# Raise the specific error with details
49+
raise ReceiptStatusError(receipt.status, tx.transaction_id, receipt)
50+
51+
print("Transaction succeeded!")
52+
53+
except ReceiptStatusError as e:
54+
print(f"Transaction failed post-consensus: {e}")
55+
print(f"Status Code: {e.status}")
56+
print(f"Transaction ID: {e.transaction_id}")
57+
# You can access the full receipt for debugging
58+
# print(e.transaction_receipt)
59+
60+
except Exception as e:
61+
print(f"An unexpected error occurred: {e}")
62+
```
63+
64+
## Summary
65+
66+
* **Precheck errors** happen *before* the network processes the transaction.
67+
* **ReceiptStatusErrors** happen *after* the network processes the transaction but finds it invalid according to ledger rules.
68+
* Always check `receipt.status` to ensure your transaction actually did what you intended.

0 commit comments

Comments
 (0)