pytonapi 0.3.6__tar.gz → 0.3.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pytonapi-0.3.7/PKG-INFO +134 -0
- pytonapi-0.3.7/README.md +114 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/__init__.py +21 -8
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/client.py +65 -25
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/__init__.py +4 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/accounts.py +13 -32
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/blockchain.py +2 -14
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/dns.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/emulate.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/events.py +4 -4
- pytonapi-0.3.7/pytonapi/async_tonapi/methods/gasless.py +56 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/inscriptions.py +3 -3
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/jettons.py +3 -3
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/liteserver.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/nft.py +4 -8
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/rates.py +17 -6
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/sse.py +12 -12
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/staking.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/storage.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/tonconnect.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/traces.py +4 -4
- pytonapi-0.3.7/pytonapi/async_tonapi/methods/utilites.py +28 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/wallet.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/async_tonapi/methods/websocket.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/exceptions.py +1 -1
- pytonapi-0.3.7/pytonapi/logger_config.py +25 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/__init__.py +2 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/_address.py +5 -10
- pytonapi-0.3.7/pytonapi/schema/_balance.py +31 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/accounts.py +14 -26
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/blockchain.py +24 -29
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/dns.py +4 -4
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/domains.py +3 -3
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/events.py +49 -49
- pytonapi-0.3.7/pytonapi/schema/gasless.py +27 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/inscriptions.py +1 -1
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/jettons.py +8 -7
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/liteserver.py +1 -1
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/nft.py +11 -11
- pytonapi-0.3.7/pytonapi/schema/rates.py +28 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/staking.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/storage.py +1 -1
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/tonconnect.py +1 -1
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/schema/traces.py +26 -26
- pytonapi-0.3.7/pytonapi/schema/utilites.py +20 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/__init__.py +36 -22
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/client.py +64 -23
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/__init__.py +4 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/accounts.py +14 -33
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/blockchain.py +2 -14
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/dns.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/emulate.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/events.py +4 -4
- pytonapi-0.3.7/pytonapi/tonapi/methods/gasless.py +56 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/inscriptions.py +3 -3
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/jettons.py +3 -4
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/liteserver.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/nft.py +33 -29
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/rates.py +18 -6
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/sse.py +13 -13
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/staking.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/storage.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/tonconnect.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/traces.py +4 -5
- pytonapi-0.3.7/pytonapi/tonapi/methods/utilites.py +28 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/tonapi/methods/wallet.py +2 -2
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/utils.py +17 -15
- pytonapi-0.3.7/pytonapi.egg-info/PKG-INFO +134 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi.egg-info/SOURCES.txt +41 -1
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi.egg-info/top_level.txt +1 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/setup.py +1 -1
- pytonapi-0.3.7/tests/async_tonapi/__init__.py +11 -0
- pytonapi-0.3.7/tests/async_tonapi/test_accounts_methods.py +86 -0
- pytonapi-0.3.7/tests/async_tonapi/test_blockchain_methods.py +81 -0
- pytonapi-0.3.7/tests/async_tonapi/test_dns_methods.py +23 -0
- pytonapi-0.3.7/tests/async_tonapi/test_events_methods.py +16 -0
- pytonapi-0.3.7/tests/async_tonapi/test_inscriptions_methods.py +25 -0
- pytonapi-0.3.7/tests/async_tonapi/test_jettons_methods.py +28 -0
- pytonapi-0.3.7/tests/async_tonapi/test_liteserver_methods.py +11 -0
- pytonapi-0.3.7/tests/async_tonapi/test_nft_methods.py +41 -0
- pytonapi-0.3.7/tests/async_tonapi/test_rates_methods.py +21 -0
- pytonapi-0.3.7/tests/async_tonapi/test_sse_methods.py +25 -0
- pytonapi-0.3.7/tests/async_tonapi/test_staking_methods.py +24 -0
- pytonapi-0.3.7/tests/async_tonapi/test_storage_methods.py +9 -0
- pytonapi-0.3.7/tests/async_tonapi/test_tonconnect_methods.py +11 -0
- pytonapi-0.3.7/tests/async_tonapi/test_traces_methods.py +15 -0
- pytonapi-0.3.7/tests/async_tonapi/test_utilities_methods.py +15 -0
- pytonapi-0.3.7/tests/async_tonapi/test_websocket_methods.py +22 -0
- pytonapi-0.3.7/tests/tonapi/__init__.py +11 -0
- pytonapi-0.3.7/tests/tonapi/test_accounts_methods.py +86 -0
- pytonapi-0.3.7/tests/tonapi/test_blockchain_methods.py +81 -0
- pytonapi-0.3.7/tests/tonapi/test_dns_methods.py +23 -0
- pytonapi-0.3.7/tests/tonapi/test_events_methods.py +16 -0
- pytonapi-0.3.7/tests/tonapi/test_inscriptions_methods.py +25 -0
- pytonapi-0.3.7/tests/tonapi/test_jettons_methods.py +28 -0
- pytonapi-0.3.7/tests/tonapi/test_liteserver_methods.py +11 -0
- pytonapi-0.3.7/tests/tonapi/test_nft_methods.py +42 -0
- pytonapi-0.3.7/tests/tonapi/test_rates_methods.py +21 -0
- pytonapi-0.3.7/tests/tonapi/test_sse_methods.py +25 -0
- pytonapi-0.3.7/tests/tonapi/test_staking_methods.py +24 -0
- pytonapi-0.3.7/tests/tonapi/test_storage_methods.py +9 -0
- pytonapi-0.3.7/tests/tonapi/test_tonconnect_methods.py +11 -0
- pytonapi-0.3.7/tests/tonapi/test_traces_methods.py +15 -0
- pytonapi-0.3.7/tests/tonapi/test_utilities_methods.py +15 -0
- pytonapi-0.3.6/PKG-INFO +0 -168
- pytonapi-0.3.6/README.md +0 -148
- pytonapi-0.3.6/pytonapi/schema/_balance.py +0 -33
- pytonapi-0.3.6/pytonapi/schema/rates.py +0 -18
- pytonapi-0.3.6/pytonapi.egg-info/PKG-INFO +0 -168
- {pytonapi-0.3.6 → pytonapi-0.3.7}/LICENSE +0 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/__init__.py +0 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi/py.typed +0 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi.egg-info/dependency_links.txt +0 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/pytonapi.egg-info/requires.txt +0 -0
- {pytonapi-0.3.6 → pytonapi-0.3.7}/setup.cfg +0 -0
pytonapi-0.3.7/PKG-INFO
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pytonapi
|
|
3
|
+
Version: 0.3.7
|
|
4
|
+
Summary: Provide access to indexed TON blockchain.
|
|
5
|
+
Home-page: https://github.com/tonkeeper/pytonapi/
|
|
6
|
+
Author: nessshon
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: httpx>=0.26.0
|
|
18
|
+
Requires-Dist: websockets>=12.0
|
|
19
|
+
Requires-Dist: pydantic==2.*
|
|
20
|
+
|
|
21
|
+
# 📦 PyTONAPI
|
|
22
|
+
|
|
23
|
+
[](https://ton.org)
|
|
24
|
+
[](https://pypi.python.org/pypi/pytonapi)
|
|
25
|
+

|
|
26
|
+
[](https://github.com/tonkeeper/pytonapi/blob/main/LICENSE)
|
|
27
|
+
|
|
28
|
+

|
|
29
|
+
|
|
30
|
+

|
|
31
|
+

|
|
32
|
+

|
|
33
|
+
|
|
34
|
+
Python SDK for [tonapi.io](https://tonapi.io).\
|
|
35
|
+
Information about the API can be found in the [documentation](https://docs.tonconsole.com/tonapi/api-v2).\
|
|
36
|
+
To use the API **you need an API key**, you can get it here [tonconsole.com](https://tonconsole.com/).
|
|
37
|
+
|
|
38
|
+
<blockquote>
|
|
39
|
+
For creating wallets, transferring TON, Jetton, NFTs, and other operations, recommend using <a href="https://github.com/nessshon/tonutils">tonutils</a> in combination with <code>TonapiClient</code>. For more information, refer to the library documentation.
|
|
40
|
+
</blockquote>
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
### Installation
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install pytonapi
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Examples
|
|
51
|
+
|
|
52
|
+
* **Asynchronous**
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from pytonapi import AsyncTonapi
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# Declare an asynchronous function for using await
|
|
59
|
+
async def main():
|
|
60
|
+
# Create a new Tonapi object with the provided API key
|
|
61
|
+
tonapi = AsyncTonapi(api_key="Your API key")
|
|
62
|
+
|
|
63
|
+
# Specify the account ID
|
|
64
|
+
account_id = "EQC-3ilVr-W0Uc3pLrGJElwSaFxvhXXfkiQA3EwdVBHNNess" # noqa
|
|
65
|
+
|
|
66
|
+
# Retrieve account information asynchronously
|
|
67
|
+
account = await tonapi.accounts.get_info(account_id=account_id)
|
|
68
|
+
|
|
69
|
+
# Print account details
|
|
70
|
+
print(f"Account Address (raw): {account.address.to_raw()}")
|
|
71
|
+
print(f"Account Address (userfriendly): {account.address.to_userfriendly(is_bounceable=True)}")
|
|
72
|
+
print(f"Account Balance (nanoton): {account.balance.to_nano()}")
|
|
73
|
+
print(f"Account Balance (amount): {account.balance.to_amount()}")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == '__main__':
|
|
77
|
+
import asyncio
|
|
78
|
+
|
|
79
|
+
# Run the asynchronous function
|
|
80
|
+
asyncio.run(main())
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
* **Synchronous**
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from pytonapi import Tonapi
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def main():
|
|
91
|
+
# Create a new Tonapi object with the provided API key
|
|
92
|
+
tonapi = Tonapi(api_key="Your API key")
|
|
93
|
+
|
|
94
|
+
# Specify the account ID
|
|
95
|
+
account_id = "EQC-3ilVr-W0Uc3pLrGJElwSaFxvhXXfkiQA3EwdVBHNNess" # noqa
|
|
96
|
+
|
|
97
|
+
# Retrieve account information
|
|
98
|
+
account = tonapi.accounts.get_info(account_id=account_id)
|
|
99
|
+
|
|
100
|
+
# Print account details
|
|
101
|
+
print(f"Account Address (raw): {account.address.to_raw()}")
|
|
102
|
+
print(f"Account Address (userfriendly): {account.address.to_userfriendly(is_bounceable=True)}")
|
|
103
|
+
print(f"Account Balance (nanoton): {account.balance.to_nano()}")
|
|
104
|
+
print(f"Account Balance (amount): {account.balance.to_amount()}")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__ == '__main__':
|
|
108
|
+
main()
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
* **Additional examples** can be found [examples](https://github.com/tonkeeper/pytonapi/tree/main/examples) folder.
|
|
112
|
+
|
|
113
|
+
## Donations
|
|
114
|
+
|
|
115
|
+
**TON** - `EQC-3ilVr-W0Uc3pLrGJElwSaFxvhXXfkiQA3EwdVBHNNess`
|
|
116
|
+
|
|
117
|
+
**USDT** (TRC-20) - `TJjADKFT2i7jqNJAxkgeRm5o9uarcoLUeR`
|
|
118
|
+
|
|
119
|
+
## Contribution
|
|
120
|
+
|
|
121
|
+
We welcome your contributions! If you have ideas for improvement or have identified a bug, please create an issue or
|
|
122
|
+
submit a pull request.
|
|
123
|
+
|
|
124
|
+
## Support
|
|
125
|
+
|
|
126
|
+
Supported by [TONAPI](https://tonapi.io) and [TON Society](https://github.com/ton-society/grants-and-bounties) (Grants
|
|
127
|
+
and Bounties program).
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
This repository is distributed under the [MIT License](https://github.com/tonkeeper/pytonapi/blob/main/LICENSE). Feel
|
|
132
|
+
free to use, modify, and distribute the code in accordance
|
|
133
|
+
with the terms of the license.
|
|
134
|
+
|
pytonapi-0.3.7/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# 📦 PyTONAPI
|
|
2
|
+
|
|
3
|
+
[](https://ton.org)
|
|
4
|
+
[](https://pypi.python.org/pypi/pytonapi)
|
|
5
|
+

|
|
6
|
+
[](https://github.com/tonkeeper/pytonapi/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+

|
|
11
|
+

|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
Python SDK for [tonapi.io](https://tonapi.io).\
|
|
15
|
+
Information about the API can be found in the [documentation](https://docs.tonconsole.com/tonapi/api-v2).\
|
|
16
|
+
To use the API **you need an API key**, you can get it here [tonconsole.com](https://tonconsole.com/).
|
|
17
|
+
|
|
18
|
+
<blockquote>
|
|
19
|
+
For creating wallets, transferring TON, Jetton, NFTs, and other operations, recommend using <a href="https://github.com/nessshon/tonutils">tonutils</a> in combination with <code>TonapiClient</code>. For more information, refer to the library documentation.
|
|
20
|
+
</blockquote>
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install pytonapi
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Examples
|
|
31
|
+
|
|
32
|
+
* **Asynchronous**
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from pytonapi import AsyncTonapi
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Declare an asynchronous function for using await
|
|
39
|
+
async def main():
|
|
40
|
+
# Create a new Tonapi object with the provided API key
|
|
41
|
+
tonapi = AsyncTonapi(api_key="Your API key")
|
|
42
|
+
|
|
43
|
+
# Specify the account ID
|
|
44
|
+
account_id = "EQC-3ilVr-W0Uc3pLrGJElwSaFxvhXXfkiQA3EwdVBHNNess" # noqa
|
|
45
|
+
|
|
46
|
+
# Retrieve account information asynchronously
|
|
47
|
+
account = await tonapi.accounts.get_info(account_id=account_id)
|
|
48
|
+
|
|
49
|
+
# Print account details
|
|
50
|
+
print(f"Account Address (raw): {account.address.to_raw()}")
|
|
51
|
+
print(f"Account Address (userfriendly): {account.address.to_userfriendly(is_bounceable=True)}")
|
|
52
|
+
print(f"Account Balance (nanoton): {account.balance.to_nano()}")
|
|
53
|
+
print(f"Account Balance (amount): {account.balance.to_amount()}")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
if __name__ == '__main__':
|
|
57
|
+
import asyncio
|
|
58
|
+
|
|
59
|
+
# Run the asynchronous function
|
|
60
|
+
asyncio.run(main())
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
* **Synchronous**
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from pytonapi import Tonapi
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def main():
|
|
71
|
+
# Create a new Tonapi object with the provided API key
|
|
72
|
+
tonapi = Tonapi(api_key="Your API key")
|
|
73
|
+
|
|
74
|
+
# Specify the account ID
|
|
75
|
+
account_id = "EQC-3ilVr-W0Uc3pLrGJElwSaFxvhXXfkiQA3EwdVBHNNess" # noqa
|
|
76
|
+
|
|
77
|
+
# Retrieve account information
|
|
78
|
+
account = tonapi.accounts.get_info(account_id=account_id)
|
|
79
|
+
|
|
80
|
+
# Print account details
|
|
81
|
+
print(f"Account Address (raw): {account.address.to_raw()}")
|
|
82
|
+
print(f"Account Address (userfriendly): {account.address.to_userfriendly(is_bounceable=True)}")
|
|
83
|
+
print(f"Account Balance (nanoton): {account.balance.to_nano()}")
|
|
84
|
+
print(f"Account Balance (amount): {account.balance.to_amount()}")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
if __name__ == '__main__':
|
|
88
|
+
main()
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
* **Additional examples** can be found [examples](https://github.com/tonkeeper/pytonapi/tree/main/examples) folder.
|
|
92
|
+
|
|
93
|
+
## Donations
|
|
94
|
+
|
|
95
|
+
**TON** - `EQC-3ilVr-W0Uc3pLrGJElwSaFxvhXXfkiQA3EwdVBHNNess`
|
|
96
|
+
|
|
97
|
+
**USDT** (TRC-20) - `TJjADKFT2i7jqNJAxkgeRm5o9uarcoLUeR`
|
|
98
|
+
|
|
99
|
+
## Contribution
|
|
100
|
+
|
|
101
|
+
We welcome your contributions! If you have ideas for improvement or have identified a bug, please create an issue or
|
|
102
|
+
submit a pull request.
|
|
103
|
+
|
|
104
|
+
## Support
|
|
105
|
+
|
|
106
|
+
Supported by [TONAPI](https://tonapi.io) and [TON Society](https://github.com/ton-society/grants-and-bounties) (Grants
|
|
107
|
+
and Bounties program).
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
This repository is distributed under the [MIT License](https://github.com/tonkeeper/pytonapi/blob/main/LICENSE). Feel
|
|
112
|
+
free to use, modify, and distribute the code in accordance
|
|
113
|
+
with the terms of the license.
|
|
114
|
+
|
|
@@ -1,36 +1,39 @@
|
|
|
1
1
|
from typing import Any, Dict, Optional
|
|
2
2
|
|
|
3
3
|
from pytonapi.async_tonapi import methods
|
|
4
|
-
from pytonapi.async_tonapi.client import
|
|
4
|
+
from pytonapi.async_tonapi.client import AsyncTonapiClientBase
|
|
5
5
|
|
|
6
6
|
__all__ = [
|
|
7
7
|
"AsyncTonapi",
|
|
8
|
-
"
|
|
8
|
+
"AsyncTonapiClientBase",
|
|
9
9
|
]
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class AsyncTonapi(
|
|
12
|
+
class AsyncTonapi(AsyncTonapiClientBase):
|
|
13
13
|
|
|
14
14
|
def __init__(
|
|
15
15
|
self,
|
|
16
16
|
api_key: str,
|
|
17
|
-
is_testnet:
|
|
18
|
-
max_retries:
|
|
17
|
+
is_testnet: bool = False,
|
|
18
|
+
max_retries: int = 0,
|
|
19
19
|
base_url: Optional[str] = None,
|
|
20
20
|
websocket_url: Optional[str] = None,
|
|
21
21
|
headers: Optional[Dict[str, Any]] = None,
|
|
22
22
|
timeout: Optional[float] = None,
|
|
23
|
+
debug: bool = False,
|
|
24
|
+
**kwargs,
|
|
23
25
|
) -> None:
|
|
24
26
|
"""
|
|
25
27
|
Initialize the AsyncTonapiClient.
|
|
26
28
|
|
|
27
29
|
:param api_key: The API key.
|
|
30
|
+
:param is_testnet: Use True if using the testnet.
|
|
31
|
+
:param max_retries: Maximum number of retries per request if rate limit is reached.
|
|
28
32
|
:param base_url: The base URL for the API.
|
|
29
33
|
:param websocket_url: The URL for the WebSocket server.
|
|
30
|
-
:param is_testnet: Use True if using the testnet.
|
|
31
|
-
:param timeout: Request timeout in seconds.
|
|
32
34
|
:param headers: Additional headers to include in requests.
|
|
33
|
-
:param
|
|
35
|
+
:param timeout: Request timeout in seconds.
|
|
36
|
+
:param debug: Enable debug mode.
|
|
34
37
|
"""
|
|
35
38
|
super().__init__(
|
|
36
39
|
api_key=api_key,
|
|
@@ -40,6 +43,8 @@ class AsyncTonapi(AsyncTonapiClient):
|
|
|
40
43
|
websocket_url=websocket_url,
|
|
41
44
|
headers=headers,
|
|
42
45
|
timeout=timeout,
|
|
46
|
+
debug=debug,
|
|
47
|
+
**kwargs,
|
|
43
48
|
)
|
|
44
49
|
|
|
45
50
|
@property
|
|
@@ -70,6 +75,10 @@ class AsyncTonapi(AsyncTonapiClient):
|
|
|
70
75
|
def events(self) -> methods.EventsMethod:
|
|
71
76
|
return methods.EventsMethod(**self.__dict__)
|
|
72
77
|
|
|
78
|
+
@property
|
|
79
|
+
def gasless(self) -> methods.GaslessMethod:
|
|
80
|
+
return methods.GaslessMethod(**self.__dict__)
|
|
81
|
+
|
|
73
82
|
@property
|
|
74
83
|
def inscriptions(self) -> methods.InscriptionsMethod:
|
|
75
84
|
return methods.InscriptionsMethod(**self.__dict__)
|
|
@@ -102,6 +111,10 @@ class AsyncTonapi(AsyncTonapiClient):
|
|
|
102
111
|
def traces(self) -> methods.TracesMethod:
|
|
103
112
|
return methods.TracesMethod(**self.__dict__)
|
|
104
113
|
|
|
114
|
+
@property
|
|
115
|
+
def utilities(self) -> methods.UtilitiesMethod:
|
|
116
|
+
return methods.UtilitiesMethod(**self.__dict__)
|
|
117
|
+
|
|
105
118
|
@property
|
|
106
119
|
def wallet(self) -> methods.WalletMethod:
|
|
107
120
|
return methods.WalletMethod(**self.__dict__)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import json
|
|
3
|
-
import logging
|
|
4
3
|
from typing import Any, Dict, Optional, AsyncGenerator
|
|
5
4
|
|
|
6
5
|
import httpx
|
|
7
6
|
import websockets
|
|
7
|
+
from httpx import URL, QueryParams
|
|
8
8
|
|
|
9
9
|
from pytonapi.exceptions import (
|
|
10
10
|
TONAPIBadRequestError,
|
|
@@ -16,9 +16,10 @@ from pytonapi.exceptions import (
|
|
|
16
16
|
TONAPINotImplementedError,
|
|
17
17
|
TONAPISSEError,
|
|
18
18
|
)
|
|
19
|
+
from pytonapi.logger_config import setup_logging
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
class
|
|
22
|
+
class AsyncTonapiClientBase:
|
|
22
23
|
"""
|
|
23
24
|
Asynchronous TON API Client.
|
|
24
25
|
"""
|
|
@@ -26,23 +27,26 @@ class AsyncTonapiClient:
|
|
|
26
27
|
def __init__(
|
|
27
28
|
self,
|
|
28
29
|
api_key: str,
|
|
29
|
-
is_testnet:
|
|
30
|
-
max_retries:
|
|
30
|
+
is_testnet: bool = False,
|
|
31
|
+
max_retries: int = 0,
|
|
31
32
|
base_url: Optional[str] = None,
|
|
32
33
|
websocket_url: Optional[str] = None,
|
|
33
34
|
headers: Optional[Dict[str, Any]] = None,
|
|
34
35
|
timeout: Optional[float] = None,
|
|
36
|
+
debug: bool = False,
|
|
37
|
+
**kwargs,
|
|
35
38
|
) -> None:
|
|
36
39
|
"""
|
|
37
40
|
Initialize the AsyncTonapiClient.
|
|
38
41
|
|
|
39
42
|
:param api_key: The API key.
|
|
43
|
+
:param is_testnet: Use True if using the testnet.
|
|
44
|
+
:param max_retries: Maximum number of retries per request if rate limit is reached.
|
|
40
45
|
:param base_url: The base URL for the API.
|
|
41
46
|
:param websocket_url: The URL for the WebSocket server.
|
|
42
|
-
:param is_testnet: Use True if using the testnet.
|
|
43
|
-
:param timeout: Request timeout in seconds.
|
|
44
47
|
:param headers: Additional headers to include in requests.
|
|
45
|
-
:param
|
|
48
|
+
:param timeout: Request timeout in seconds.
|
|
49
|
+
:param debug: Enable debug mode.
|
|
46
50
|
"""
|
|
47
51
|
self.api_key = api_key
|
|
48
52
|
self.is_testnet = is_testnet
|
|
@@ -53,6 +57,9 @@ class AsyncTonapiClient:
|
|
|
53
57
|
self.websocket_url = websocket_url or "wss://tonapi.io/v2/websocket"
|
|
54
58
|
self.headers = headers or {"Authorization": f"Bearer {api_key}"}
|
|
55
59
|
|
|
60
|
+
self.debug = debug
|
|
61
|
+
self.logger = setup_logging(self.debug)
|
|
62
|
+
|
|
56
63
|
@staticmethod
|
|
57
64
|
async def __read_content(response: httpx.Response) -> Any:
|
|
58
65
|
"""
|
|
@@ -97,15 +104,18 @@ class AsyncTonapiClient:
|
|
|
97
104
|
501: TONAPINotImplementedError,
|
|
98
105
|
}
|
|
99
106
|
error_class = error_map.get(response.status_code, TONAPIError)
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
|
|
108
|
+
if isinstance(content, dict):
|
|
109
|
+
content = content.get("error") or content.get("Error")
|
|
110
|
+
self.logger.error(f"Error response received: {content}")
|
|
111
|
+
raise error_class(content)
|
|
102
112
|
|
|
103
113
|
return content
|
|
104
114
|
|
|
105
115
|
async def _subscribe(
|
|
106
116
|
self,
|
|
107
117
|
method: str,
|
|
108
|
-
params:
|
|
118
|
+
params: Dict[str, Any],
|
|
109
119
|
) -> AsyncGenerator[str, None]:
|
|
110
120
|
"""
|
|
111
121
|
Subscribe to an SSE event stream.
|
|
@@ -115,26 +125,36 @@ class AsyncTonapiClient:
|
|
|
115
125
|
"""
|
|
116
126
|
url = self.base_url + method
|
|
117
127
|
timeout = httpx.Timeout(timeout=self.timeout)
|
|
118
|
-
data = {"headers": self.headers, "params": params, "timeout": timeout}
|
|
119
128
|
|
|
129
|
+
self.logger.debug(f"Subscribing to SSE with URL: {url} and params: {params}")
|
|
120
130
|
async with httpx.AsyncClient() as client:
|
|
121
131
|
try:
|
|
122
|
-
async with client.stream(
|
|
123
|
-
|
|
132
|
+
async with client.stream(
|
|
133
|
+
method="GET",
|
|
134
|
+
url=url,
|
|
135
|
+
headers=self.headers,
|
|
136
|
+
params=params or {},
|
|
137
|
+
timeout=timeout,
|
|
138
|
+
) as response:
|
|
124
139
|
response.raise_for_status()
|
|
125
140
|
|
|
126
141
|
async for line in response.aiter_lines():
|
|
127
142
|
try:
|
|
128
143
|
key, value = line.split(": ", 1)
|
|
129
144
|
except ValueError:
|
|
145
|
+
self.logger.debug(f"Skipped line due to ValueError: {line}")
|
|
130
146
|
continue
|
|
131
147
|
if value == "heartbeat":
|
|
148
|
+
self.logger.debug("Received heartbeat")
|
|
132
149
|
continue
|
|
133
150
|
if key == "data":
|
|
151
|
+
self.logger.debug(f"Received SSE data: {value}")
|
|
134
152
|
yield value
|
|
135
153
|
except httpx.LocalProtocolError:
|
|
154
|
+
self.logger.error("Local protocol error during SSE subscription.")
|
|
136
155
|
raise TONAPIUnauthorizedError
|
|
137
156
|
except httpx.HTTPStatusError as e:
|
|
157
|
+
self.logger.error(f"HTTP status error during SSE subscription: {e}")
|
|
138
158
|
raise TONAPISSEError(e)
|
|
139
159
|
|
|
140
160
|
async def _subscribe_websocket(
|
|
@@ -155,6 +175,7 @@ class AsyncTonapiClient:
|
|
|
155
175
|
"method": method,
|
|
156
176
|
"params": params,
|
|
157
177
|
}
|
|
178
|
+
self.logger.debug("Subscribing to WebSocket with payload: {payload}")
|
|
158
179
|
async with websockets.connect(self.websocket_url) as websocket:
|
|
159
180
|
try:
|
|
160
181
|
await websocket.send(json.dumps(payload))
|
|
@@ -163,9 +184,11 @@ class AsyncTonapiClient:
|
|
|
163
184
|
message_json = json.loads(message)
|
|
164
185
|
if "params" in message_json:
|
|
165
186
|
value = message_json["params"]
|
|
187
|
+
self.logger.debug(f"Received WebSocket message: {value}")
|
|
166
188
|
yield value
|
|
167
|
-
except websockets.exceptions.ConnectionClosed:
|
|
168
|
-
|
|
189
|
+
except websockets.exceptions.ConnectionClosed as e:
|
|
190
|
+
self.logger.error(f"WebSocket connection closed unexpectedly: {e}")
|
|
191
|
+
raise TONAPIError(e)
|
|
169
192
|
|
|
170
193
|
async def _request(
|
|
171
194
|
self,
|
|
@@ -188,14 +211,33 @@ class AsyncTonapiClient:
|
|
|
188
211
|
url = self.base_url + path
|
|
189
212
|
self.headers.update(headers or {})
|
|
190
213
|
timeout = httpx.Timeout(timeout=self.timeout)
|
|
214
|
+
|
|
215
|
+
self.logger.debug(f"Request {method}: {URL(url).copy_merge_params(QueryParams(params))}")
|
|
216
|
+
self.logger.debug(f"Request headers: {self.headers}")
|
|
217
|
+
if params:
|
|
218
|
+
self.logger.debug(f"Request params: {params}")
|
|
219
|
+
if body:
|
|
220
|
+
self.logger.debug(f"Request body: {body}")
|
|
191
221
|
try:
|
|
192
222
|
async with httpx.AsyncClient(headers=self.headers, timeout=timeout) as session:
|
|
193
|
-
session
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
223
|
+
response = await session.request(
|
|
224
|
+
method=method,
|
|
225
|
+
url=url,
|
|
226
|
+
params=params or {},
|
|
227
|
+
json=body or {},
|
|
228
|
+
)
|
|
229
|
+
response_content = await self.__process_response(response)
|
|
230
|
+
self.logger.debug(f"Response received - Status code: {response.status_code}")
|
|
231
|
+
self.logger.debug(f"Response headers: {response.headers}")
|
|
232
|
+
self.logger.debug(f"Response content: {response_content}")
|
|
233
|
+
return response_content
|
|
234
|
+
|
|
197
235
|
except httpx.LocalProtocolError:
|
|
236
|
+
self.logger.error("Local protocol error occurred during request.")
|
|
198
237
|
raise TONAPIUnauthorizedError
|
|
238
|
+
except httpx.HTTPStatusError as e:
|
|
239
|
+
self.logger.error(f"HTTP status error during request: {e}")
|
|
240
|
+
raise TONAPIError(e)
|
|
199
241
|
|
|
200
242
|
async def _request_retries(
|
|
201
243
|
self,
|
|
@@ -225,12 +267,10 @@ class AsyncTonapiClient:
|
|
|
225
267
|
body=body,
|
|
226
268
|
)
|
|
227
269
|
except TONAPITooManyRequestsError:
|
|
228
|
-
|
|
229
|
-
f"Rate limit exceeded. "
|
|
230
|
-
f"Retrying {i + 1}/{self.max_retries} is in progress."
|
|
231
|
-
)
|
|
270
|
+
self.logger.warning(f"Rate limit exceeded. Retrying {i + 1}/{self.max_retries} in 1 second.")
|
|
232
271
|
await asyncio.sleep(1)
|
|
233
272
|
|
|
273
|
+
self.logger.error("Max retries exceeded while making request")
|
|
234
274
|
raise TONAPITooManyRequestsError
|
|
235
275
|
|
|
236
276
|
async def _get(
|
|
@@ -248,7 +288,7 @@ class AsyncTonapiClient:
|
|
|
248
288
|
:return: The response content as a dictionary.
|
|
249
289
|
"""
|
|
250
290
|
request = self._request
|
|
251
|
-
if self.max_retries:
|
|
291
|
+
if self.max_retries > 0:
|
|
252
292
|
request = self._request_retries
|
|
253
293
|
return await request("GET", method, headers, params=params)
|
|
254
294
|
|
|
@@ -268,6 +308,6 @@ class AsyncTonapiClient:
|
|
|
268
308
|
:return: The response content as a dictionary.
|
|
269
309
|
"""
|
|
270
310
|
request = self._request
|
|
271
|
-
if self.max_retries:
|
|
311
|
+
if self.max_retries > 0:
|
|
272
312
|
request = self._request_retries
|
|
273
313
|
return await request("POST", method, headers, params=params, body=body)
|
|
@@ -3,6 +3,7 @@ from .blockchain import BlockchainMethod
|
|
|
3
3
|
from .dns import DnsMethod
|
|
4
4
|
from .emulate import EmulateMethod
|
|
5
5
|
from .events import EventsMethod
|
|
6
|
+
from .gasless import GaslessMethod
|
|
6
7
|
from .inscriptions import InscriptionsMethod
|
|
7
8
|
from .jettons import JettonsMethod
|
|
8
9
|
from .liteserver import LiteserverMethod
|
|
@@ -13,6 +14,7 @@ from .staking import StakingMethod
|
|
|
13
14
|
from .storage import StorageMethod
|
|
14
15
|
from .tonconnect import TonconnectMethod
|
|
15
16
|
from .traces import TracesMethod
|
|
17
|
+
from .utilites import UtilitiesMethod
|
|
16
18
|
from .wallet import WalletMethod
|
|
17
19
|
from .websocket import WebSocketMethod
|
|
18
20
|
|
|
@@ -22,6 +24,7 @@ __all__ = [
|
|
|
22
24
|
"DnsMethod",
|
|
23
25
|
"EmulateMethod",
|
|
24
26
|
"EventsMethod",
|
|
27
|
+
"GaslessMethod",
|
|
25
28
|
"InscriptionsMethod",
|
|
26
29
|
"JettonsMethod",
|
|
27
30
|
"LiteserverMethod",
|
|
@@ -32,6 +35,7 @@ __all__ = [
|
|
|
32
35
|
"StorageMethod",
|
|
33
36
|
"TonconnectMethod",
|
|
34
37
|
"TracesMethod",
|
|
38
|
+
"UtilitiesMethod",
|
|
35
39
|
"WalletMethod",
|
|
36
40
|
"WebSocketMethod",
|
|
37
41
|
]
|