Skip to content

Commit ffd1928

Browse files
authored
Merge pull request #286 from InjectiveLabs/feat/initialize_tokens_from_chain_denoms
Feat/initialize tokens from chain denoms
2 parents 3261b40 + 7143944 commit ffd1928

15 files changed

+743
-12
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import asyncio
2+
3+
from pyinjective.async_client import AsyncClient
4+
from pyinjective.core.network import Network
5+
6+
7+
async def main() -> None:
8+
network = Network.testnet()
9+
client = AsyncClient(network)
10+
address = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
11+
spendable_balances = await client.fetch_spendable_balances(address=address)
12+
print(spendable_balances)
13+
14+
15+
if __name__ == "__main__":
16+
asyncio.get_event_loop().run_until_complete(main())
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import asyncio
2+
3+
from pyinjective.async_client import AsyncClient
4+
from pyinjective.core.network import Network
5+
6+
7+
async def main() -> None:
8+
network = Network.testnet()
9+
client = AsyncClient(network)
10+
address = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r"
11+
denom = "inj"
12+
spendable_balances = await client.fetch_spendable_balances_by_denom(address=address, denom=denom)
13+
print(spendable_balances)
14+
15+
16+
if __name__ == "__main__":
17+
asyncio.get_event_loop().run_until_complete(main())
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import asyncio
2+
3+
from pyinjective.async_client import AsyncClient
4+
from pyinjective.client.model.pagination import PaginationOption
5+
from pyinjective.core.network import Network
6+
7+
8+
async def main() -> None:
9+
network = Network.testnet()
10+
client = AsyncClient(network)
11+
total_supply = await client.fetch_total_supply(
12+
pagination=PaginationOption(limit=10),
13+
)
14+
print(total_supply)
15+
16+
17+
if __name__ == "__main__":
18+
asyncio.get_event_loop().run_until_complete(main())

examples/chain_client/53_SupplyOf.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import asyncio
2+
3+
from pyinjective.async_client import AsyncClient
4+
from pyinjective.core.network import Network
5+
6+
7+
async def main() -> None:
8+
network = Network.testnet()
9+
client = AsyncClient(network)
10+
supply_of = await client.fetch_supply_of(denom="inj")
11+
print(supply_of)
12+
13+
14+
if __name__ == "__main__":
15+
asyncio.get_event_loop().run_until_complete(main())
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import asyncio
2+
3+
from pyinjective.async_client import AsyncClient
4+
from pyinjective.core.network import Network
5+
6+
7+
async def main() -> None:
8+
network = Network.testnet()
9+
client = AsyncClient(network)
10+
denom = "factory/inj107aqkjc3t5r3l9j4n9lgrma5tm3jav8qgppz6m/position"
11+
metadata = await client.fetch_denom_metadata(denom=denom)
12+
print(metadata)
13+
14+
15+
if __name__ == "__main__":
16+
asyncio.get_event_loop().run_until_complete(main())
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import asyncio
2+
3+
from pyinjective.async_client import AsyncClient
4+
from pyinjective.client.model.pagination import PaginationOption
5+
from pyinjective.core.network import Network
6+
7+
8+
async def main() -> None:
9+
network = Network.testnet()
10+
client = AsyncClient(network)
11+
denoms = await client.fetch_denoms_metadata(
12+
pagination=PaginationOption(limit=10),
13+
)
14+
print(denoms)
15+
16+
17+
if __name__ == "__main__":
18+
asyncio.get_event_loop().run_until_complete(main())
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import asyncio
2+
3+
from pyinjective.async_client import AsyncClient
4+
from pyinjective.client.model.pagination import PaginationOption
5+
from pyinjective.core.network import Network
6+
7+
8+
async def main() -> None:
9+
network = Network.testnet()
10+
client = AsyncClient(network)
11+
denom = "inj"
12+
owners = await client.fetch_denom_owners(
13+
denom=denom,
14+
pagination=PaginationOption(limit=10),
15+
)
16+
print(owners)
17+
18+
19+
if __name__ == "__main__":
20+
asyncio.get_event_loop().run_until_complete(main())
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import asyncio
2+
3+
from pyinjective.async_client import AsyncClient
4+
from pyinjective.client.model.pagination import PaginationOption
5+
from pyinjective.core.network import Network
6+
7+
8+
async def main() -> None:
9+
network = Network.testnet()
10+
client = AsyncClient(network)
11+
denom = "inj"
12+
enabled = await client.fetch_send_enabled(
13+
denoms=[denom],
14+
pagination=PaginationOption(limit=10),
15+
)
16+
print(enabled)
17+
18+
19+
if __name__ == "__main__":
20+
asyncio.get_event_loop().run_until_complete(main())

