tonutils 0.5.1__py3-none-any.whl → 0.6.0a1__py3-none-any.whl

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 (196) hide show
  1. tonutils/{client → clients}/__init__.py +3 -11
  2. tonutils/clients/base.py +95 -0
  3. tonutils/clients/liteserver/__init__.py +3 -0
  4. tonutils/clients/liteserver/client.py +155 -0
  5. tonutils/clients/liteserver/stub.py +70 -0
  6. tonutils/clients/quicknode/__init__.py +3 -0
  7. tonutils/clients/quicknode/api.py +19 -0
  8. tonutils/clients/quicknode/client.py +20 -0
  9. tonutils/clients/tatum/__init__.py +3 -0
  10. tonutils/clients/tatum/api.py +28 -0
  11. tonutils/clients/tatum/client.py +24 -0
  12. tonutils/clients/tonapi/__init__.py +3 -0
  13. tonutils/clients/tonapi/api.py +93 -0
  14. tonutils/clients/tonapi/client.py +146 -0
  15. tonutils/clients/tonapi/models.py +34 -0
  16. tonutils/clients/toncenter/__init__.py +3 -0
  17. tonutils/clients/toncenter/api.py +91 -0
  18. tonutils/clients/toncenter/client.py +200 -0
  19. tonutils/clients/toncenter/models.py +70 -0
  20. tonutils/contracts/__init__.py +55 -0
  21. tonutils/contracts/base.py +155 -0
  22. tonutils/contracts/codes.py +30 -0
  23. tonutils/contracts/nft/__init__.py +21 -0
  24. tonutils/contracts/nft/collection.py +116 -0
  25. tonutils/contracts/nft/get_methods.py +124 -0
  26. tonutils/contracts/nft/item.py +119 -0
  27. tonutils/contracts/wallet/__init__.py +39 -0
  28. tonutils/contracts/wallet/base.py +300 -0
  29. tonutils/contracts/wallet/get_methods.py +145 -0
  30. tonutils/contracts/wallet/versions/__init__.py +45 -0
  31. tonutils/contracts/wallet/versions/hw.py +215 -0
  32. tonutils/contracts/wallet/versions/pp.py +88 -0
  33. tonutils/contracts/wallet/versions/v1.py +92 -0
  34. tonutils/contracts/wallet/versions/v2.py +81 -0
  35. tonutils/contracts/wallet/versions/v3.py +80 -0
  36. tonutils/contracts/wallet/versions/v4.py +102 -0
  37. tonutils/contracts/wallet/versions/v5.py +236 -0
  38. tonutils/exceptions.py +74 -25
  39. tonutils/protocols/__init__.py +9 -0
  40. tonutils/protocols/client.py +41 -0
  41. tonutils/protocols/contract.py +99 -0
  42. tonutils/protocols/wallet.py +116 -0
  43. tonutils/tonconnect/__init__.py +0 -11
  44. tonutils/types/__init__.py +187 -0
  45. tonutils/types/client.py +7 -0
  46. tonutils/types/common.py +39 -0
  47. tonutils/types/configs.py +79 -0
  48. tonutils/types/contract.py +79 -0
  49. tonutils/types/keystructs.py +91 -0
  50. tonutils/types/messages.py +142 -0
  51. tonutils/types/opcodes.py +15 -0
  52. tonutils/types/params.py +85 -0
  53. tonutils/types/stack.py +17 -0
  54. tonutils/types/tlb/__init__.py +87 -0
  55. tonutils/types/tlb/content.py +156 -0
  56. tonutils/types/tlb/contract.py +9 -0
  57. tonutils/types/tlb/msg.py +36 -0
  58. tonutils/types/tlb/nft.py +626 -0
  59. tonutils/types/tlb/text.py +53 -0
  60. tonutils/types/tlb/wallet.py +299 -0
  61. tonutils/utils/__init__.py +51 -0
  62. tonutils/utils/converters.py +58 -0
  63. tonutils/utils/msg_builders.py +82 -0
  64. tonutils/utils/parse_config.py +35 -0
  65. tonutils/utils/stack_codec.py +188 -0
  66. tonutils/utils/text_cipher.py +140 -0
  67. tonutils/utils/validations.py +23 -0
  68. tonutils/utils/value_utils.py +62 -0
  69. tonutils/utils/wallet_utils.py +55 -0
  70. {tonutils-0.5.1.dist-info → tonutils-0.6.0a1.dist-info}/METADATA +5 -10
  71. tonutils-0.6.0a1.dist-info/RECORD +76 -0
  72. {tonutils-0.5.1.dist-info → tonutils-0.6.0a1.dist-info}/licenses/LICENSE +1 -1
  73. tonutils/account.py +0 -32
  74. tonutils/cache.py +0 -82
  75. tonutils/client/_base.py +0 -292
  76. tonutils/client/lite.py +0 -163
  77. tonutils/client/quicknode.py +0 -33
  78. tonutils/client/tatum.py +0 -50
  79. tonutils/client/tonapi.py +0 -145
  80. tonutils/client/toncenter.py +0 -303
  81. tonutils/client/utils.py +0 -203
  82. tonutils/contract.py +0 -184
  83. tonutils/dns/__init__.py +0 -5
  84. tonutils/dns/categories.py +0 -15
  85. tonutils/dns/contract.py +0 -256
  86. tonutils/dns/op_codes.py +0 -1
  87. tonutils/dns/subdomain_collection/__init__.py +0 -5
  88. tonutils/dns/subdomain_collection/content.py +0 -18
  89. tonutils/dns/subdomain_collection/contract.py +0 -91
  90. tonutils/dns/subdomain_collection/data.py +0 -63
  91. tonutils/dns/subdomain_collection/op_codes.py +0 -5
  92. tonutils/dns/subdomain_manager/__init__.py +0 -5
  93. tonutils/dns/subdomain_manager/contract.py +0 -210
  94. tonutils/dns/subdomain_manager/data.py +0 -38
  95. tonutils/dns/subdomain_manager/op_codes.py +0 -1
  96. tonutils/dns/utils.py +0 -115
  97. tonutils/jetton/__init__.py +0 -15
  98. tonutils/jetton/content.py +0 -79
  99. tonutils/jetton/contract/__init__.py +0 -10
  100. tonutils/jetton/contract/base/__init__.py +0 -5
  101. tonutils/jetton/contract/base/master.py +0 -76
  102. tonutils/jetton/contract/stablecoin/__init__.py +0 -7
  103. tonutils/jetton/contract/stablecoin/master.py +0 -188
  104. tonutils/jetton/contract/stablecoin/op_codes.py +0 -15
  105. tonutils/jetton/contract/stablecoin/wallet.py +0 -130
  106. tonutils/jetton/contract/standard/__init__.py +0 -7
  107. tonutils/jetton/contract/standard/master.py +0 -141
  108. tonutils/jetton/contract/standard/op_codes.py +0 -11
  109. tonutils/jetton/contract/standard/wallet.py +0 -132
  110. tonutils/jetton/data.py +0 -165
  111. tonutils/jetton/dex/__init__.py +0 -0
  112. tonutils/jetton/dex/dedust/__init__.py +0 -5
  113. tonutils/jetton/dex/dedust/constants.py +0 -48
  114. tonutils/jetton/dex/dedust/factory.py +0 -362
  115. tonutils/jetton/dex/stonfi/__init__.py +0 -10
  116. tonutils/jetton/dex/stonfi/utils.py +0 -47
  117. tonutils/jetton/dex/stonfi/v1/__init__.py +0 -7
  118. tonutils/jetton/dex/stonfi/v1/pton/__init__.py +0 -5
  119. tonutils/jetton/dex/stonfi/v1/pton/constants.py +0 -19
  120. tonutils/jetton/dex/stonfi/v1/pton/pton.py +0 -78
  121. tonutils/jetton/dex/stonfi/v1/router/__init__.py +0 -5
  122. tonutils/jetton/dex/stonfi/v1/router/constants.py +0 -38
  123. tonutils/jetton/dex/stonfi/v1/router/router.py +0 -193
  124. tonutils/jetton/dex/stonfi/v2/__init__.py +0 -7
  125. tonutils/jetton/dex/stonfi/v2/pton/__init__.py +0 -5
  126. tonutils/jetton/dex/stonfi/v2/pton/constants.py +0 -21
  127. tonutils/jetton/dex/stonfi/v2/pton/pton.py +0 -102
  128. tonutils/jetton/dex/stonfi/v2/router/__init__.py +0 -5
  129. tonutils/jetton/dex/stonfi/v2/router/constants.py +0 -41
  130. tonutils/jetton/dex/stonfi/v2/router/router.py +0 -308
  131. tonutils/nft/__init__.py +0 -22
  132. tonutils/nft/content.py +0 -135
  133. tonutils/nft/contract/__init__.py +0 -0
  134. tonutils/nft/contract/base/__init__.py +0 -7
  135. tonutils/nft/contract/base/collection.py +0 -80
  136. tonutils/nft/contract/base/nft.py +0 -71
  137. tonutils/nft/contract/editable/__init__.py +0 -9
  138. tonutils/nft/contract/editable/collection.py +0 -341
  139. tonutils/nft/contract/editable/nft.py +0 -155
  140. tonutils/nft/contract/soulbound/__init__.py +0 -9
  141. tonutils/nft/contract/soulbound/collection.py +0 -277
  142. tonutils/nft/contract/soulbound/nft.py +0 -123
  143. tonutils/nft/contract/standard/__init__.py +0 -9
  144. tonutils/nft/contract/standard/collection.py +0 -257
  145. tonutils/nft/contract/standard/nft.py +0 -78
  146. tonutils/nft/data.py +0 -95
  147. tonutils/nft/marketplace/__init__.py +0 -0
  148. tonutils/nft/marketplace/getgems/__init__.py +0 -5
  149. tonutils/nft/marketplace/getgems/addresses.py +0 -8
  150. tonutils/nft/marketplace/getgems/contract/__init__.py +0 -5
  151. tonutils/nft/marketplace/getgems/contract/salev3r3.py +0 -161
  152. tonutils/nft/marketplace/getgems/data.py +0 -54
  153. tonutils/nft/marketplace/getgems/op_codes.py +0 -7
  154. tonutils/nft/op_codes.py +0 -19
  155. tonutils/nft/royalty_params.py +0 -29
  156. tonutils/tonconnect/connector.py +0 -699
  157. tonutils/tonconnect/models/__init__.py +0 -53
  158. tonutils/tonconnect/models/account.py +0 -57
  159. tonutils/tonconnect/models/chain.py +0 -10
  160. tonutils/tonconnect/models/device.py +0 -137
  161. tonutils/tonconnect/models/event.py +0 -33
  162. tonutils/tonconnect/models/proof.py +0 -80
  163. tonutils/tonconnect/models/request.py +0 -533
  164. tonutils/tonconnect/models/wallet.py +0 -248
  165. tonutils/tonconnect/provider/__init__.py +0 -5
  166. tonutils/tonconnect/provider/bridge.py +0 -581
  167. tonutils/tonconnect/provider/session.py +0 -104
  168. tonutils/tonconnect/storage/__init__.py +0 -7
  169. tonutils/tonconnect/storage/base.py +0 -39
  170. tonutils/tonconnect/storage/default.py +0 -40
  171. tonutils/tonconnect/tonconnect.py +0 -290
  172. tonutils/tonconnect/utils/__init__.py +0 -25
  173. tonutils/tonconnect/utils/exceptions.py +0 -140
  174. tonutils/tonconnect/utils/logger.py +0 -3
  175. tonutils/tonconnect/utils/verifiers.py +0 -255
  176. tonutils/tonconnect/utils/wallet_manager.py +0 -239
  177. tonutils/utils.py +0 -207
  178. tonutils/vanity/__init__.py +0 -5
  179. tonutils/vanity/contract.py +0 -35
  180. tonutils/vanity/data.py +0 -34
  181. tonutils/wallet/__init__.py +0 -31
  182. tonutils/wallet/contract/__init__.py +0 -24
  183. tonutils/wallet/contract/_base.py +0 -438
  184. tonutils/wallet/contract/highload.py +0 -505
  185. tonutils/wallet/contract/preprocessed.py +0 -291
  186. tonutils/wallet/contract/v2.py +0 -95
  187. tonutils/wallet/contract/v3.py +0 -94
  188. tonutils/wallet/contract/v4.py +0 -122
  189. tonutils/wallet/contract/v5.py +0 -193
  190. tonutils/wallet/data.py +0 -188
  191. tonutils/wallet/messages.py +0 -631
  192. tonutils/wallet/op_codes.py +0 -9
  193. tonutils/wallet/utils.py +0 -57
  194. tonutils-0.5.1.dist-info/RECORD +0 -131
  195. {tonutils-0.5.1.dist-info → tonutils-0.6.0a1.dist-info}/WHEEL +0 -0
  196. {tonutils-0.5.1.dist-info → tonutils-0.6.0a1.dist-info}/top_level.txt +0 -0
