Skip to content

Commit 38ecc4e

Browse files
fix: correct typo in token airdrop example and update CHANGELOG.md
1 parent fbdf88d commit 38ecc4e

File tree

2 files changed

+109
-15
lines changed

2 files changed

+109
-15
lines changed

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
2626
- AccountId support for ECDSA alias accounts
2727
- ContractId.to_evm_address() method for EVM compatibility
2828
- consumeLargeData() function in StatefulContract
29-
- example script for Token Airdrop
30-
- added variables directly in the example script to reduce the need for users to supply extra environment variables.
29+
- Added comprehensive example script for Token Airdrop (`token_airdrop.py`) that demonstrates:
30+
- Creating and airdropping both fungible tokens and NFTs with specific serial numbers
31+
- Verifying token transfers using transaction records and balance checks
32+
- Detailed transaction result reporting with visual summary tables
33+
- Added variables directly in the example script to reduce the need for users to supply extra environment variables.
3134
- Added new `merge_conflicts.md` with detailed guidance on handling conflicts during rebase.
3235

3336
### Changed

examples/token_airdrop.py

Lines changed: 104 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
CryptoGetAccountBalanceQuery,
1616
TokenType,
1717
ResponseCode,
18-
NftId
18+
NftId,
19+
TransactionRecordQuery
1920
)
21+
# Check the transaction record to verify the contents
2022

2123
load_dotenv()
2224

