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.
Files changed (118) hide show
  1. {pytonapi-0.4.0 → pytonapi-0.4.2}/PKG-INFO +1 -1
  2. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/__init__.py +4 -0
  3. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/client.py +19 -0
  4. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/__init__.py +2 -0
  5. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/accounts.py +25 -4
  6. pytonapi-0.4.2/pytonapi/async_tonapi/methods/webhooks.py +81 -0
  7. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/rates.py +1 -1
  8. pytonapi-0.4.2/pytonapi/schema/webhooks.py +33 -0
  9. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/__init__.py +4 -0
  10. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/client.py +19 -0
  11. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/__init__.py +2 -0
  12. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/accounts.py +25 -4
  13. pytonapi-0.4.2/pytonapi/tonapi/methods/webhooks.py +81 -0
  14. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi.egg-info/PKG-INFO +1 -1
  15. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi.egg-info/SOURCES.txt +3 -0
  16. {pytonapi-0.4.0 → pytonapi-0.4.2}/setup.py +1 -1
  17. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/__init__.py +1 -1
  18. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_accounts_methods.py +4 -0
  19. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_jettons_methods.py +1 -1
  20. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_nft_methods.py +1 -2
  21. pytonapi-0.4.2/tests/async_tonapi/test_sse_methods.py +25 -0
  22. pytonapi-0.4.2/tests/async_tonapi/test_websocket_methods.py +22 -0
  23. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/__init__.py +1 -1
  24. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_accounts_methods.py +4 -0
  25. pytonapi-0.4.0/tests/async_tonapi/test_sse_methods.py +0 -25
  26. pytonapi-0.4.0/tests/async_tonapi/test_websocket_methods.py +0 -22
  27. {pytonapi-0.4.0 → pytonapi-0.4.2}/LICENSE +0 -0
  28. {pytonapi-0.4.0 → pytonapi-0.4.2}/README.md +0 -0
  29. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/__init__.py +0 -0
  30. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/blockchain.py +0 -0
  31. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/dns.py +0 -0
  32. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/emulate.py +0 -0
  33. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/events.py +0 -0
  34. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/gasless.py +0 -0
  35. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/inscriptions.py +0 -0
  36. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/jettons.py +0 -0
  37. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/liteserver.py +0 -0
  38. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/multisig.py +0 -0
  39. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/nft.py +0 -0
  40. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/rates.py +0 -0
  41. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/sse.py +0 -0
  42. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/staking.py +0 -0
  43. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/storage.py +0 -0
  44. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/tonconnect.py +0 -0
  45. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/traces.py +0 -0
  46. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/utilites.py +0 -0
  47. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/wallet.py +0 -0
  48. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/async_tonapi/methods/websocket.py +0 -0
  49. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/exceptions.py +0 -0
  50. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/logger_config.py +0 -0
  51. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/py.typed +0 -0
  52. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/__init__.py +0 -0
  53. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/_address.py +0 -0
  54. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/_balance.py +0 -0
  55. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/accounts.py +0 -0
  56. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/blockchain.py +0 -0
  57. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/dns.py +0 -0
  58. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/domains.py +0 -0
  59. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/events.py +0 -0
  60. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/gasless.py +0 -0
  61. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/inscriptions.py +0 -0
  62. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/jettons.py +0 -0
  63. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/liteserver.py +0 -0
  64. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/multisig.py +0 -0
  65. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/nft.py +0 -0
  66. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/staking.py +0 -0
  67. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/storage.py +0 -0
  68. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/tonconnect.py +0 -0
  69. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/traces.py +0 -0
  70. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/schema/utilites.py +0 -0
  71. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/blockchain.py +0 -0
  72. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/dns.py +0 -0
  73. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/emulate.py +0 -0
  74. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/events.py +0 -0
  75. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/gasless.py +0 -0
  76. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/inscriptions.py +0 -0
  77. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/jettons.py +0 -0
  78. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/liteserver.py +0 -0
  79. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/multisig.py +0 -0
  80. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/nft.py +0 -0
  81. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/rates.py +0 -0
  82. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/sse.py +0 -0
  83. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/staking.py +0 -0
  84. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/storage.py +0 -0
  85. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/tonconnect.py +0 -0
  86. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/traces.py +0 -0
  87. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/utilites.py +0 -0
  88. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/tonapi/methods/wallet.py +0 -0
  89. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi/utils.py +0 -0
  90. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi.egg-info/dependency_links.txt +0 -0
  91. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi.egg-info/requires.txt +0 -0
  92. {pytonapi-0.4.0 → pytonapi-0.4.2}/pytonapi.egg-info/top_level.txt +0 -0
  93. {pytonapi-0.4.0 → pytonapi-0.4.2}/setup.cfg +0 -0
  94. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_blockchain_methods.py +0 -0
  95. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_dns_methods.py +0 -0
  96. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_events_methods.py +0 -0
  97. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_inscriptions_methods.py +0 -0
  98. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_liteserver_methods.py +0 -0
  99. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_rates_methods.py +0 -0
  100. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_staking_methods.py +0 -0
  101. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_storage_methods.py +0 -0
  102. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_tonconnect_methods.py +0 -0
  103. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_traces_methods.py +0 -0
  104. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/async_tonapi/test_utilities_methods.py +0 -0
  105. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_blockchain_methods.py +0 -0
  106. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_dns_methods.py +0 -0
  107. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_events_methods.py +0 -0
  108. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_inscriptions_methods.py +0 -0
  109. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_jettons_methods.py +0 -0
  110. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_liteserver_methods.py +0 -0
  111. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_nft_methods.py +0 -0
  112. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_rates_methods.py +0 -0
  113. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_sse_methods.py +0 -0
  114. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_staking_methods.py +0 -0
  115. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_storage_methods.py +0 -0
  116. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_tonconnect_methods.py +0 -0
  117. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_traces_methods.py +0 -0
  118. {pytonapi-0.4.0 → pytonapi-0.4.2}/tests/tonapi/test_utilities_methods.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytonapi
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Provide access to indexed TON blockchain.
5
5
  Home-page: https://github.com/tonkeeper/pytonapi/