pyinjective/async_client.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import base64
23
import time
34
from copy import deepcopy
45
from decimal import Decimal
@@ -522,6 +523,42 @@ async def get_bank_balance(self, address: str, denom: str):
522523
async def fetch_bank_balance(self, address: str, denom: str) -> Dict[str, Any]:
523524
return await self.bank_api.fetch_balance(account_address=address, denom=denom)
524525

526+
async def fetch_spendable_balances(
527+
self,
528+
address: str,
529+
pagination: Optional[PaginationOption] = None,
530+
) -> Dict[str, Any]:
531+
return await self.bank_api.fetch_spendable_balances(account_address=address, pagination=pagination)
532+
533+
async def fetch_spendable_balances_by_denom(
534+
self,
535+
address: str,
536+
denom: str,
537+
) -> Dict[str, Any]:
538+
return await self.bank_api.fetch_spendable_balances_by_denom(account_address=address, denom=denom)
539+
540+
async def fetch_total_supply(self, pagination: Optional[PaginationOption] = None) -> Dict[str, Any]:
541+
return await self.bank_api.fetch_total_supply(pagination=pagination)
542+
543+
async def fetch_supply_of(self, denom: str) -> Dict[str, Any]:
544+
return await self.bank_api.fetch_supply_of(denom=denom)
545+
546+
async def fetch_denom_metadata(self, denom: str) -> Dict[str, Any]:
547+
return await self.bank_api.fetch_denom_metadata(denom=denom)
548+
549+
async def fetch_denoms_metadata(self, pagination: Optional[PaginationOption] = None) -> Dict[str, Any]:
550+
return await self.bank_api.fetch_denoms_metadata(pagination=pagination)
551+
552+
async def fetch_denom_owners(self, denom: str, pagination: Optional[PaginationOption] = None) -> Dict[str, Any]:
553+
return await self.bank_api.fetch_denom_owners(denom=denom, pagination=pagination)
554+
555+
async def fetch_send_enabled(
556+
self,
557+
denoms: Optional[List[str]] = None,
558+
pagination: Optional[PaginationOption] = None,
559+
) -> Dict[str, Any]:
560+
return await self.bank_api.fetch_send_enabled(denoms=denoms, pagination=pagination)
561+
525562
# Injective Exchange client methods
526563

527564
# Auction RPC
@@ -2461,6 +2498,51 @@ async def composer(self):
24612498
tokens=await self.all_tokens(),
24622499
)
24632500

2501+
async def initialize_tokens_from_chain_denoms(self):
2502+
# force initialization of markets and tokens
2503+
await self.all_tokens()
2504+
2505+
all_denoms_metadata = []
2506+
2507+
query_result = await self.fetch_denoms_metadata()
2508+
2509+
all_denoms_metadata.extend(query_result.get("metadatas", []))
2510+
next_key = query_result.get("pagination", {}).get("nextKey", "")
2511+
2512+
while next_key != "":
2513+
query_result = await self.fetch_denoms_metadata(pagination=PaginationOption(key=next_key))
2514+
2515+
all_denoms_metadata.extend(query_result.get("metadatas", []))
2516+
result_next_key = query_result.get("pagination", {}).get("nextKey", "")
2517+
next_key = base64.b64decode(result_next_key).decode()
2518+
2519+
for token_metadata in all_denoms_metadata:
2520+
symbol = token_metadata["symbol"]
2521+
denom = token_metadata["base"]
2522+
2523+
if denom != "" and symbol != "" and denom not in self._tokens_by_denom:
2524+
name = token_metadata["name"] or symbol
2525+
decimals = max({denom_unit["exponent"] for denom_unit in token_metadata["denomUnits"]})
2526+
2527+
unique_symbol = denom
2528+
for symbol_candidate in [symbol, name]:
2529+
if symbol_candidate not in self._tokens_by_symbol:
2530+
unique_symbol = symbol_candidate
2531+
break
2532+
2533+
token = Token(
2534+
name=name,
2535+
symbol=symbol,
2536+
denom=denom,
2537+
address="",
2538+
decimals=decimals,
2539+
logo=token_metadata["uri"],
2540+
updated=-1,
2541+
)
2542+
2543+
self._tokens_by_denom[denom] = token
2544+
self._tokens_by_symbol[unique_symbol] = token
2545+
24642546
async def _initialize_tokens_and_markets(self):
24652547
spot_markets = dict()
24662548
derivative_markets = dict()

pyinjective/client/chain/grpc/chain_grpc_bank_api.py

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
from typing import Any, Callable, Dict
1+
from typing import Any, Callable, Dict, List, Optional
22