@@ -119,13 +121,18 @@ def associate_tokens(client, recipient_id, recipient_key, tokens):
119121
"""Associate the token and nft with the recipient"""
120122
print("\nStep 4: Associating tokens to recipient...")
121123
try:
122-
assocciate_tx = TokenAssociateTransaction(
124+
associate_tx = TokenAssociateTransaction(
123125
account_id=recipient_id,
124126
token_ids=tokens
125127
)
126-
assocciate_tx.freeze_with(client)
127-
assocciate_tx.sign(recipient_key)
128-
assocciate_tx.execute(client)
128+
associate_tx.freeze_with(client)
129+
associate_tx.sign(recipient_key)
130+
associate_receipt = associate_tx.execute(client)
131+
132+
# Verify association was successful
133+
if associate_receipt.status != ResponseCode.SUCCESS:
134+
print(f"❌ Failed to associate tokens: Status: {associate_receipt.status}")
135+
sys.exit(1)
129136

130137
balance_before = (
131138
CryptoGetAccountBalanceQuery(account_id=recipient_id)
@@ -161,6 +168,7 @@ def token_airdrop():
161168

162169
# Mint nft
163170
serial_number = mint_nft(client, operator_key, nft_id)
171+
print(f"Using NFT with serial #{serial_number} for the airdrop")
164172

165173
# Associate tokens
166174
associate_tokens(client, recipient_id, recipient_key, [token_id, nft_id])
@@ -177,7 +185,9 @@ def token_airdrop():
177185
print(f" {nft_id}: {recipient_balances_before.get(nft_id, 0)}")
178186

179187
# Airdrop the tokens
180-
print(f"\nStep 6: Airdropping fungible token TKA ({token_id}) and NFTA ({nft_id}, serial {serial_number}) to recipient {recipient_id}...")
188+
print(f"\nStep 6: Airdropping tokens to recipient {recipient_id}:")
189+
print(f" - 1 fungible token TKA ({token_id})")
190+
print(f" - NFT from NFTA collection ({nft_id}) with serial number #{serial_number}")
181191
try:
182192
airdrop_receipt = (
183193
TokenAirdropTransaction()
@@ -197,25 +207,106 @@ def token_airdrop():
197207
sys.exit(1)
198208

199209
print(f"Token airdrop ID: {airdrop_receipt.transaction_id}")
200-
210+
print("\nVerifying airdrop contents:")
211+
print(f" - Transaction status: {airdrop_receipt.status}")
212+
213+
record = TransactionRecordQuery(transaction_id=airdrop_receipt.transaction_id).execute(client)
214+
215+
# Check token transfers
216+
print(" - Token transfers in this transaction:")
217+
expected_token_transfer = False
218+
for token_id_key, transfers in record.token_transfers.items():
219+
is_expected_token = token_id_key == token_id
220+
token_indicator = "✓ EXPECTED" if is_expected_token else ""
221+
print(f" Token {token_id_key}: {token_indicator}")
222+
223+
# Check for the expected transfer pattern
224+
sender_sent_one = False
225+
recipient_received_one = False
226+
227+
for account, amount in transfers.items():
228+
if amount > 0:
229+
print(f" → {account} received {amount} token(s)")
230+
if account == recipient_id and amount == 1 and is_expected_token:
231+
recipient_received_one = True
232+
else:
233+
print(f" → {account} sent {abs(amount)} token(s)")
234+
if account == operator_id and amount == -1 and is_expected_token:
235+
sender_sent_one = True
236+
237+
if sender_sent_one and recipient_received_one:
238+
expected_token_transfer = True
239+
240+
# Verify the expected fungible token transfer
241+
print("\nVerifying expected fungible token transfer:")
242+
if expected_token_transfer:
243+
print(f" ✅ Success! 1 token of {token_id} (TKA) was successfully transferred")
244+
print(f" from {operator_id} to {recipient_id}")
245+
else:
246+
print(f" ⚠️ Warning: Could not confirm transfer of 1 token of {token_id} (TKA)")
247+
print(f" This might indicate an issue with the transaction or record retrieval")
248+
249+
# Instead of trying to parse the NFT transfers from the record (which has a complex structure),
250+
# we'll verify the NFT transfer through balance changes, which is more reliable
251+
print(" - Verifying NFT transfer through balance changes:")
252+
expected_serial_transferred = False
253+
254+
# Check if balances reflect the NFT transfer
255+
try:
256+
# Get updated balances right now to verify transfer
257+
sender_current = CryptoGetAccountBalanceQuery(account_id=operator_id).execute(client).token_balances
258+
recipient_current = CryptoGetAccountBalanceQuery(account_id=recipient_id).execute(client).token_balances
259+
260+
# Check if the NFT balance changed as expected
261+
sender_nft_before = sender_balances_before.get(nft_id, 0)
262+
sender_nft_after = sender_current.get(nft_id, 0)
263+
recipient_nft_before = recipient_balances_before.get(nft_id, 0)
264+
recipient_nft_after = recipient_current.get(nft_id, 0)
265+
266+
print(f" Sender NFT balance: {sender_nft_before} -> {sender_nft_after}")
267+
print(f" Recipient NFT balance: {recipient_nft_before} -> {recipient_nft_after}")
268+
269+
# If the sender's balance decreased by 1 and the recipient's increased by 1,
270+
# we can infer that the NFT was transferred
271+
if sender_nft_before > sender_nft_after and recipient_nft_after > recipient_nft_before:
272+
expected_serial_transferred = True
273+
print(f" ✓ EXPECTED: Balance changes confirm NFT transfer")
274+
print(f" → NFT with serial #{serial_number} was transferred from {operator_id} to {recipient_id}")
275+
276+
except Exception as e:
277+
print(f" Error verifying NFT transfer through balances: {str(e)}")
278+
279+
# Store the updated balances for later use
280+
sender_balances_after = sender_current
281+
recipient_balances_after = recipient_current
282+
283+
# Verify the specific serial we intended to transfer
284+
print("\nVerifying expected NFT transfer:")
285+
if expected_serial_transferred:
286+
print(f" ✅ Success! NFT {nft_id} with serial #{serial_number} was successfully transferred")
287+
print(f" from {operator_id} to {recipient_id}")
288+
else:
289+
print(f" ⚠️ Warning: Could not confirm transfer of NFT {nft_id} with serial #{serial_number}")
290+
print(f" This might indicate an issue with the transaction or record retrieval")
291+
201292
# Log balances after airdrop
202293
sender_balances_after = CryptoGetAccountBalanceQuery(account_id=operator_id).execute(client).token_balances
203294
recipient_balances_after = CryptoGetAccountBalanceQuery(account_id=recipient_id).execute(client).token_balances
204295
print("\nBalances after airdrop:")
205296
print(f"Sender ({operator_id}):")
206-
print(f" {str(token_id)}: {sender_balances_after.get(str(token_id), 0)}")
207-
print(f" {str(nft_id)}: {sender_balances_after.get(str(nft_id), 0)}")
297+
print(f" {token_id}: {sender_balances_after.get(token_id, 0)}")
298+
print(f" {nft_id}: {sender_balances_after.get(nft_id, 0)}")
208299
print(f"Recipient ({recipient_id}):")
209-
print(f" {str(token_id)}: {recipient_balances_after.get(str(token_id), 0)}")
210-
print(f" {str(nft_id)}: {recipient_balances_after.get(str(nft_id), 0)}")
300+
print(f" {token_id}: {recipient_balances_after.get(token_id, 0)}")
301+
print(f" {nft_id}: {recipient_balances_after.get(nft_id, 0)}")
211302

212303
# Summary table
213304
print("\nSummary Table:")
214305
print("+----------------+----------------------+----------------------+----------------------+----------------------+")
215306
print("| Token Type | Token ID | NFT Serial | Sender Balance | Recipient Balance |")
216307
print("+----------------+----------------------+----------------------+----------------------+----------------------+")
217-
print(f"| Fungible (TKA) | {str(token_id):20} | -{'':20} | {str(sender_balances_after.get(str(token_id), 0)):20} | {str(recipient_balances_after.get(str(token_id), 0)):20} |")
218-
print(f"| NFT (NFTA) | {str(nft_id):20} | {str(serial_number):20} | {str(sender_balances_after.get(str(nft_id), 0)):20} | {str(recipient_balances_after.get(str(nft_id), 0)):20} |")
308+
print(f"| Fungible (TKA) | {str(token_id):20} | {'N/A':20} | {str(sender_balances_after.get(token_id, 0)):20} | {str(recipient_balances_after.get(token_id, 0)):20} |")
309+
print(f"| NFT (NFTA) | {str(nft_id):20} | #{str(serial_number):19} | {str(sender_balances_after.get(nft_id, 0)):20} | {str(recipient_balances_after.get(nft_id, 0)):20} |")
219310
print("+----------------+----------------------+----------------------+----------------------+----------------------+")
220311
print("\n✅ Success! Token Airdrop transaction successful")
221312
except Exception as e:

0 commit comments

Comments
 (0)