6
6
  Author: nessshon
@@ -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(self, account_id: str) -> JettonsBalances:
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
- response = await self._get(method=method)
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(self, account_id: str, jetton_id: str) -> JettonBalance:
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
- response = await self._get(method=method)
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, str]] = None
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]
@@ -114,3 +114,7 @@ class Tonapi(TonapiClientBase):
114
114
  @property
115
115
  def wallet(self) -> methods.WalletMethod:
116
116
  return methods.WalletMethod(**self.__dict__)
117
+
118
+ @property
119
+ def webhooks(self) -> methods.WebhooksMethod:
120
+ return methods.WebhooksMethod(**self.__dict__)
@@ -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(self, account_id: str) -> JettonsBalances:
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
- response = self._get(method=method)
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(self, account_id: str, jetton_id: str) -> JettonBalance:
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
- response = self._get(method=method)
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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytonapi
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Provide access to indexed TON blockchain.
5
5
  Home-page: https://github.com/tonkeeper/pytonapi/
6
6
  Author: nessshon
@@ -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
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="pytonapi",
8
- version="0.4.0",
8
+ version="0.4.2",
9
9
  author="nessshon",
10
10
  description="Provide access to indexed TON blockchain.",
11
11
  long_description=long_description,
@@ -2,7 +2,7 @@ from unittest import IsolatedAsyncioTestCase
2
2
 
3
3
  from pytonapi import AsyncTonapi
4
4
 
5
- API_KEY = "AE33EX7DNCVC7JAAAAABVSF7O6YWCTGMYMDXSDQYUCV2UUO5AI35QXNTQAWGXEGYPJ2BD5I"
5
+ API_KEY = ""
6
6
 
7
7
 
8
8
  class TestAsyncTonapi(IsolatedAsyncioTestCase):
@@ -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 = "0:0336261f4d3e8a3521b5fc38ee30d203de5ec60d8231a4b3f2e42d512bedd7cc" # noqa
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("EQBcjALtmHwSBCSpDOZ1_emrSQVtJU6J0POZR-ThkZjfXkZs")
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])
@@ -2,7 +2,7 @@ from unittest import TestCase
2
2
 
3
3
  from pytonapi import Tonapi
4
4
 
5
- API_KEY = "AE33EX7DNCVC7JAAAAABVSF7O6YWCTGMYMDXSDQYUCV2UUO5AI35QXNTQAWGXEGYPJ2BD5I"
5
+ API_KEY = ""
6
6
 
7
7
 
8
8
  class TestTonapi(TestCase):
@@ -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