33
from grpc.aio import Channel
44

5+
from pyinjective.client.model.pagination import PaginationOption
56
from pyinjective.proto.cosmos.bank.v1beta1 import query_pb2 as bank_query_pb, query_pb2_grpc as bank_query_grpc
67
from pyinjective.utils.grpc_api_request_assistant import GrpcApiRequestAssistant
78

@@ -29,11 +30,86 @@ async def fetch_balances(self, account_address: str) -> Dict[str, Any]:
2930

3031
return response
3132

32-
async def fetch_total_supply(self) -> Dict[str, Any]:
33-
request = bank_query_pb.QueryTotalSupplyRequest()
33+
async def fetch_spendable_balances(
34+
self,
35+
account_address: str,
36+
pagination: Optional[PaginationOption] = None,
37+
) -> Dict[str, Any]:
38+
pagination_request = None
39+
if pagination is not None:
40+
pagination_request = pagination.create_pagination_request()
41+
request = bank_query_pb.QuerySpendableBalancesRequest(
42+
address=account_address,
43+
pagination=pagination_request,
44+
)
45+
response = await self._execute_call(call=self._stub.SpendableBalances, request=request)
46+
47+
return response
48+
49+
async def fetch_spendable_balances_by_denom(
50+
self,
51+
account_address: str,
52+
denom: str,
53+
) -> Dict[str, Any]:
54+
request = bank_query_pb.QuerySpendableBalanceByDenomRequest(
55+
address=account_address,
56+
denom=denom,
57+
)
58+
response = await self._execute_call(call=self._stub.SpendableBalanceByDenom, request=request)
59+
60+
return response
61+
62+
async def fetch_total_supply(self, pagination: Optional[PaginationOption] = None) -> Dict[str, Any]:
63+
pagination_request = None
64+
if pagination is not None:
65+
pagination_request = pagination.create_pagination_request()
66+
request = bank_query_pb.QueryTotalSupplyRequest(pagination=pagination_request)
3467
response = await self._execute_call(call=self._stub.TotalSupply, request=request)
3568

3669
return response
3770

71+
async def fetch_supply_of(self, denom: str) -> Dict[str, Any]:
72+
request = bank_query_pb.QuerySupplyOfRequest(denom=denom)
73+
response = await self._execute_call(call=self._stub.SupplyOf, request=request)
74+
75+
return response
76+
77+
async def fetch_denom_metadata(self, denom: str) -> Dict[str, Any]:
78+
request = bank_query_pb.QueryDenomMetadataRequest(denom=denom)
79+
response = await self._execute_call(call=self._stub.DenomMetadata, request=request)
80+
81+
return response
82+
83+
async def fetch_denoms_metadata(self, pagination: Optional[PaginationOption] = None) -> Dict[str, Any]:
84+
pagination_request = None
85+
if pagination is not None:
86+
pagination_request = pagination.create_pagination_request()
87+
request = bank_query_pb.QueryDenomsMetadataRequest(pagination=pagination_request)
88+
response = await self._execute_call(call=self._stub.DenomsMetadata, request=request)
89+
90+
return response
91+
92+
async def fetch_denom_owners(self, denom: str, pagination: Optional[PaginationOption] = None) -> Dict[str, Any]:
93+
pagination_request = None
94+
if pagination is not None:
95+
pagination_request = pagination.create_pagination_request()
96+
request = bank_query_pb.QueryDenomOwnersRequest(denom=denom, pagination=pagination_request)
97+
response = await self._execute_call(call=self._stub.DenomOwners, request=request)
98+
99+
return response
100+
101+
async def fetch_send_enabled(
102+
self,
103+
denoms: Optional[List[str]] = None,
104+
pagination: Optional[PaginationOption] = None,
105+
) -> Dict[str, Any]:
106+
pagination_request = None
107+
if pagination is not None:
108+
pagination_request = pagination.create_pagination_request()
109+
request = bank_query_pb.QuerySendEnabledRequest(denoms=denoms, pagination=pagination_request)
110+
response = await self._execute_call(call=self._stub.SendEnabled, request=request)
111+
112+
return response
113+
38114
async def _execute_call(self, call: Callable, request) -> Dict[str, Any]:
39115
return await self._assistant.execute_call(call=call, request=request)

pyinjective/client/model/pagination.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def create_pagination_request(self) -> pagination_pb.PageRequest:
3131
page_request = pagination_pb.PageRequest()
3232

3333
if self.key is not None:
34-
page_request.key = bytes.fromhex(self.key)
34+
page_request.key = self.key.encode()
3535
if self.skip is not None:
3636
page_request.offset = self.skip
3737
if self.limit is not None:

0 commit comments

Comments
 (0)