@@ -1,21 +1,13 @@
1
- from ._base import Client
2
-
3
- from .lite import LiteserverClient
1
+ from .liteserver import LiteserverClient
4
2
  from .quicknode import QuicknodeClient
5
3
  from .tatum import TatumClient
6
4
  from .tonapi import TonapiClient
7
- from .toncenter import (
8
- ToncenterV2Client,
9
- ToncenterV3Client,
10
- )
5
+ from .toncenter import ToncenterClient
11
6
 
12
7
  __all__ = [
13
- "Client",
14
-
15
8
  "LiteserverClient",
16
9
  "QuicknodeClient",
17
10
  "TatumClient",
18
11
  "TonapiClient",
19
- "ToncenterV2Client",
20
- "ToncenterV3Client",
12
+ "ToncenterClient",
21
13
  ]
@@ -0,0 +1,95 @@
1
+ import abc
2
+ import typing as t
3
+
4
+ from pyapiq import AsyncClientAPI
5
+ from pytoniq_core import Address, Transaction
6
+
7
+ from .liteserver.stub import LiteBalancer
8
+ from ..types import AddressLike, ContractStateInfo
9
+
10
+ A = t.TypeVar("A", bound=t.Union[AsyncClientAPI, LiteBalancer])
11
+
12
+
13
+ class BaseClient(abc.ABC, t.Generic[A]):
14
+ is_testnet: bool
15
+ api: A
16
+
17
+ @abc.abstractmethod
18
+ async def _send_boc(self, boc: str) -> None:
19
+ raise NotImplementedError
20
+
21
+ @abc.abstractmethod
22
+ async def _get_blockchain_config(self) -> t.Dict[int, t.Any]:
23
+ raise NotImplementedError
24
+
25
+ @abc.abstractmethod
26
+ async def _get_contract_info(self, address: str) -> ContractStateInfo:
27
+ raise NotImplementedError
28
+
29
+ @abc.abstractmethod
30
+ async def _get_contract_transactions(
31
+ self,
32
+ address: str,
33
+ limit: int = 100,
34
+ from_lt: t.Optional[int] = None,
35
+ to_lt: t.Optional[int] = 0,
36
+ ) -> t.List[Transaction]:
37
+ raise NotImplementedError
38
+
39
+ @abc.abstractmethod
40
+ async def _run_get_method(
41
+ self,
42
+ address: str,
43
+ method_name: str,
44
+ stack: t.Optional[t.List[t.Any]] = None,
45
+ ) -> t.List[t.Any]:
46
+ raise NotImplementedError
47
+
48
+ @abc.abstractmethod
49
+ async def startup(self) -> None:
50
+ raise NotImplementedError
51
+
52
+ @abc.abstractmethod
53
+ async def close(self) -> None:
54
+ raise NotImplementedError
55
+
56
+ async def send_boc(self, boc: str) -> None:
57
+ await self._send_boc(boc)
58
+
59
+ async def get_blockchain_config(self) -> t.Dict[int, t.Any]:
60
+ return await self._get_blockchain_config()
61
+
62
+ async def get_contract_info(self, address: AddressLike) -> ContractStateInfo:
63
+ if isinstance(address, Address):
64
+ address = Address(address).to_str(is_user_friendly=False)
65
+ return await self._get_contract_info(address=address)
66
+
67
+ async def get_contract_transactions(
68
+ self,
69
+ address: AddressLike,
70
+ limit: int = 100,
71
+ from_lt: t.Optional[int] = None,
72
+ to_lt: t.Optional[int] = 0,
73
+ ) -> t.List[Transaction]:
74
+ if isinstance(address, Address):
75
+ address = Address(address).to_str(is_user_friendly=False)
76
+ return await self._get_contract_transactions(
77
+ address=address,
78
+ limit=limit,
79
+ from_lt=from_lt,
80
+ to_lt=to_lt,
81
+ )
82
+
83
+ async def run_get_method(
84
+ self,
85
+ address: AddressLike,
86
+ method_name: str,
87
+ stack: t.Optional[t.List[t.Any]] = None,
88
+ ) -> t.List[t.Any]:
89
+ if isinstance(address, Address):
90
+ address = Address(address).to_str(is_user_friendly=False)
91
+ return await self._run_get_method(
92
+ address=address,
93
+ method_name=method_name,
94
+ stack=stack,
95
+ )
@@ -0,0 +1,3 @@
1
+ from .client import LiteserverClient
2
+
3
+ __all__ = ["LiteserverClient"]
@@ -0,0 +1,155 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+ from functools import wraps
5
+
6
+ from pytoniq_core import Address, SimpleAccount, Transaction
7
+
8
+ from ..base import BaseClient
9
+ from ...exceptions import PytoniqDependencyError
10
+ from ...types import (
11
+ ContractStateInfo,
12
+ ContractState,
13
+ ClientType,
14
+ )
15
+ from ...utils import (
16
+ StackCodec,
17
+ cell_to_hex,
18
+ )
19
+
20
+ try:
21
+ # noinspection PyPackageRequirements
22
+ from pytoniq import LiteBalancer
23
+
24
+ pytoniq_available = True
25
+ except ImportError:
26
+ pytoniq_available = False
27
+ from .stub import LiteBalancer
28
+
29
+ F = t.TypeVar("F", bound=t.Callable[..., t.Any])
30
+
31
+
32
+ def _ensure_api_ready(func: F) -> F:
33
+
34
+ @wraps(func)
35
+ async def wrapper(self: LiteserverClient, *args: t.Any, **kwargs: t.Any) -> t.Any:
36
+ if not pytoniq_available:
37
+ raise PytoniqDependencyError()
38
+ if not self.api.inited:
39
+ await self.api.start_up()
40
+ return await func(self, *args, **kwargs)
41
+
42
+ return t.cast(F, wrapper)
43
+
44
+
45
+ class LiteserverClient(BaseClient[LiteBalancer]):
46
+
47
+ def __init__(
48
+ self,
49
+ config: t.Optional[t.Dict[str, t.Any]] = None,
50
+ is_testnet: bool = False,
51
+ trust_level: int = 2,
52
+ ) -> None:
53
+ if not pytoniq_available:
54
+ raise PytoniqDependencyError()
55
+
56
+ if config is not None:
57
+ self.api = LiteBalancer.from_config(config, trust_level)
58
+ elif is_testnet:
59
+ self.api = LiteBalancer.from_testnet_config(trust_level)
60
+ else:
61
+ self.api = LiteBalancer.from_mainnet_config(trust_level)
62
+
63
+ self.is_testnet = is_testnet
64
+
65
+ async def __aenter__(self) -> LiteBalancer:
66
+ return await self.api.__aenter__()
67
+
68
+ async def __aexit__(
69
+ self,
70
+ exc_type: t.Optional[t.Type[BaseException]],
71
+ exc_value: t.Optional[BaseException],
72
+ traceback: t.Optional[t.Any],
73
+ ) -> None:
74
+ await self.api.__aexit__(exc_type, exc_value, traceback)
75
+
76
+ @_ensure_api_ready
77
+ async def _send_boc(self, boc: str) -> None:
78
+ await self.api.raw_send_message(bytes.fromhex(boc))
79
+
80
+ @_ensure_api_ready
81
+ async def _get_blockchain_config(self) -> t.Dict[int, t.Any]:
82
+ return await self.api.get_config_all()
83
+
84
+ @_ensure_api_ready
85
+ async def _get_contract_info(self, address: str) -> ContractStateInfo:
86
+ account, shard_account = await self.api.raw_get_account_state(address)
87
+
88
+ simple_account = SimpleAccount.from_raw(account, Address(address))
89
+ contract_info = ContractStateInfo(balance=simple_account.balance)
90
+
91
+ if simple_account.state is not None:
92
+ state_init = simple_account.state.state_init
93
+ if state_init is not None:
94
+ if state_init.code is not None:
95
+ contract_info.code_raw = cell_to_hex(state_init.code)
96
+ if state_init.data is not None:
97
+ contract_info.data_raw = cell_to_hex(state_init.data)
98
+
99
+ contract_info.state = ContractState(
100
+ "uninit"
101
+ if simple_account.state.type_ == "uninitialized"
102
+ else simple_account.state.type_
103
+ )
104
+
105
+ if shard_account is not None:
106
+ if shard_account.last_trans_lt is not None:
107
+ contract_info.last_transaction_lt = int(shard_account.last_trans_lt)
108
+ if shard_account.last_trans_hash is not None:
109
+ contract_info.last_transaction_hash = (
110
+ shard_account.last_trans_hash.hex()
111
+ )
112
+ if (
113
+ contract_info.last_transaction_lt is None
114
+ and contract_info.last_transaction_hash is None
115
+ and contract_info.state == ContractState.UNINIT
116
+ ):
117
+ contract_info.state = ContractState.NONEXIST
118
+
119
+ return contract_info
120
+
121
+ @_ensure_api_ready
122
+ async def _get_contract_transactions(
123
+ self,
124
+ address: str,
125
+ limit: int = 100,
126
+ from_lt: t.Optional[int] = None,
127
+ to_lt: t.Optional[int] = 0,
128
+ ) -> t.List[Transaction]:
129
+ return await self.api.get_transactions(
130
+ address=Address(address),
131
+ count=limit,
132
+ from_lt=from_lt,
133
+ to_lt=to_lt,
134
+ )
135
+
136
+ @_ensure_api_ready
137
+ async def _run_get_method(
138
+ self,
139
+ address: str,
140
+ method_name: str,
141
+ stack: t.Optional[t.List[t.Any]] = None,
142
+ ) -> t.List[t.Any]:
143
+ stack_codec = StackCodec(ClientType.LITESERVER)
144
+ stack_result = await self.api.run_get_method(
145
+ address=address,
146
+ method=method_name,
147
+ stack=stack_codec.encode(stack or []),
148
+ )
149
+ return stack_codec.decode(stack_result or [])
150
+
151
+ async def startup(self) -> None:
152
+ await self.api.start_up()
153
+
154
+ async def close(self) -> None:
155
+ await self.api.close_all()
@@ -0,0 +1,70 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+ from types import TracebackType
5
+
6
+ from pytoniq_core import Address, Transaction
7
+
8
+ from ...exceptions import PytoniqDependencyError
9
+
10
+
11
+ class LiteBalancer:
12
+ inited: bool = False
13
+
14
+ @staticmethod
15
+ def from_config(
16
+ config: t.Dict[str, t.Any],
17
+ trust_level: int,
18
+ ) -> LiteBalancer:
19
+ raise PytoniqDependencyError()
20
+
21
+ @staticmethod
22
+ def from_testnet_config(trust_level: int) -> LiteBalancer:
23
+ raise PytoniqDependencyError()
24
+
25
+ @staticmethod
26
+ def from_mainnet_config(trust_level: int) -> LiteBalancer:
27
+ raise PytoniqDependencyError()
28
+
29
+ async def __aenter__(self) -> LiteBalancer:
30
+ raise PytoniqDependencyError()
31
+
32
+ async def __aexit__(
33
+ self,
34
+ exc_type: t.Optional[type[BaseException]],
35
+ exc_value: t.Optional[BaseException],
36
+ traceback: t.Optional[TracebackType],
37
+ ) -> None:
38
+ raise PytoniqDependencyError()
39
+
40
+ async def run_get_method(
41
+ self,
42
+ address: t.Union[str, Address],
43
+ method: str,
44
+ stack: t.List[t.Any],
45
+ ) -> t.Any:
46
+ raise PytoniqDependencyError()
47
+
48
+ async def raw_send_message(self, message: bytes) -> None:
49
+ raise PytoniqDependencyError()
50
+
51
+ async def start_up(self):
52
+ raise PytoniqDependencyError()
53
+
54
+ async def close_all(self):
55
+ raise PytoniqDependencyError()
56
+
57
+ async def raw_get_account_state(self, address):
58
+ raise PytoniqDependencyError()
59
+
60
+ async def get_config_all(self) -> t.Dict[int, t.Any]:
61
+ raise PytoniqDependencyError()
62
+
63
+ async def get_transactions(
64
+ self,
65
+ address: t.Union[str, Address],
66
+ count: int,
67
+ from_lt: t.Optional[int] = None,
68
+ to_lt: int = 0,
69
+ ) -> t.List[Transaction]:
70
+ raise PytoniqDependencyError()
@@ -0,0 +1,3 @@
1
+ from .client import QuicknodeClient
2
+
3
+ __all__ = ["QuicknodeClient"]
@@ -0,0 +1,19 @@
1
+ import typing as t
2
+
3
+ from ..toncenter.api import ToncenterAPI
4
+
5
+
6
+ class QuicknodeAPI(ToncenterAPI):
7
+
8
+ def __init__(
9
+ self,
10
+ http_provider_url: str,
11
+ rps: t.Optional[int] = None,
12
+ max_retries: t.Optional[int] = None,
13
+ ) -> None:
14
+ super().__init__(
15
+ is_testnet=False,
16
+ base_url=http_provider_url,
17
+ rps=rps,
18
+ max_retries=max_retries,
19
+ )
@@ -0,0 +1,20 @@
1
+ import typing as t
2
+
3
+ from .api import QuicknodeAPI
4
+ from ..toncenter.client import ToncenterClient
5
+
6
+
7
+ class QuicknodeClient(ToncenterClient):
8
+
9
+ def __init__(
10
+ self,
11
+ http_provider_url: str,
12
+ rps: t.Optional[int] = None,
13
+ max_retries: int = 2,
14
+ ) -> None:
15
+ super().__init__(is_testnet=False)
16
+ self.api = QuicknodeAPI(
17
+ http_provider_url=http_provider_url,
18
+ rps=rps,
19
+ max_retries=max_retries,
20
+ )
@@ -0,0 +1,3 @@
1
+ from .client import TatumClient
2
+
3
+ __all__ = ["TatumClient"]
@@ -0,0 +1,28 @@
1
+ import typing as t
2
+
3
+ from ..toncenter.api import ToncenterAPI
4
+
5
+
6
+ class TatumAPI(ToncenterAPI):
7
+
8
+ def __init__(
9
+ self,
10
+ api_key: str,
11
+ is_testnet: bool = False,
12
+ base_url: t.Optional[str] = None,
13
+ rps: t.Optional[int] = None,
14
+ max_retries: t.Optional[int] = None,
15
+ ) -> None:
16
+ mainnet_url = "https://ton-mainnet.gateway.tatum.io"
17
+ testnet_url = "https://ton-testnet.gateway.tatum.io"
18
+ default_url = testnet_url if is_testnet else mainnet_url
19
+
20
+ base_url = base_url or default_url
21
+
22
+ super().__init__(
23
+ api_key=api_key,
24
+ is_testnet=is_testnet,
25
+ base_url=base_url,
26
+ rps=rps,
27
+ max_retries=max_retries,
28
+ )
@@ -0,0 +1,24 @@
1
+ import typing as t
2
+
3
+ from .api import TatumAPI
4
+ from ..toncenter.client import ToncenterClient
5
+
6
+
7
+ class TatumClient(ToncenterClient):
8
+
9
+ def __init__(
10
+ self,
11
+ api_key: str,
12
+ is_testnet: bool = False,
13
+ base_url: t.Optional[str] = None,
14
+ rps: t.Optional[int] = None,
15
+ max_retries: int = 2,
16
+ ) -> None:
17
+ super().__init__(is_testnet=is_testnet)
18
+ self.api = TatumAPI(
19
+ api_key=api_key,
20
+ is_testnet=is_testnet,
21
+ base_url=base_url,
22
+ rps=rps,
23
+ max_retries=max_retries,
24
+ )
@@ -0,0 +1,3 @@
1
+ from .client import TonapiClient
2
+
3
+ __all__ = ["TonapiClient"]
@@ -0,0 +1,93 @@
1
+ import typing as t
2
+
3
+ from pyapiq import AsyncClientAPI, async_endpoint
4
+ from pyapiq.types import ReturnType, RepeatQuery, HTTPMethod
5
+
6
+ from .models import (
7
+ BlockchainMessagePayload,
8
+ BlockchainConfigResult,
9
+ BlockchainAccountResult,
10
+ BlockchainAccountTransactionsResult,
11
+ BlockchainAccountMethodResult,
12
+ )
13
+
14
+
15
+ class TonapiAPI(AsyncClientAPI):
16
+ version = "v2"
17
+
18
+ def __init__(
19
+ self,
20
+ api_key: str,
21
+ is_testnet: bool = False,
22
+ base_url: t.Optional[str] = None,
23
+ rps: t.Optional[int] = None,
24
+ max_retries: t.Optional[int] = None,
25
+ ) -> None:
26
+ mainnet_url = "https://tonapi.io"
27
+ testnet_url = "https://testnet.tonapi.io"
28
+ default_url = testnet_url if is_testnet else mainnet_url
29
+
30
+ base_url = base_url or default_url
31
+ headers = {"Authorization": f"Bearer {api_key}"}
32
+
33
+ super().__init__(
34
+ base_url=base_url,
35
+ headers=headers,
36
+ rps=rps,
37
+ max_retries=max_retries,
38
+ )
39
+
40
+ @async_endpoint(
41
+ HTTPMethod.POST,
42
+ path="/blockchain/message",
43
+ return_as=ReturnType.NONE,
44
+ )
45
+ async def blockchain_message( # type: ignore[empty-body]
46
+ self,
47
+ payload: BlockchainMessagePayload,
48
+ ) -> None: ...
49
+
50
+ @async_endpoint(
51
+ HTTPMethod.GET,
52
+ path="/blockchain/config",
53
+ return_as=BlockchainConfigResult,
54
+ )
55
+ async def blockchain_config( # type: ignore[empty-body]
56
+ self,
57
+ ) -> BlockchainConfigResult: ...
58
+
59
+ @async_endpoint(
60
+ HTTPMethod.GET,
61
+ path="/blockchain/accounts/{address}",
62
+ return_as=BlockchainAccountResult,
63
+ )
64
+ async def blockchain_account( # type: ignore[empty-body]
65
+ self,
66
+ address: str,
67
+ ) -> BlockchainAccountResult: ...
68
+
69
+ @async_endpoint(
70
+ HTTPMethod.GET,
71
+ path="/blockchain/accounts/{address}/transactions",
72
+ return_as=BlockchainAccountTransactionsResult,
73
+ )
74
+ async def blockchain_account_transactions( # type: ignore[empty-body]
75
+ self,
76
+ address: str,
77
+ limit: int = 100,
78
+ after_lt: t.Optional[int] = None,
79
+ before_lt: t.Optional[int] = 0,
80
+ sort_order: t.Optional[t.Literal["asc", "desc"]] = "desc",
81
+ ) -> BlockchainAccountTransactionsResult: ...
82
+
83
+ @async_endpoint(
84
+ HTTPMethod.GET,
85
+ path="/blockchain/accounts/{address}/methods/{method_name}",
86
+ return_as=BlockchainAccountMethodResult,
87
+ )
88
+ async def blockchain_account_method( # type: ignore[empty-body]
89
+ self,
90
+ address: str,
91
+ method_name: str,
92
+ args: t.Annotated[t.List[t.Any], RepeatQuery],
93
+ ) -> BlockchainAccountMethodResult: ...
@@ -0,0 +1,146 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+ from functools import wraps
5
+
6
+ from pyapiq import AsyncClientAPI
7
+ from pytoniq_core import Cell, Slice, Transaction
8
+
9
+ from .api import TonapiAPI
10
+ from .models import BlockchainMessagePayload
11
+ from ..base import BaseClient
12
+ from ...exceptions import ClientError
13
+ from ...types import (
14
+ ContractStateInfo,
15
+ ContractState,
16
+ ClientType,
17
+ )
18
+ from ...utils import (
19
+ StackCodec,
20
+ cell_to_hex,
21
+ parse_config,
22
+ )
23
+
24
+ F = t.TypeVar("F", bound=t.Callable[..., t.Any])
25
+
26
+
27
+ def _ensure_api_ready(func: F) -> F:
28
+
29
+ @wraps(func)
30
+ async def wrapper(self: "TonapiClient", *args: t.Any, **kwargs: t.Any) -> t.Any:
31
+ if self.api.session is None:
32
+ await self.api.ensure_session()
33
+ return await func(self, *args, **kwargs)
34
+
35
+ return t.cast(F, wrapper)
36
+
37
+
38
+ class TonapiClient(BaseClient[TonapiAPI]):
39
+
40
+ def __init__(
41
+ self,
42
+ api_key: str,
43
+ is_testnet: bool = False,
44
+ base_url: t.Optional[str] = None,
45
+ rps: t.Optional[int] = None,
46
+ max_retries: int = 2,
47
+ ) -> None:
48
+ self.is_testnet = is_testnet
49
+ self.api = TonapiAPI(
50
+ api_key=api_key,
51
+ is_testnet=is_testnet,
52
+ base_url=base_url,
53
+ rps=rps,
54
+ max_retries=max_retries,
55
+ )
56
+
57
+ async def __aenter__(self) -> AsyncClientAPI:
58
+ return await self.api.__aenter__()
59
+
60
+ async def __aexit__(
61
+ self,
62
+ exc_type: t.Optional[t.Type[BaseException]],
63
+ exc_value: t.Optional[BaseException],
64
+ traceback: t.Optional[t.Any],
65
+ ) -> None:
66
+ await self.api.__aexit__(exc_type, exc_value, traceback)
67
+
68
+ @_ensure_api_ready
69
+ async def _send_boc(self, boc: str) -> None:
70
+ payload = BlockchainMessagePayload(boc=boc)
71
+ return await self.api.blockchain_message(payload=payload)
72
+
73
+ @_ensure_api_ready
74
+ async def _get_blockchain_config(self) -> t.Dict[int, t.Any]:
75
+ result = await self.api.blockchain_config()
76
+
77
+ if result.raw is None:
78
+ raise ClientError("Invalid config response: missing 'raw' field")
79
+
80
+ config_cell = Cell.one_from_boc(result.raw)[0]
81
+ config_slice = config_cell.begin_parse()
82
+ return parse_config(config_slice)
83
+
84
+ @_ensure_api_ready
85
+ async def _get_contract_info(self, address: str) -> ContractStateInfo:
86
+ result = await self.api.blockchain_account(address)
87
+
88
+ contract_info = ContractStateInfo(
89
+ balance=result.balance,
90
+ state=ContractState(result.status),
91
+ last_transaction_lt=result.last_transaction_lt,
92
+ last_transaction_hash=result.last_transaction_hash,
93
+ )
94
+ if result.code is not None:
95
+ contract_info.code_raw = cell_to_hex(result.code)
96
+ if result.data is not None:
97
+ contract_info.data_raw = cell_to_hex(result.data)
98
+
99
+ return contract_info
100
+
101
+ @_ensure_api_ready
102
+ async def _get_contract_transactions(
103
+ self,
104
+ address: str,
105
+ limit: int = 100,
106
+ from_lt: t.Optional[int] = None,
107
+ to_lt: t.Optional[int] = 0,
108
+ ) -> t.List[Transaction]:
109
+ if from_lt is not None:
110
+ from_lt += 1
111
+
112
+ result = await self.api.blockchain_account_transactions(
113
+ address=address,
114
+ limit=limit,
115
+ after_lt=to_lt,
116
+ before_lt=from_lt,
117
+ )
118
+
119
+ transactions = []
120
+ for tx in result.transactions or []:
121
+ if tx.raw is not None:
122
+ tx_slice = Slice.one_from_boc(tx.raw)
123
+ transactions.append(Transaction.deserialize(tx_slice))
124
+
125
+ return transactions
126
+
127
+ @_ensure_api_ready
128
+ async def _run_get_method(
129
+ self,
130
+ address: str,
131
+ method_name: str,
132
+ stack: t.Optional[t.List[t.Any]] = None,
133
+ ) -> t.List[t.Any]:
134
+ stack_codec = StackCodec(ClientType.TONAPI)
135
+ result = await self.api.blockchain_account_method(
136
+ address=address,
137
+ method_name=method_name,
138
+ args=stack_codec.encode(stack or []),
139
+ )
140
+ return stack_codec.decode(result.stack or [])
141
+
142
+ async def startup(self) -> None:
143
+ await self.api.ensure_session()
144
+
145
+ async def close(self) -> None:
146
+ await self.api.close()