Skip to content

Commit c494f0f

Browse files
Dosik130xivanov
andauthored
feat: add AccountInfoQuery (#142)
* feat: add AccountInfo class Signed-off-by: dosi <[email protected]> * test: add unit tests for AccountInfo Signed-off-by: dosi <[email protected]> * feat: add TokenRelationship Signed-off-by: dosi <[email protected]> * test: add unit tests for TokenRelationship Signed-off-by: dosi <[email protected]> * feat: implement AccountInfoQuery Signed-off-by: dosi <[email protected]> * test: add AccountInfoQuery unit tests Signed-off-by: dosi <[email protected]> * test: add AccountInfoQuery integration tests Signed-off-by: dosi <[email protected]> * fix: remove incorrect token freeze validation that blocks creating frozen tokens Signed-off-by: dosi <[email protected]> * docs: add account info query example Signed-off-by: dosi <[email protected]> * docs: update examples README Signed-off-by: dosi <[email protected]> * chore: add AccountInfoQuery to __init__.py Signed-off-by: dosi <[email protected]> * refactor: use list comprehension to reduce cyclomatic complexity Signed-off-by: dosi <[email protected]> * test: fix unit test for AccountInfo Signed-off-by: dosi <[email protected]> * test: reduce test_account_info_query_execute() lines in AccountInfoQuery unit tests Signed-off-by: dosi <[email protected]> * chore: add type hinting Signed-off-by: Ivan Ivanov <[email protected]> --------- Signed-off-by: dosi <[email protected]> Signed-off-by: Ivan Ivanov <[email protected]> Co-authored-by: Ivan Ivanov <[email protected]>
1 parent b8569d3 commit c494f0f

File tree

11 files changed

+1293
-5
lines changed

11 files changed

+1293
-5
lines changed

examples/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ You can choose either syntax or even mix both styles in your projects.
1313
- [Account Transactions](#account-transactions)
1414
- [Creating an Account](#creating-an-account)
1515
- [Querying Account Balance](#querying-account-balance)
16+
- [Querying Account Info](#querying-account-info)
1617
- [Creating a Token](#creating-a-token)
1718
- [Token Transactions](#token-transactions)
1819
- [Minting a Fungible Token](#minting-a-fungible-token)
@@ -90,6 +91,33 @@ balance = CryptoGetAccountBalanceQuery(account_id=some_account_id).execute(clien
9091
balance = ( CryptoGetAccountBalanceQuery() .set_account_id(some_account_id) .execute(client) ) print(f"Account balance: {balance.hbars} hbars")
9192
```
9293

94+
### Querying Account Info
95+
96+
#### Pythonic Syntax:
97+
```
98+
info = AccountInfoQuery(account_id=account_id).execute(client)
99+
print(f"Account ID: {info.account_id}")
100+
print(f"Account Public Key: {info.key.to_string()}")
101+
print(f"Account Balance: {info.balance}")
102+
print(f"Account Memo: '{info.account_memo}'")
103+
print(f"Owned NFTs: {info.owned_nfts}")
104+
print(f"Token Relationships: {info.token_relationships}")
105+
```
106+
107+
#### Method Chaining:
108+
```
109+
info = (
110+
AccountInfoQuery()
111+
.set_account_id(account_id)
112+
.execute(client)
113+
)
114+
print(f"Account ID: {info.account_id}")
115+
print(f"Account Public Key: {info.key.to_string()}")
116+
print(f"Account Balance: {info.balance}")
117+
print(f"Account Memo: '{info.account_memo}'")
118+
print(f"Owned NFTs: {info.owned_nfts}")
119+
print(f"Token Relationships: {info.token_relationships}")
120+
```
93121

94122
## Token Transactions
95123

examples/query_account_info.py

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
import os
2+
import sys
3+
from dotenv import load_dotenv
4+
5+
from hiero_sdk_python import (
6+
Client,
7+
Network,
8+
AccountId,
9+
PrivateKey,
10+
AccountCreateTransaction,
11+
ResponseCode,
12+
Hbar,
13+
)
14+
from hiero_sdk_python.query.account_info_query import AccountInfoQuery
15+
from hiero_sdk_python.tokens.token_create_transaction import TokenCreateTransaction
16+
from hiero_sdk_python.tokens.token_associate_transaction import TokenAssociateTransaction
17+
from hiero_sdk_python.tokens.token_grant_kyc_transaction import TokenGrantKycTransaction
18+
from hiero_sdk_python.tokens.supply_type import SupplyType
19+
from hiero_sdk_python.hapi.services.basic_types_pb2 import TokenType
20+
from hiero_sdk_python.tokens.token_mint_transaction import TokenMintTransaction
21+
from hiero_sdk_python.tokens.nft_id import NftId
22+
23+
load_dotenv()
24+
25+
def setup_client():
26+
"""Initialize and set up the client with operator account"""
27+
network = Network(network='testnet')
28+
client = Client(network)
29+
30+
operator_id = AccountId.from_string(os.getenv('OPERATOR_ID'))
31+
operator_key = PrivateKey.from_string(os.getenv('OPERATOR_KEY'))
32+
client.set_operator(operator_id, operator_key)
33+
34+
return client, operator_id, operator_key
35+
36+
def create_test_account(client, operator_key):
37+
"""Create a new test account for demonstration"""
38+
new_account_private_key = PrivateKey.generate_ed25519()
39+
new_account_public_key = new_account_private_key.public_key()
40+
41+
receipt = (
42+
AccountCreateTransaction()
43+
.set_key(new_account_public_key)
44+
.set_initial_balance(Hbar(1))
45+
.set_account_memo("Test account memo")
46+
.freeze_with(client)
47+
.sign(operator_key)
48+
.execute(client)
49+
)
50+
51+
if receipt.status != ResponseCode.SUCCESS:
52+
print(f"Account creation failed with status: {ResponseCode(receipt.status).name}")
53+
sys.exit(1)
54+
55+
new_account_id = receipt.accountId
56+
print(f"\nTest account created with ID: {new_account_id}")
57+
58+
return new_account_id, new_account_private_key
59+
60+
def create_fungible_token(client, operator_id, operator_key):
61+
"""Create a fungible token for association with test account"""
62+
receipt = (
63+
TokenCreateTransaction()
64+
.set_token_name("FungibleToken")
65+
.set_token_symbol("FTT")
66+
.set_decimals(2)
67+
.set_initial_supply(1000)
68+
.set_treasury_account_id(operator_id)
69+
.set_token_type(TokenType.FUNGIBLE_COMMON)
70+
.set_supply_type(SupplyType.FINITE)
71+
.set_max_supply(10000)
72+
.set_admin_key(operator_key)
73+
.set_supply_key(operator_key)
74+
.set_kyc_key(operator_key)
75+
.execute(client)
76+
)
77+
78+
if receipt.status != ResponseCode.SUCCESS:
79+
print(f"Token creation failed with status: {ResponseCode(receipt.status).name}")
80+
sys.exit(1)
81+
82+
token_id = receipt.tokenId
83+
print(f"\nFungible token created with ID: {token_id}")
84+
85+
return token_id
86+
87+
def create_nft(client, account_id, account_private_key):
88+
"""Create a non-fungible token"""
89+
receipt = (
90+
TokenCreateTransaction()
91+
.set_token_name("MyExampleNFT")
92+
.set_token_symbol("EXNFT")
93+
.set_decimals(0)
94+
.set_initial_supply(0)
95+
.set_treasury_account_id(account_id)
96+
.set_token_type(TokenType.NON_FUNGIBLE_UNIQUE)
97+
.set_supply_type(SupplyType.FINITE)
98+
.set_max_supply(100)
99+
.set_admin_key(account_private_key)
100+
.set_supply_key(account_private_key)
101+
.set_freeze_key(account_private_key)
102+
.freeze_with(client)
103+
.sign(account_private_key) # Sign with the account private key
104+
.execute(client)
105+
)
106+
107+
# Check if nft creation was successful
108+
if receipt.status != ResponseCode.SUCCESS:
109+
print(f"NFT creation failed with status: {ResponseCode(receipt.status).name}")
110+
sys.exit(1)
111+
112+
# Get token ID from receipt
113+
nft_token_id = receipt.tokenId
114+
print(f"\nNFT created with ID: {nft_token_id}")
115+
116+
return nft_token_id
117+
118+
def mint_nft(client, nft_token_id, account_private_key):
119+
"""Mint a non-fungible token"""
120+
receipt = (
121+
TokenMintTransaction()
122+
.set_token_id(nft_token_id)
123+
.set_metadata(b"My NFT Metadata 1")
124+
.freeze_with(client)
125+
.sign(account_private_key) # Sign with the account private key
126+
.execute(client)
127+
)
128+
129+
if receipt.status != ResponseCode.SUCCESS:
130+
print(f"NFT minting failed with status: {ResponseCode(receipt.status).name}")
131+
sys.exit(1)
132+
133+
print(f"\nNFT minted with serial number: {receipt.serial_numbers[0]}")
134+
135+
return NftId(nft_token_id, receipt.serial_numbers[0])
136+
137+
def associate_token_with_account(client, token_id, account_id, account_key):
138+
"""Associate the token with the test account"""
139+
receipt = (
140+
TokenAssociateTransaction()
141+
.set_account_id(account_id)
142+
.add_token_id(token_id)
143+
.freeze_with(client)
144+
.sign(account_key)
145+
.execute(client)
146+
)
147+
148+
if receipt.status != ResponseCode.SUCCESS:
149+
print(f"Token association failed with status: {ResponseCode(receipt.status).name}")
150+
sys.exit(1)
151+
152+
print(f"Token {token_id} associated with account {account_id}")
153+
154+
def grant_kyc_for_token(client, account_id, token_id):
155+
"""Grant KYC for the token to the account"""
156+
receipt = (
157+
TokenGrantKycTransaction()
158+
.set_account_id(account_id)
159+
.set_token_id(token_id)
160+
.execute(client)
161+
)
162+
163+
if receipt.status != ResponseCode.SUCCESS:
164+
print(f"KYC grant failed with status: {ResponseCode(receipt.status).name}")
165+
sys.exit(1)
166+
167+
print(f"\nKYC granted for token_id: {token_id}")
168+
169+
def display_account_info(info):
170+
"""Display basic account information"""
171+
print(f"\nAccount ID: {info.account_id}")
172+
print(f"Contract Account ID: {info.contract_account_id}")
173+
print(f"Account Balance: {info.balance}")
174+
print(f"Account Memo: '{info.account_memo}'")
175+
print(f"Is Deleted: {info.is_deleted}")
176+
print(f"Receiver Signature Required: {info.receiver_signature_required}")
177+
print(f"Owned NFTs: {info.owned_nfts}")
178+
179+
print(f"Public Key: {info.key.to_string()}")
180+
181+
print(f"Expiration Time: {info.expiration_time}")
182+
print(f"Auto Renew Period: {info.auto_renew_period}")
183+
184+
print(f"Proxy Received: {info.proxy_received}")
185+
186+
def display_token_relationships(info):
187+
"""Display token relationships information"""
188+
print(f"\nToken Relationships ({len(info.token_relationships)} total) for account {info.account_id}:")
189+
if info.token_relationships:
190+
for i, relationship in enumerate(info.token_relationships, 1):
191+
print(f" Token {i}:")
192+
print(f" Token ID: {relationship.token_id}")
193+
print(f" Symbol: {relationship.symbol}")
194+
print(f" Balance: {relationship.balance}")
195+
print(f" Decimals: {relationship.decimals}")
196+
print(f" Freeze Status: {relationship.freeze_status}")
197+
print(f" KYC Status: {relationship.kyc_status}")
198+
print(f" Automatic Association: {relationship.automatic_association}")
199+
else:
200+
print(" No token relationships found")
201+
202+
def query_account_info():
203+
"""
204+
Demonstrates the account info query functionality by:
205+
1. Setting up client with operator account
206+
2. Creating a new account
207+
3. Querying account info and displaying account information
208+
4. Creating a fungible token and associating it with the new account
209+
5. Querying account info to see token relationships
210+
6. Granting KYC to the new account for the token
211+
7. Querying account info again to see updated KYC status
212+
8. Creating an NFT token with the new account as treasury and minting one NFT
213+
9. Querying final account info to see complete token relationships and NFT ownership
214+
"""
215+
client, operator_id, operator_key = setup_client()
216+
217+
# Create a new account
218+
account_id, account_private_key = create_test_account(client, operator_key)
219+
220+
# Query the account info and display account information
221+
info = AccountInfoQuery(account_id).execute(client)
222+
print("\nAccount info query completed successfully!")
223+
display_account_info(info)
224+
225+
# Create a fungible token
226+
token_id = create_fungible_token(client, operator_id, operator_key)
227+
228+
# Associate the token with the account
229+
associate_token_with_account(client, token_id, account_id, account_private_key)
230+
231+
# Query the account info and display token relationships
232+
info = AccountInfoQuery(account_id).execute(client)
233+
print("\nToken info query completed successfully!")
234+
display_token_relationships(info)
235+
236+
# Grant KYC for the token
237+
print(f"\nGrant KYC for token: {token_id}")
238+
grant_kyc_for_token(client, account_id, token_id)
239+
240+
# Query the account info again and see the kyc status has been updated to GRANTED
241+
info = AccountInfoQuery(account_id).execute(client)
242+
print("\nAccount info query completed successfully!")
243+
display_token_relationships(info)
244+
245+
# Create an NFT token with the new account as the owner
246+
nft_token_id = create_nft(client, account_id, account_private_key)
247+
248+
# Mint an NFT to the account
249+
mint_nft(client, nft_token_id, account_private_key)
250+
251+
# Query the account info again and see that the account has 1 owned NFT
252+
# and the token relationship has been updated to include the NFT
253+
# NOTE: the newest token is the first in the list
254+
info = AccountInfoQuery(account_id).execute(client)
255+
display_account_info(info)
256+
display_token_relationships(info)
257+
258+
if __name__ == "__main__":
259+
query_account_info()

src/hiero_sdk_python/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# Account
66
from .account.account_id import AccountId
77
from .account.account_create_transaction import AccountCreateTransaction
8+
from .account.account_info import AccountInfo
89

910
# Crypto
1011
from .crypto.private_key import PrivateKey
@@ -32,6 +33,7 @@
3233
from .tokens.nft_id import NftId
3334
from .tokens.token_nft_transfer import TokenNftTransfer
3435
from .tokens.token_nft_info import TokenNftInfo
36+
from .tokens.token_relationship import TokenRelationship
3537

3638
# Transaction
3739
from .transaction.transfer_transaction import TransferTransaction
@@ -67,6 +69,7 @@
6769
from .query.account_balance_query import CryptoGetAccountBalanceQuery
6870
from .query.token_nft_info_query import TokenNftInfoQuery
6971
from .query.token_info_query import TokenInfoQuery
72+
from .query.account_info_query import AccountInfoQuery
7073

7174
# Address book
7275
from .address_book.endpoint import Endpoint
@@ -85,6 +88,7 @@
8588
# Account
8689
"AccountId",
8790
"AccountCreateTransaction",
91+
"AccountInfo",
8892

8993
# Crypto
9094
"PrivateKey",
@@ -108,7 +112,7 @@
108112
"TokenUpdateNftsTransaction",
109113
"TokenBurnTransaction",
110114
"TokenGrantKycTransaction",
111-
"TokenRevokeKycTransaction",
115+
"TokenRelationship",
112116
"TokenUpdateTransaction",
113117
"TokenType",
114118
"SupplyType",
@@ -138,6 +142,7 @@
138142
"CryptoGetAccountBalanceQuery",
139143
"TokenNftInfoQuery",
140144
"TokenInfoQuery",
145+
"AccountInfoQuery",
141146

142147
# Address book
143148
"Endpoint",

0 commit comments

Comments
 (0)