pytonapi 0.4.0__tar.gz → 0.4.2__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.4.0 → pytonapi-0.4.2}/PKG-INFO +1 -1
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/__init__.py +4 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/client.py +19 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/__init__.py +2 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/accounts.py +25 -4
- pytonapi-0.4.2/pytonapi/async_tonapi/methods/webhooks.py +81 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/rates.py +1 -1
- pytonapi-0.4.2/pytonapi/schema/webhooks.py +33 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/__init__.py +4 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/client.py +19 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/__init__.py +2 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/accounts.py +25 -4
- pytonapi-0.4.2/pytonapi/tonapi/methods/webhooks.py +81 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi.egg-info/PKG-INFO +1 -1
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi.egg-info/SOURCES.txt +3 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/setup.py +1 -1
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/__init__.py +1 -1
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_accounts_methods.py +4 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_jettons_methods.py +1 -1
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_nft_methods.py +1 -2
- pytonapi-0.4.2/tests/async_tonapi/test_sse_methods.py +25 -0
- pytonapi-0.4.2/tests/async_tonapi/test_websocket_methods.py +22 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/__init__.py +1 -1
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_accounts_methods.py +4 -0
- pytonapi-0.4.0/tests/async_tonapi/test_sse_methods.py +0 -25
- pytonapi-0.4.0/tests/async_tonapi/test_websocket_methods.py +0 -22
- {pytonapi-0.4.0 → pytonapi-0.4.2}/LICENSE +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/README.md +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/__init__.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/blockchain.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/dns.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/emulate.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/events.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/gasless.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/inscriptions.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/jettons.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/liteserver.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/multisig.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/nft.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/rates.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/sse.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/staking.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/storage.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/tonconnect.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/traces.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/utilites.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/wallet.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/websocket.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/exceptions.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/logger_config.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/py.typed +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/__init__.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/_address.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/_balance.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/accounts.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/blockchain.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/dns.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/domains.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/events.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/gasless.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/inscriptions.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/jettons.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/liteserver.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/multisig.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/nft.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/staking.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/storage.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/tonconnect.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/traces.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/utilites.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/blockchain.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/dns.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/emulate.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/events.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/gasless.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/inscriptions.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/jettons.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/liteserver.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/multisig.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/nft.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/rates.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/sse.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/staking.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/storage.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/tonconnect.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/traces.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/utilites.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/wallet.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/utils.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi.egg-info/dependency_links.txt +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi.egg-info/requires.txt +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi.egg-info/top_level.txt +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/setup.cfg +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_blockchain_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_dns_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_events_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_inscriptions_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_liteserver_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_rates_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_staking_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_storage_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_tonconnect_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_traces_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_utilities_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_blockchain_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_dns_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_events_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_inscriptions_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_jettons_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_liteserver_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_nft_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_rates_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_sse_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_staking_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_storage_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_tonconnect_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_traces_methods.py +0 -0
- {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_utilities_methods.py +0 -0
|
@@ -123,6 +123,10 @@ class AsyncTonapi(AsyncTonapiClientBase):
|
|
|
123
123
|
def wallet(self) -> methods.WalletMethod:
|
|
124
124
|
return methods.WalletMethod(**self.__dict__)
|
|
125
125
|
|
|
126
|
+
@property
|
|
127
|
+
def webhooks(self) -> methods.WebhooksMethod:
|
|
128
|
+
return methods.WebhooksMethod(**self.__dict__)
|
|
129
|
+
|
|
126
130
|
@property
|
|
127
131
|
def websocket(self) -> methods.WebSocketMethod:
|
|
128
132
|
return methods.WebSocketMethod(**self.__dict__)
|
|
@@ -311,3 +311,22 @@ class AsyncTonapiClientBase:
|
|
|
311
311
|
if self.max_retries > 0:
|
|
312
312
|
request = self._request_retries
|
|
313
313
|
return await request("POST", method, headers, params=params, body=body)
|
|
314
|
+
|
|
315
|
+
async def _delete(
|
|
316
|
+
self,
|
|
317
|
+
method: str,
|
|
318
|
+
params: Optional[Dict[str, Any]] = None,
|
|
319
|
+
headers: Optional[Dict[str, Any]] = None,
|
|
320
|
+
) -> Dict[str, Any]:
|
|
321
|
+
"""
|
|
322
|
+
Make a DELETE request.
|
|
323
|
+
|
|
324
|
+
:param method: The API method.
|
|
325
|
+
:param params: Optional query parameters.
|
|
326
|
+
:param headers: Optional headers to include in the request.
|
|
327
|
+
:return: The response content as a dictionary.
|
|
328
|
+
"""
|
|
329
|
+
request = self._request
|
|
330
|
+
if self.max_retries > 0:
|
|
331
|
+
request = self._request_retries
|
|
332
|
+
return await request("DELETE", method, headers, params=params)
|
|
@@ -17,6 +17,7 @@ from .tonconnect import TonconnectMethod
|
|
|
17
17
|
from .traces import TracesMethod
|
|
18
18
|
from .utilites import UtilitiesMethod
|
|
19
19
|
from .wallet import WalletMethod
|
|
20
|
+
from .webhooks import WebhooksMethod
|
|
20
21
|
from .websocket import WebSocketMethod
|
|
21
22
|
|
|
22
23
|
__all__ = [
|
|
@@ -39,5 +40,6 @@ __all__ = [
|
|
|
39
40
|
"TracesMethod",
|
|
40
41
|
"UtilitiesMethod",
|
|
41
42
|
"WalletMethod",
|
|
43
|
+
"WebhooksMethod",
|
|
42
44
|
"WebSocketMethod",
|
|
43
45
|
]
|
|
@@ -57,28 +57,49 @@ class AccountsMethod(AsyncTonapiClientBase):
|
|
|
57
57
|
|
|
58
58
|
return DomainNames(**response)
|
|
59
59
|
|
|
60
|
-
async def get_jettons_balances(
|
|
60
|
+
async def get_jettons_balances(
|
|
61
|
+
self,
|
|
62
|
+
account_id: str,
|
|
63
|
+
currencies: Optional[List[str]] = None,
|
|
64
|
+
supported_extensions: Optional[List[str]] = None,
|
|
65
|
+
) -> JettonsBalances:
|
|
61
66
|
"""
|
|
62
67
|
Get all Jettons balances by owner address.
|
|
63
68
|
|
|
64
69
|
:param account_id: account ID
|
|
70
|
+
:param currencies: accept ton and all possible fiat currencies, separated by commas
|
|
71
|
+
:param supported_extensions: comma separated list supported extensions
|
|
65
72
|
:return: :class:`JettonsBalances`
|
|
66
73
|
"""
|
|
67
74
|
method = f"v2/accounts/{account_id}/jettons"
|
|
68
|
-
|
|
75
|
+
params = {"supported_extensions": ",".join(supported_extensions)} if supported_extensions else {}
|
|
76
|
+
if currencies:
|
|
77
|
+
params["currencies"] = ",".join(currencies)
|
|
78
|
+
response = await self._get(method=method, params=params)
|
|
69
79
|
|
|
70
80
|
return JettonsBalances(**response)
|
|
71
81
|
|
|
72
|
-
async def get_jetton_balance(
|
|
82
|
+
async def get_jetton_balance(
|
|
83
|
+
self,
|
|
84
|
+
account_id: str,
|
|
85
|
+
jetton_id: str,
|
|
86
|
+
currencies: Optional[List[str]] = None,
|
|
87
|
+
supported_extensions: Optional[List[str]] = None,
|
|
88
|
+
) -> JettonBalance:
|
|
73
89
|
"""
|
|
74
90
|
Get Jetton balance by owner address
|
|
75
91
|
|
|
76
92
|
:param account_id: account ID
|
|
77
93
|
:param jetton_id: jetton ID
|
|
94
|
+
:param currencies: accept ton and all possible fiat currencies, separated by commas
|
|
95
|
+
:param supported_extensions: comma separated list supported extensions
|
|
78
96
|
:return: :class:`JettonBalance`
|
|
79
97
|
"""
|
|
80
98
|
method = f"v2/accounts/{account_id}/jettons/{jetton_id}"
|
|
81
|
-
|
|
99
|
+
params = {"supported_extensions": ",".join(supported_extensions)} if supported_extensions else {}
|
|
100
|
+
if currencies:
|
|
101
|
+
params["currencies"] = ",".join(currencies)
|
|
102
|
+
response = await self._get(method=method, params=params)
|
|
82
103
|
|
|
83
104
|
return JettonBalance(**response)
|
|
84
105
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from pytonapi.async_tonapi.client import AsyncTonapiClientBase
|
|
4
|
+
from pytonapi.schema.webhooks import WebhookCreate, WebhookList, AccountSubscriptions
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class WebhooksMethod(AsyncTonapiClientBase):
|
|
8
|
+
|
|
9
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
10
|
+
super().__init__(*args, **kwargs)
|
|
11
|
+
self.base_url = "https://rt.tonapi.io/"
|
|
12
|
+
|
|
13
|
+
async def create_webhook(self, endpoint: str) -> WebhookCreate:
|
|
14
|
+
"""
|
|
15
|
+
Create a new webhook and return its ID.
|
|
16
|
+
|
|
17
|
+
:param endpoint: The webhook endpoint URL to receive transaction events.
|
|
18
|
+
:return: An object containing the ID of the created webhook.
|
|
19
|
+
:rtype: WebhookCreate
|
|
20
|
+
"""
|
|
21
|
+
method = "webhooks"
|
|
22
|
+
body = {"endpoint": endpoint}
|
|
23
|
+
response = await self._post(method=method, body=body)
|
|
24
|
+
return WebhookCreate(**response)
|
|
25
|
+
|
|
26
|
+
async def list_webhooks(self) -> WebhookList:
|
|
27
|
+
"""
|
|
28
|
+
Retrieve a list of all available webhooks.
|
|
29
|
+
|
|
30
|
+
:return: A list containing all webhooks with their IDs and endpoints.
|
|
31
|
+
:rtype: WebhookList
|
|
32
|
+
"""
|
|
33
|
+
method = "webhooks"
|
|
34
|
+
response = await self._get(method=method)
|
|
35
|
+
return WebhookList(**response)
|
|
36
|
+
|
|
37
|
+
async def delete_webhook(self, webhook_id: int) -> None:
|
|
38
|
+
"""
|
|
39
|
+
Delete a webhook and all its subscriptions.
|
|
40
|
+
|
|
41
|
+
:param webhook_id: The ID of the webhook to delete.
|
|
42
|
+
"""
|
|
43
|
+
method = f"webhooks/{webhook_id}"
|
|
44
|
+
await self._delete(method=method)
|
|
45
|
+
|
|
46
|
+
async def subscribe_to_account(self, webhook_id: int, accounts: List[str]) -> None:
|
|
47
|
+
"""
|
|
48
|
+
Subscribe a webhook to specific account transactions.
|
|
49
|
+
|
|
50
|
+
:param webhook_id: The ID of the webhook to subscribe.
|
|
51
|
+
:param accounts: A list of account IDs to subscribe to.
|
|
52
|
+
"""
|
|
53
|
+
method = f"webhooks/{webhook_id}/account-tx/subscribe"
|
|
54
|
+
body = {"accounts": [{"account_id": account} for account in accounts]}
|
|
55
|
+
await self._post(method=method, body=body)
|
|
56
|
+
|
|
57
|
+
async def unsubscribe_from_account(self, webhook_id: int, accounts: List[str]) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Unsubscribe a webhook from specific account transactions.
|
|
60
|
+
|
|
61
|
+
:param webhook_id: The ID of the webhook to unsubscribe.
|
|
62
|
+
:param accounts: A list of account IDs to unsubscribe from.
|
|
63
|
+
"""
|
|
64
|
+
method = f"webhooks/{webhook_id}/account-tx/unsubscribe"
|
|
65
|
+
body = {"accounts": accounts}
|
|
66
|
+
await self._post(method=method, body=body)
|
|
67
|
+
|
|
68
|
+
async def get_subscriptions(self, webhook_id: int, offset: int = 0, limit: int = 10) -> AccountSubscriptions:
|
|
69
|
+
"""
|
|
70
|
+
Retrieve the list of subscriptions for a given webhook.
|
|
71
|
+
|
|
72
|
+
:param webhook_id: The ID of the webhook.
|
|
73
|
+
:param offset: The offset for pagination. Default is 0.
|
|
74
|
+
:param limit: The maximum number of subscriptions to return. Default is 10.
|
|
75
|
+
:return: A list of account transaction subscriptions with details.
|
|
76
|
+
:rtype: AccountSubscriptions
|
|
77
|
+
"""
|
|
78
|
+
method = f"webhooks/{webhook_id}/account-tx/subscriptions"
|
|
79
|
+
params = {"offset": offset, "limit": limit}
|
|
80
|
+
response = await self._get(method=method, params=params)
|
|
81
|
+
return AccountSubscriptions(**response)
|
|
@@ -12,7 +12,7 @@ class ChartRates(BaseModel):
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class TokenRates(BaseModel):
|
|
15
|
-
prices: Optional[Dict[str,
|
|
15
|
+
prices: Optional[Dict[str, Union[float, int]]] = None
|
|
16
16
|
diff_24h: Optional[Dict[str, str]] = None
|
|
17
17
|
diff_7d: Optional[Dict[str, str]] = None
|
|
18
18
|
diff_30d: Optional[Dict[str, str]] = None
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class WebhookCreate(BaseModel):
|
|
7
|
+
webhook_id: int
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Webhook(BaseModel):
|
|
11
|
+
id: int
|
|
12
|
+
endpoint: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class WebhookList(BaseModel):
|
|
16
|
+
webhooks: List[Webhook]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AccountSubscription(BaseModel):
|
|
20
|
+
accounts: List[dict]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AccountTxSubscription(BaseModel):
|
|
25
|
+
account_id: str
|
|
26
|
+
last_delivered_lt: int
|
|
27
|
+
failed_at: Optional[str] = None
|
|
28
|
+
failed_lt: Optional[int] = None
|
|
29
|
+
failed_attempts: Optional[int] = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AccountSubscriptions(BaseModel):
|
|
33
|
+
account_tx_subscriptions: List[AccountTxSubscription]
|
|
@@ -266,3 +266,22 @@ class TonapiClientBase:
|
|
|
266
266
|
if self.max_retries > 0:
|
|
267
267
|
request = self._request_retries
|
|
268
268
|
return request("POST", method, headers, params=params, body=body)
|
|
269
|
+
|
|
270
|
+
def _delete(
|
|
271
|
+
self,
|
|
272
|
+
method: str,
|
|
273
|
+
params: Optional[Dict[str, Any]] = None,
|
|
274
|
+
headers: Optional[Dict[str, Any]] = None,
|
|
275
|
+
) -> Dict[str, Any]:
|
|
276
|
+
"""
|
|
277
|
+
Make a DELETE request.
|
|
278
|
+
|
|
279
|
+
:param method: The API method.
|
|
280
|
+
:param params: Optional query parameters.
|
|
281
|
+
:param headers: Optional headers to include in the request.
|
|
282
|
+
:return: The response content as a dictionary.
|
|
283
|
+
"""
|
|
284
|
+
request = self._request
|
|
285
|
+
if self.max_retries > 0:
|
|
286
|
+
request = self._request_retries
|
|
287
|
+
return request("DELETE", method, headers, params=params)
|
|
@@ -17,6 +17,7 @@ from .tonconnect import TonconnectMethod
|
|
|
17
17
|
from .traces import TracesMethod
|
|
18
18
|
from .utilites import UtilitiesMethod
|
|
19
19
|
from .wallet import WalletMethod
|
|
20
|
+
from .webhooks import WebhooksMethod
|
|
20
21
|
|
|
21
22
|
__all__ = [
|
|
22
23
|
"AccountsMethod",
|
|
@@ -38,4 +39,5 @@ __all__ = [
|
|
|
38
39
|
"TracesMethod",
|
|
39
40
|
"UtilitiesMethod",
|
|
40
41
|
"WalletMethod",
|
|
42
|
+
"WebhooksMethod",
|
|
41
43
|
]
|
|
@@ -57,28 +57,49 @@ class AccountsMethod(TonapiClientBase):
|
|
|
57
57
|
|
|
58
58
|
return DomainNames(**response)
|
|
59
59
|
|
|
60
|
-
def get_jettons_balances(
|
|
60
|
+
def get_jettons_balances(
|
|
61
|
+
self,
|
|
62
|
+
account_id: str,
|
|
63
|
+
currencies: Optional[List[str]] = None,
|
|
64
|
+
supported_extensions: Optional[List[str]] = None,
|
|
65
|
+
) -> JettonsBalances:
|
|
61
66
|
"""
|
|
62
67
|
Get all Jettons balances by owner address.
|
|
63
68
|
|
|
64
69
|
:param account_id: account ID
|
|
70
|
+
:param currencies: accept ton and all possible fiat currencies, separated by commas
|
|
71
|
+
:param supported_extensions: comma separated list supported extensions
|
|
65
72
|
:return: :class:`JettonsBalances`
|
|
66
73
|
"""
|
|
67
74
|
method = f"v2/accounts/{account_id}/jettons"
|
|
68
|
-
|
|
75
|
+
params = {"supported_extensions": ",".join(supported_extensions)} if supported_extensions else {}
|
|
76
|
+
if currencies:
|
|
77
|
+
params["currencies"] = ",".join(currencies)
|
|
78
|
+
response = self._get(method=method, params=params)
|
|
69
79
|
|
|
70
80
|
return JettonsBalances(**response)
|
|
71
81
|
|
|
72
|
-
def get_jetton_balance(
|
|
82
|
+
def get_jetton_balance(
|
|
83
|
+
self,
|
|
84
|
+
account_id: str,
|
|
85
|
+
jetton_id: str,
|
|
86
|
+
currencies: Optional[List[str]] = None,
|
|
87
|
+
supported_extensions: Optional[List[str]] = None,
|
|
88
|
+
) -> JettonBalance:
|
|
73
89
|
"""
|
|
74
90
|
Get Jetton balance by owner address
|
|
75
91
|
|
|
76
92
|
:param account_id: account ID
|
|
77
93
|
:param jetton_id: jetton ID
|
|
94
|
+
:param currencies: accept ton and all possible fiat currencies, separated by commas
|
|
95
|
+
:param supported_extensions: comma separated list supported extensions
|
|
78
96
|
:return: :class:`JettonBalance`
|
|
79
97
|
"""
|
|
80
98
|
method = f"v2/accounts/{account_id}/jettons/{jetton_id}"
|
|
81
|
-
|
|
99
|
+
params = {"supported_extensions": ",".join(supported_extensions)} if supported_extensions else {}
|
|
100
|
+
if currencies:
|
|
101
|
+
params["currencies"] = ",".join(currencies)
|
|
102
|
+
response = self._get(method=method, params=params)
|
|
82
103
|
|
|
83
104
|
return JettonBalance(**response)
|
|
84
105
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from pytonapi.schema.webhooks import WebhookCreate, WebhookList, AccountSubscriptions
|
|
4
|
+
from pytonapi.tonapi.client import TonapiClientBase
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class WebhooksMethod(TonapiClientBase):
|
|
8
|
+
|
|
9
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
10
|
+
super().__init__(*args, **kwargs)
|
|
11
|
+
self.base_url = "https://rt.tonapi.io/"
|
|
12
|
+
|
|
13
|
+
def create_webhook(self, endpoint: str) -> WebhookCreate:
|
|
14
|
+
"""
|
|
15
|
+
Create a new webhook and return its ID.
|
|
16
|
+
|
|
17
|
+
:param endpoint: The webhook endpoint URL to receive transaction events.
|
|
18
|
+
:return: An object containing the ID of the created webhook.
|
|
19
|
+
:rtype: WebhookCreate
|
|
20
|
+
"""
|
|
21
|
+
method = "webhooks"
|
|
22
|
+
body = {"endpoint": endpoint}
|
|
23
|
+
response = self._post(method=method, body=body)
|
|
24
|
+
return WebhookCreate(**response)
|
|
25
|
+
|
|
26
|
+
def list_webhooks(self) -> WebhookList:
|
|
27
|
+
"""
|
|
28
|
+
Retrieve a list of all available webhooks.
|
|
29
|
+
|
|
30
|
+
:return: A list containing all webhooks with their IDs and endpoints.
|
|
31
|
+
:rtype: WebhookList
|
|
32
|
+
"""
|
|
33
|
+
method = "webhooks"
|
|
34
|
+
response = self._get(method=method)
|
|
35
|
+
return WebhookList(**response)
|
|
36
|
+
|
|
37
|
+
def delete_webhook(self, webhook_id: int) -> None:
|
|
38
|
+
"""
|
|
39
|
+
Delete a webhook and all its subscriptions.
|
|
40
|
+
|
|
41
|
+
:param webhook_id: The ID of the webhook to delete.
|
|
42
|
+
"""
|
|
43
|
+
method = f"webhooks/{webhook_id}"
|
|
44
|
+
self._delete(method=method)
|
|
45
|
+
|
|
46
|
+
def subscribe_to_account(self, webhook_id: int, accounts: List[str]) -> None:
|
|
47
|
+
"""
|
|
48
|
+
Subscribe a webhook to specific account transactions.
|
|
49
|
+
|
|
50
|
+
:param webhook_id: The ID of the webhook to subscribe.
|
|
51
|
+
:param accounts: A list of account IDs to subscribe to.
|
|
52
|
+
"""
|
|
53
|
+
method = f"webhooks/{webhook_id}/account-tx/subscribe"
|
|
54
|
+
body = {"accounts": [{"account_id": account} for account in accounts]}
|
|
55
|
+
self._post(method=method, body=body)
|
|
56
|
+
|
|
57
|
+
def unsubscribe_from_account(self, webhook_id: int, accounts: List[str]) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Unsubscribe a webhook from specific account transactions.
|
|
60
|
+
|
|
61
|
+
:param webhook_id: The ID of the webhook to unsubscribe.
|
|
62
|
+
:param accounts: A list of account IDs to unsubscribe from.
|
|
63
|
+
"""
|
|
64
|
+
method = f"webhooks/{webhook_id}/account-tx/unsubscribe"
|
|
65
|
+
body = {"accounts": accounts}
|
|
66
|
+
self._post(method=method, body=body)
|
|
67
|
+
|
|
68
|
+
def get_subscriptions(self, webhook_id: int, offset: int = 0, limit: int = 10) -> AccountSubscriptions:
|
|
69
|
+
"""
|
|
70
|
+
Retrieve the list of subscriptions for a given webhook.
|
|
71
|
+
|
|
72
|
+
:param webhook_id: The ID of the webhook.
|
|
73
|
+
:param offset: The offset for pagination. Default is 0.
|
|
74
|
+
:param limit: The maximum number of subscriptions to return. Default is 10.
|
|
75
|
+
:return: A list of account transaction subscriptions with details.
|
|
76
|
+
:rtype: AccountSubscriptions
|
|
77
|
+
"""
|
|
78
|
+
method = f"webhooks/{webhook_id}/account-tx/subscriptions"
|
|
79
|
+
params = {"offset": offset, "limit": limit}
|
|
80
|
+
response = self._get(method=method, params=params)
|
|
81
|
+
return AccountSubscriptions(**response)
|
|
@@ -33,6 +33,7 @@ pytonapi/async_tonapi/methods/tonconnect.py
|
|
|
33
33
|
pytonapi/async_tonapi/methods/traces.py
|
|
34
34
|
pytonapi/async_tonapi/methods/utilites.py
|
|
35
35
|
pytonapi/async_tonapi/methods/wallet.py
|
|
36
|
+
pytonapi/async_tonapi/methods/webhooks.py
|
|
36
37
|
pytonapi/async_tonapi/methods/websocket.py
|
|
37
38
|
pytonapi/schema/__init__.py
|
|
38
39
|
pytonapi/schema/_address.py
|
|
@@ -54,6 +55,7 @@ pytonapi/schema/storage.py
|
|
|
54
55
|
pytonapi/schema/tonconnect.py
|
|
55
56
|
pytonapi/schema/traces.py
|
|
56
57
|
pytonapi/schema/utilites.py
|
|
58
|
+
pytonapi/schema/webhooks.py
|
|
57
59
|
pytonapi/tonapi/__init__.py
|
|
58
60
|
pytonapi/tonapi/client.py
|
|
59
61
|
pytonapi/tonapi/methods/__init__.py
|
|
@@ -76,6 +78,7 @@ pytonapi/tonapi/methods/tonconnect.py
|
|
|
76
78
|
pytonapi/tonapi/methods/traces.py
|
|
77
79
|
pytonapi/tonapi/methods/utilites.py
|
|
78
80
|
pytonapi/tonapi/methods/wallet.py
|
|
81
|
+
pytonapi/tonapi/methods/webhooks.py
|
|
79
82
|
tests/async_tonapi/__init__.py
|
|
80
83
|
tests/async_tonapi/test_accounts_methods.py
|
|
81
84
|
tests/async_tonapi/test_blockchain_methods.py
|
|
@@ -9,6 +9,10 @@ JETTON_ID = "EQD0vdSA_NedR9uvbgN9EikRX-suesDxGeFg69XQMavfLqIw" # noqa
|
|
|
9
9
|
|
|
10
10
|
class TestAccountMethod(TestAsyncTonapi):
|
|
11
11
|
|
|
12
|
+
async def test_parse_address(self):
|
|
13
|
+
response = await self.tonapi.accounts.parse_address(ACCOUNT_ID)
|
|
14
|
+
self.assertIsInstance(response, schema.accounts.AddressForm)
|
|
15
|
+
|
|
12
16
|
async def test_get_info(self):
|
|
13
17
|
response = await self.tonapi.accounts.get_info(ACCOUNT_ID)
|
|
14
18
|
self.assertIsInstance(response, schema.accounts.Account)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from pytonapi import schema
|
|
2
2
|
from tests.async_tonapi import TestAsyncTonapi
|
|
3
3
|
|
|
4
|
-
ACCOUNT_ID = "
|
|
4
|
+
ACCOUNT_ID = "EQBCFwW8uFUh-amdRmNY9NyeDEaeDYXd9ggJGsicpqVcHq7B" # noqa
|
|
5
5
|
EVENT_ID = "68656e74d18b10309e41e057191abcfc42f973c82bc84326985cdbf7bf89b126"
|
|
6
6
|
|
|
7
7
|
|
|
@@ -25,8 +25,7 @@ class TestNftMethod(TestAsyncTonapi):
|
|
|
25
25
|
self.assertIsInstance(response, schema.nft.NftItems)
|
|
26
26
|
|
|
27
27
|
async def test_get_all_items_by_collection_address(self):
|
|
28
|
-
response = await self.tonapi.nft.get_all_items_by_collection_address(
|
|
29
|
-
print(len(response.nft_items))
|
|
28
|
+
response = await self.tonapi.nft.get_all_items_by_collection_address(ACCOUNT_ID_COLLECTION)
|
|
30
29
|
self.assertIsInstance(response, schema.nft.NftItems)
|
|
31
30
|
|
|
32
31
|
async def test_get_item_by_address(self):
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from pprint import pprint
|
|
2
|
+
|
|
3
|
+
from tests.async_tonapi import TestAsyncTonapi
|
|
4
|
+
|
|
5
|
+
ACCOUNT_ID = "EQChB2eMoFG4ThuEsZ6ehlBPKJXOjNxlR5B7qKZNGIv256Da"
|
|
6
|
+
ACCOUNTS_IDS = ["ALL"]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def handler(event) -> None:
|
|
10
|
+
pprint(event)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestSSEMethod(TestAsyncTonapi):
|
|
14
|
+
|
|
15
|
+
async def test_subscribe_to_transactions(self):
|
|
16
|
+
await self.tonapi.sse.subscribe_to_transactions(handler, ACCOUNTS_IDS)
|
|
17
|
+
|
|
18
|
+
async def test_subscribe_to_traces(self):
|
|
19
|
+
await self.tonapi.sse.subscribe_to_traces(handler, ACCOUNTS_IDS)
|
|
20
|
+
|
|
21
|
+
async def test_subscribe_to_mempool(self):
|
|
22
|
+
await self.tonapi.sse.subscribe_to_mempool(handler, [ACCOUNT_ID])
|
|
23
|
+
|
|
24
|
+
async def test_subscribe_to_blocks(self):
|
|
25
|
+
await self.tonapi.sse.subscribe_to_blocks(handler)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from pprint import pprint
|
|
2
|
+
|
|
3
|
+
from tests.async_tonapi import TestAsyncTonapi
|
|
4
|
+
|
|
5
|
+
ACCOUNT_ID = "Ef8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM0vF"
|
|
6
|
+
ACCOUNTS_IDS = ["UQCFJEP4WZ_mpdo0_kMEmsTgvrMHG7K_tWY16pQhKHwoOtFz"]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def handler(event) -> None:
|
|
10
|
+
pprint(event)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestSSEMethod(TestAsyncTonapi):
|
|
14
|
+
|
|
15
|
+
async def test_subscribe_to_transactions(self):
|
|
16
|
+
await self.tonapi.websocket.subscribe_to_transactions(handler, ACCOUNTS_IDS)
|
|
17
|
+
|
|
18
|
+
async def test_subscribe_to_traces(self):
|
|
19
|
+
await self.tonapi.websocket.subscribe_to_traces(handler, ACCOUNTS_IDS)
|
|
20
|
+
|
|
21
|
+
async def test_subscribe_to_mempool(self):
|
|
22
|
+
await self.tonapi.websocket.subscribe_to_mempool(handler, [ACCOUNT_ID])
|
|
@@ -25,6 +25,10 @@ class TestAccountMethod(TestTonapi):
|
|
|
25
25
|
response = self.tonapi.accounts.get_jettons_balances(ACCOUNT_ID)
|
|
26
26
|
self.assertIsInstance(response, schema.jettons.JettonsBalances)
|
|
27
27
|
|
|
28
|
+
def test_get_jettons_with_currencies(self):
|
|
29
|
+
response = self.tonapi.accounts.get_jettons_balances(ACCOUNT_ID, currencies=["ton"])
|
|
30
|
+
self.assertIsInstance(response, schema.jettons.JettonsBalances)
|
|
31
|
+
|
|
28
32
|
def test_get_jetton(self):
|
|
29
33
|
response = self.tonapi.accounts.get_jetton_balance(ACCOUNT_ID, JETTON_ID)
|
|
30
34
|
self.assertIsInstance(response, schema.jettons.JettonBalance)
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
from pprint import pprint
|
|
2
|
-
|
|
3
|
-
from tests.async_tonapi import TestAsyncTonapi
|
|
4
|
-
|
|
5
|
-
ACCOUNT_ID = "EQChB2eMoFG4ThuEsZ6ehlBPKJXOjNxlR5B7qKZNGIv256Da"
|
|
6
|
-
ACCOUNTS_IDS = ["ALL"]
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
async def handler(event) -> None:
|
|
10
|
-
pprint(event)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TestSSEMethod(TestAsyncTonapi):
|
|
14
|
-
pass
|
|
15
|
-
# async def test_subscribe_to_transactions(self):
|
|
16
|
-
# await self.tonapi.sse.subscribe_to_transactions(handler, ACCOUNTS_IDS)
|
|
17
|
-
#
|
|
18
|
-
# async def test_subscribe_to_traces(self):
|
|
19
|
-
# await self.tonapi.sse.subscribe_to_traces(handler, ACCOUNTS_IDS)
|
|
20
|
-
#
|
|
21
|
-
# async def test_subscribe_to_mempool(self):
|
|
22
|
-
# await self.tonapi.sse.subscribe_to_mempool(handler, [ACCOUNT_ID])
|
|
23
|
-
#
|
|
24
|
-
# async def test_subscribe_to_blocks(self):
|
|
25
|
-
# await self.tonapi.sse.subscribe_to_blocks(handler)
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from pprint import pprint
|
|
2
|
-
|
|
3
|
-
from tests.async_tonapi import TestAsyncTonapi
|
|
4
|
-
|
|
5
|
-
ACCOUNT_ID = "Ef8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM0vF"
|
|
6
|
-
ACCOUNTS_IDS = ["UQCFJEP4WZ_mpdo0_kMEmsTgvrMHG7K_tWY16pQhKHwoOtFz"]
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
async def handler(event) -> None:
|
|
10
|
-
pprint(event)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TestSSEMethod(TestAsyncTonapi):
|
|
14
|
-
pass
|
|
15
|
-
# async def test_subscribe_to_transactions(self):
|
|
16
|
-
# await self.tonapi.websocket.subscribe_to_transactions(handler, ACCOUNTS_IDS)
|
|
17
|
-
#
|
|
18
|
-
# async def test_subscribe_to_traces(self):
|
|
19
|
-
# await self.tonapi.websocket.subscribe_to_traces(handler, ACCOUNTS_IDS)
|
|
20
|
-
#
|
|
21
|
-
# async def test_subscribe_to_mempool(self):
|
|
22
|
-
# await self.tonapi.websocket.subscribe_to_mempool(handler, [ACCOUNT_ID])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|