tonutils 2.0.1b2__py3-none-any.whl → 2.0.1b4__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 (91) hide show
  1. tonutils/__init__.py +0 -2
  2. tonutils/__meta__.py +1 -1
  3. tonutils/cli.py +111 -0
  4. tonutils/clients/__init__.py +7 -11
  5. tonutils/clients/adnl/__init__.py +7 -3
  6. tonutils/clients/adnl/balancer.py +362 -168
  7. tonutils/clients/adnl/client.py +203 -67
  8. tonutils/clients/adnl/provider/config.py +24 -25
  9. tonutils/clients/adnl/provider/models.py +4 -0
  10. tonutils/clients/adnl/provider/provider.py +203 -160
  11. tonutils/clients/adnl/provider/transport.py +44 -33
  12. tonutils/clients/adnl/provider/workers/base.py +0 -2
  13. tonutils/clients/adnl/provider/workers/pinger.py +1 -1
  14. tonutils/clients/adnl/provider/workers/reader.py +3 -2
  15. tonutils/clients/adnl/{provider/builder.py → utils.py} +62 -2
  16. tonutils/clients/http/__init__.py +11 -8
  17. tonutils/clients/http/balancer.py +75 -63
  18. tonutils/clients/http/clients/__init__.py +13 -0
  19. tonutils/clients/http/clients/chainstack.py +48 -0
  20. tonutils/clients/http/clients/quicknode.py +47 -0
  21. tonutils/clients/http/clients/tatum.py +56 -0
  22. tonutils/clients/http/{tonapi/client.py → clients/tonapi.py} +31 -31
  23. tonutils/clients/http/{toncenter/client.py → clients/toncenter.py} +59 -48
  24. tonutils/clients/http/providers/__init__.py +4 -0
  25. tonutils/clients/http/providers/base.py +201 -0
  26. tonutils/clients/http/providers/response.py +85 -0
  27. tonutils/clients/http/providers/tonapi/__init__.py +3 -0
  28. tonutils/clients/http/{tonapi → providers/tonapi}/models.py +1 -0
  29. tonutils/clients/http/providers/tonapi/provider.py +125 -0
  30. tonutils/clients/http/providers/toncenter/__init__.py +3 -0
  31. tonutils/clients/http/{toncenter → providers/toncenter}/models.py +1 -0
  32. tonutils/clients/http/providers/toncenter/provider.py +119 -0
  33. tonutils/clients/http/utils.py +140 -0
  34. tonutils/clients/limiter.py +115 -0
  35. tonutils/contracts/__init__.py +4 -0
  36. tonutils/contracts/base.py +33 -20
  37. tonutils/contracts/dns/methods.py +2 -2
  38. tonutils/contracts/jetton/methods.py +2 -2
  39. tonutils/contracts/nft/methods.py +2 -2
  40. tonutils/contracts/nft/tlb.py +1 -1
  41. tonutils/{protocols/contract.py → contracts/protocol.py} +29 -29
  42. tonutils/contracts/telegram/methods.py +2 -2
  43. tonutils/contracts/vanity/vanity.py +1 -1
  44. tonutils/contracts/wallet/__init__.py +2 -0
  45. tonutils/contracts/wallet/base.py +3 -3
  46. tonutils/contracts/wallet/messages.py +1 -1
  47. tonutils/contracts/wallet/methods.py +2 -2
  48. tonutils/{protocols/wallet.py → contracts/wallet/protocol.py} +35 -35
  49. tonutils/contracts/wallet/versions/v5.py +3 -3
  50. tonutils/exceptions.py +146 -228
  51. tonutils/tonconnect/__init__.py +0 -0
  52. tonutils/tools/__init__.py +6 -0
  53. tonutils/tools/block_scanner/__init__.py +26 -0
  54. tonutils/tools/block_scanner/annotations.py +23 -0
  55. tonutils/tools/block_scanner/dispatcher.py +141 -0
  56. tonutils/tools/block_scanner/events.py +31 -0
  57. tonutils/tools/block_scanner/scanner.py +315 -0
  58. tonutils/tools/block_scanner/traversal.py +96 -0
  59. tonutils/tools/block_scanner/where.py +151 -0
  60. tonutils/tools/status_monitor/__init__.py +3 -0
  61. tonutils/tools/status_monitor/console.py +157 -0
  62. tonutils/tools/status_monitor/models.py +27 -0
  63. tonutils/tools/status_monitor/monitor.py +295 -0
  64. tonutils/types.py +125 -2
  65. tonutils/utils.py +3 -3
  66. {tonutils-2.0.1b2.dist-info → tonutils-2.0.1b4.dist-info}/METADATA +2 -5
  67. tonutils-2.0.1b4.dist-info/RECORD +108 -0
  68. tonutils-2.0.1b4.dist-info/entry_points.txt +2 -0
  69. tonutils/clients/adnl/provider/limiter.py +0 -56
  70. tonutils/clients/adnl/stack.py +0 -64
  71. tonutils/clients/http/chainstack/__init__.py +0 -4
  72. tonutils/clients/http/chainstack/client.py +0 -63
  73. tonutils/clients/http/chainstack/provider.py +0 -44
  74. tonutils/clients/http/quicknode/__init__.py +0 -4
  75. tonutils/clients/http/quicknode/client.py +0 -60
  76. tonutils/clients/http/quicknode/provider.py +0 -42
  77. tonutils/clients/http/tatum/__init__.py +0 -4
  78. tonutils/clients/http/tatum/client.py +0 -66
  79. tonutils/clients/http/tatum/provider.py +0 -53
  80. tonutils/clients/http/tonapi/__init__.py +0 -4
  81. tonutils/clients/http/tonapi/provider.py +0 -150
  82. tonutils/clients/http/tonapi/stack.py +0 -71
  83. tonutils/clients/http/toncenter/__init__.py +0 -4
  84. tonutils/clients/http/toncenter/provider.py +0 -145
  85. tonutils/clients/http/toncenter/stack.py +0 -73
  86. tonutils/protocols/__init__.py +0 -9
  87. tonutils-2.0.1b2.dist-info/RECORD +0 -98
  88. /tonutils/{protocols/client.py → clients/protocol.py} +0 -0
  89. {tonutils-2.0.1b2.dist-info → tonutils-2.0.1b4.dist-info}/WHEEL +0 -0
  90. {tonutils-2.0.1b2.dist-info → tonutils-2.0.1b4.dist-info}/licenses/LICENSE +0 -0
  91. {tonutils-2.0.1b2.dist-info → tonutils-2.0.1b4.dist-info}/top_level.txt +0 -0
@@ -2,19 +2,33 @@ from __future__ import annotations
2
2
 
3
3
  import typing as t
4
4
 
5
- from pytoniq_core import Address, Transaction
5
+ from pytoniq_core import Address, BlockIdExt, Block, Transaction
6
6
 
7
7
  from tonutils.clients.adnl.provider import AdnlProvider
8
- from tonutils.clients.adnl.provider.config import TONClient
9
- from tonutils.clients.adnl.provider.limiter import PriorityLimiter
10
- from tonutils.clients.adnl.provider.models import LiteServer, GlobalConfig
11
- from tonutils.clients.adnl.stack import decode_stack, encode_stack
8
+ from tonutils.clients.adnl.provider.config import (
9
+ get_mainnet_global_config,
10
+ get_testnet_global_config,
11
+ )
12
+ from tonutils.clients.adnl.provider.models import (
13
+ LiteServer,
14
+ GlobalConfig,
15
+ MasterchainInfo,
16
+ )
17
+ from tonutils.clients.adnl.utils import decode_stack, encode_stack
12
18
  from tonutils.clients.base import BaseClient
13
- from tonutils.types import BinaryLike, ClientType, ContractStateInfo, NetworkGlobalID
19
+ from tonutils.clients.limiter import RateLimiter
20
+ from tonutils.types import (
21
+ BinaryLike,
22
+ ClientType,
23
+ ContractStateInfo,
24
+ NetworkGlobalID,
25
+ RetryPolicy,
26
+ WorkchainID,
27
+ )
14
28
 
15
29
 
16
- class AdnlClient(BaseClient):
17
- """TON blockchain client using ADNL lite-server as transport."""
30
+ class LiteClient(BaseClient):
31
+ """TON blockchain client for lite-server communication over ADNL provider."""
18
32
 
19
33
  TYPE = ClientType.ADNL
20
34
 
@@ -25,39 +39,40 @@ class AdnlClient(BaseClient):
25
39
  ip: t.Union[str, int],
26
40
  port: int,
27
41
  public_key: BinaryLike,
28
- timeout: int = 10,
42
+ connect_timeout: float = 2.0,
43
+ request_timeout: float = 10.0,
29
44
  rps_limit: t.Optional[int] = None,
30
45
  rps_period: float = 1.0,
31
- rps_retries: int = 2,
32
- limiter: t.Optional[PriorityLimiter] = None,
46
+ retry_policy: t.Optional[RetryPolicy] = None,
47
+ limiter: t.Optional[RateLimiter] = None,
33
48
  ) -> None:
34
49
  """
35
- Initialize ADNL client.
50
+ Initialize lite-server client.
36
51
 
37
52
  To obtain lite-server connection parameters (ip, port, public_key),
38
53
  it is recommended to use a private configuration for better stability
39
54
  and performance. You can obtain private lite-server configs from:
40
55
  - Tonconsole website: https://tonconsole.com/
41
56
  - dTON telegram bot: https://t.me/dtontech_bot (https://dton.io/)
57
+ Public free lite-server data may also be used, but may be unstable under load.
42
58
 
43
- Public free lite-server data may also be used via `from_network_config()`.
44
-
45
- :param network: Target TON network (mainnet or testnet)
59
+ :param network: Target TON network
46
60
  :param ip: Lite-server IP address or integer representation
47
61
  :param port: Lite-server port
48
62
  :param public_key: Lite-server ADNL public key
49
- :param timeout: Request timeout in seconds
50
- :param rps_limit: Optional requests-per-second limit
63
+ :param connect_timeout: Timeout in seconds for connect/handshake performed
64
+ by this client.
65
+ :param request_timeout: Timeout in seconds for a single request executed
66
+ by this client (one provider attempt).
67
+ :param rps_limit: Optional requests-per-second limit for this client
51
68
  :param rps_period: Time window in seconds for RPS limit
52
- :param rps_retries: Number of retries on rate limiting
53
- :param limiter: Optional pre-configured PriorityLimiter
69
+ :param retry_policy: Optional retry policy that defines per-error-code retry rules
70
+ :param limiter: Optional pre-configured RateLimiter (overrides rps_limit)
54
71
  """
55
72
  self.network: NetworkGlobalID = network
56
73
 
57
- if limiter is not None:
58
- limiter = limiter
59
- elif rps_limit is not None:
60
- limiter = PriorityLimiter(rps_limit, rps_period)
74
+ if limiter is None and rps_limit is not None:
75
+ limiter = RateLimiter(rps_limit, rps_period)
61
76
 
62
77
  self._provider: AdnlProvider = AdnlProvider(
63
78
  node=LiteServer(
@@ -65,9 +80,10 @@ class AdnlClient(BaseClient):
65
80
  port=port,
66
81
  id=public_key,
67
82
  ),
68
- timeout=timeout,
69
- rps_retries=rps_retries,
83
+ connect_timeout=connect_timeout,
84
+ request_timeout=request_timeout,
70
85
  limiter=limiter,
86
+ retry_policy=retry_policy,
71
87
  )
72
88
 
73
89
  @property
@@ -75,20 +91,20 @@ class AdnlClient(BaseClient):
75
91
  """
76
92
  Underlying ADNL provider.
77
93
 
78
- :return: AdnlProvider instance used for all ADNL requests
94
+ :return: AdnlProvider instance used for all lite-server requests
79
95
  """
80
96
  return self._provider
81
97
 
82
98
  @property
83
99
  def is_connected(self) -> bool:
84
100
  """
85
- Check whether ADNL transport is connected.
101
+ Check whether the lite-server connection is established.
86
102
 
87
103
  :return: True if connected, False otherwise
88
104
  """
89
105
  return self._provider.is_connected
90
106
 
91
- async def __aenter__(self) -> AdnlClient:
107
+ async def __aenter__(self) -> LiteClient:
92
108
  await self.connect()
93
109
  return self
94
110
 
@@ -107,57 +123,64 @@ class AdnlClient(BaseClient):
107
123
  network: NetworkGlobalID = NetworkGlobalID.MAINNET,
108
124
  config: t.Union[GlobalConfig, t.Dict[str, t.Any]],
109
125
  index: int,
110
- timeout: int = 10,
126
+ connect_timeout: float = 2.0,
127
+ request_timeout: float = 10.0,
111
128
  rps_limit: t.Optional[int] = None,
112
129
  rps_period: float = 1.0,
113
- rps_retries: int = 2,
114
- ) -> AdnlClient:
130
+ retry_policy: t.Optional[RetryPolicy] = None,
131
+ ) -> LiteClient:
115
132
  """
116
- Create ADNL client from a lite-server config.
133
+ Create lite-server client from a configuration.
117
134
 
118
- For best performance, it is recommended to use a private lite-server
119
- configuration. You can obtain private configs from:
135
+ To obtain lite-server connection parameters, it is recommended to use
136
+ a private lite-server configuration for better stability and performance.
137
+ You can obtain private lite-server configs from:
120
138
  - Tonconsole website: https://tonconsole.com/
121
139
  - dTON telegram bot: https://t.me/dtontech_bot (https://dton.io/)
122
140
 
123
- Public free configs may also be used via `from_network_config()`.
141
+ Public free configs may also be used, but may be unstable under load.
124
142
 
125
143
  :param network: Target TON network
126
144
  :param config: GlobalConfig instance or raw dict
127
- :param index: Index of lite-server
128
- :param timeout: Request timeout in seconds
129
- :param rps_limit: Optional requests-per-second limit
145
+ :param index: Index of lite-server entry in the configuration
146
+ :param connect_timeout: Timeout in seconds for connect/handshake performed
147
+ by this client.
148
+ :param request_timeout: Timeout in seconds for a single request executed
149
+ by this client (one provider attempt).
150
+ :param rps_limit: Optional requests-per-second limit for this client
130
151
  :param rps_period: Time window in seconds for RPS limit
131
- :param rps_retries: Number of retries on rate limiting
132
- :return: Configured AdnlClient instance
152
+ :param retry_policy: Optional retry policy that defines per-error-code retry rules
153
+ :return: Configured LiteClient instance
133
154
  """
134
155
  if isinstance(config, dict):
135
156
  config = GlobalConfig(**config)
136
- node = config.liteservers[index]
157
+ ls = config.liteservers[index]
137
158
  return cls(
138
159
  network=network,
139
- ip=node.host,
140
- port=node.port,
141
- public_key=node.id,
142
- timeout=timeout,
160
+ ip=ls.host,
161
+ port=ls.port,
162
+ public_key=ls.id,
163
+ connect_timeout=connect_timeout,
164
+ request_timeout=request_timeout,
143
165
  rps_limit=rps_limit,
144
166
  rps_period=rps_period,
145
- rps_retries=rps_retries,
167
+ retry_policy=retry_policy,
146
168
  )
147
169
 
148
170
  @classmethod
149
- async def from_network_config(
171
+ def from_network_config(
150
172
  cls,
151
173
  *,
152
174
  network: NetworkGlobalID = NetworkGlobalID.MAINNET,
153
175
  index: int,
154
- timeout: int = 10,
176
+ connect_timeout: float = 2.0,
177
+ request_timeout: float = 10.0,
155
178
  rps_limit: t.Optional[int] = None,
156
179
  rps_period: float = 1.0,
157
- rps_retries: int = 2,
158
- ) -> AdnlClient:
180
+ retry_policy: t.Optional[RetryPolicy] = None,
181
+ ) -> LiteClient:
159
182
  """
160
- Create ADNL client using global network config fetched from ton.org.
183
+ Create lite-server client using global network configuration fetched from ton.org.
161
184
 
162
185
  Public lite-servers available in the global network configuration are
163
186
  free to use but may be unstable under load. For higher reliability and
@@ -167,28 +190,30 @@ class AdnlClient(BaseClient):
167
190
  - dTON telegram bot: https://t.me/dtontech_bot (https://dton.io/)
168
191
 
169
192
  :param network: Target TON network
170
- :param index: Index of lite-server
171
- :param timeout: Request timeout in seconds
172
- :param rps_limit: Optional requests-per-second limit
193
+ :param index: Index of lite-server entry in the global configuration
194
+ :param connect_timeout: Timeout in seconds for connect/handshake performed
195
+ by this client.
196
+ :param request_timeout: Timeout in seconds for a single request executed
197
+ by this client (one provider attempt).
198
+ :param rps_limit: Optional requests-per-second limit for this client
173
199
  :param rps_period: Time window in seconds for RPS limit
174
- :param rps_retries: Number of retries on rate limiting
175
- :return: Configured AdnlClient instance
200
+ :param retry_policy: Optional retry policy that defines per-error-code retry rules
201
+ :return: Configured LiteClient instance
176
202
  """
177
- ton_client = TONClient()
178
203
  config_getters = {
179
- NetworkGlobalID.MAINNET: ton_client.mainnet_global_config,
180
- NetworkGlobalID.TESTNET: ton_client.testnet_global_config,
204
+ NetworkGlobalID.MAINNET: get_mainnet_global_config,
205
+ NetworkGlobalID.TESTNET: get_testnet_global_config,
181
206
  }
182
- async with ton_client:
183
- config = await config_getters[network]()
207
+ config = config_getters[network]()
184
208
  return cls.from_config(
185
209
  network=network,
186
210
  config=config,
187
211
  index=index,
188
- timeout=timeout,
212
+ connect_timeout=connect_timeout,
213
+ request_timeout=request_timeout,
189
214
  rps_limit=rps_limit,
190
215
  rps_period=rps_period,
191
- rps_retries=rps_retries,
216
+ retry_policy=retry_policy,
192
217
  )
193
218
 
194
219
  async def _send_boc(self, boc: str) -> None:
@@ -215,7 +240,7 @@ class AdnlClient(BaseClient):
215
240
 
216
241
  curr_lt = state.last_transaction_lt
217
242
  curr_hash = state.last_transaction_hash
218
- transactions: list[Transaction] = []
243
+ transactions: t.List[Transaction] = []
219
244
 
220
245
  while len(transactions) < limit and curr_lt != 0:
221
246
  batch_size = min(16, limit - len(transactions))
@@ -230,7 +255,7 @@ class AdnlClient(BaseClient):
230
255
  break
231
256
 
232
257
  if to_lt > 0 and txs[-1].lt <= to_lt:
233
- trimmed: list[Transaction] = []
258
+ trimmed: t.List[Transaction] = []
234
259
  for tx in txs:
235
260
  if tx.lt <= to_lt:
236
261
  break
@@ -264,7 +289,7 @@ class AdnlClient(BaseClient):
264
289
  return decode_stack(result or [])
265
290
 
266
291
  async def connect(self) -> None:
267
- """Ensure that ADNL connection is established."""
292
+ """Establish connection to the lite-server."""
268
293
  await self.provider.connect()
269
294
 
270
295
  async def reconnect(self) -> None:
@@ -272,5 +297,116 @@ class AdnlClient(BaseClient):
272
297
  await self.provider.reconnect()
273
298
 
274
299
  async def close(self) -> None:
275
- """Close ADNL connection."""
300
+ """Close the lite-server connection."""
276
301
  await self.provider.close()
302
+
303
+ async def get_time(self) -> int:
304
+ """
305
+ Fetch current network time from lite-server.
306
+
307
+ :return: Current UNIX timestamp
308
+ """
309
+ return await self.provider.get_time()
310
+
311
+ async def get_version(self) -> int:
312
+ """
313
+ Fetch lite-server protocol version.
314
+
315
+ :return: Version number
316
+ """
317
+ return await self.provider.get_version()
318
+
319
+ async def wait_masterchain_seqno(
320
+ self,
321
+ seqno: int,
322
+ timeout_ms: int,
323
+ schema_name: str,
324
+ data: t.Optional[dict] = None,
325
+ ) -> dict:
326
+ """
327
+ Combine waitMasterchainSeqno with another lite-server query.
328
+
329
+ :param seqno: Masterchain seqno to wait for
330
+ :param timeout_ms: Wait timeout in milliseconds
331
+ :param schema_name: Lite-server TL method name without prefix
332
+ :param data: Additional method arguments
333
+ :return: Lite-server response as dictionary
334
+ """
335
+ return await self.provider.wait_masterchain_seqno(
336
+ seqno=seqno,
337
+ timeout_ms=timeout_ms,
338
+ schema_name=schema_name,
339
+ data=data,
340
+ )
341
+
342
+ async def get_masterchain_info(self) -> MasterchainInfo:
343
+ """
344
+ Fetch basic masterchain information.
345
+
346
+ :return: MasterchainInfo instance
347
+ """
348
+ return await self.provider.get_masterchain_info()
349
+
350
+ async def lookup_block(
351
+ self,
352
+ workchain: WorkchainID,
353
+ shard: int,
354
+ seqno: t.Optional[int] = None,
355
+ lt: t.Optional[int] = None,
356
+ utime: t.Optional[int] = None,
357
+ ) -> t.Tuple[BlockIdExt, Block]:
358
+ """
359
+ Locate a block by workchain/shard and one of seqno/lt/utime.
360
+
361
+ :param workchain: Workchain identifier
362
+ :param shard: Shard identifier
363
+ :param seqno: Block sequence number
364
+ :param lt: Logical time filter
365
+ :param utime: UNIX time filter
366
+ :return: Tuple of BlockIdExt and deserialized Block
367
+ """
368
+ return await self.provider.lookup_block(
369
+ workchain=workchain,
370
+ shard=shard,
371
+ seqno=seqno,
372
+ lt=lt,
373
+ utime=utime,
374
+ )
375
+
376
+ async def get_block_header(
377
+ self,
378
+ block: BlockIdExt,
379
+ ) -> t.Tuple[BlockIdExt, Block]:
380
+ """
381
+ Fetch and deserialize block header by BlockIdExt.
382
+
383
+ :param block: BlockIdExt to query
384
+ :return: Tuple of BlockIdExt and deserialized Block
385
+ """
386
+ return await self.provider.get_block_header(block)
387
+
388
+ async def get_block_transactions_ext(
389
+ self,
390
+ block: BlockIdExt,
391
+ count: int = 1024,
392
+ ) -> t.List[Transaction]:
393
+ """
394
+ Fetch extended block transactions list.
395
+
396
+ :param block: Target block identifier
397
+ :param count: Maximum number of transactions per request
398
+ :return: List of deserialized Transaction objects
399
+ """
400
+ return await self.provider.get_block_transactions_ext(block, count=count)
401
+
402
+ async def get_all_shards_info(
403
+ self,
404
+ block: t.Optional[BlockIdExt] = None,
405
+ ) -> t.List[BlockIdExt]:
406
+ """
407
+ Fetch shard info for all workchains at a given masterchain block.
408
+
409
+ :param block: Masterchain block ID or None to use latest
410
+ :return: List of shard BlockIdExt objects
411
+ """
412
+ return await self.provider.get_all_shards_info(block)
@@ -1,34 +1,33 @@
1
- from pyapiq import AsyncClientAPI, async_endpoint
2
- from pyapiq.types import HTTPMethod
1
+ import json
2
+ import urllib.request
3
+ from pathlib import Path
3
4
 
4
5
  from tonutils.clients.adnl.provider.models import GlobalConfig
5
6
 
6
7
 
7
- class TONClient(AsyncClientAPI):
8
- """Minimal HTTP client for fetching TON global configuration files."""
8
+ def load_global_config(source: str) -> GlobalConfig:
9
+ if source.startswith(("http://", "https://")):
10
+ with urllib.request.urlopen(source) as response:
11
+ data = json.loads(response.read().decode())
12
+ else:
13
+ data = json.loads(Path(source).read_text())
9
14
 
10
- base_url = "https://ton.org/"
15
+ return GlobalConfig.model_validate(data)
11
16
 
12
- @async_endpoint(
13
- HTTPMethod.GET,
14
- path="global-config.json",
15
- return_as=GlobalConfig,
16
- )
17
- async def mainnet_global_config(self) -> GlobalConfig: # type: ignore[empty-body]
18
- """
19
- Fetch mainnet global configuration.
20
17
 
21
- :return: Parsed GlobalConfig instance
22
- """
18
+ def get_mainnet_global_config() -> GlobalConfig:
19
+ """
20
+ Fetch mainnet global configuration.
23
21
 
24
- @async_endpoint(
25
- HTTPMethod.GET,
26
- path="testnet-global-config.json",
27
- return_as=GlobalConfig,
28
- )
29
- async def testnet_global_config(self) -> GlobalConfig: # type: ignore[empty-body]
30
- """
31
- Fetch testnet global configuration.
22
+ :return: Parsed GlobalConfig instance
23
+ """
24
+ return load_global_config("https://ton.org/global-config.json")
32
25
 
33
- :return: Parsed GlobalConfig instance
34
- """
26
+
27
+ def get_testnet_global_config() -> GlobalConfig:
28
+ """
29
+ Fetch testnet global configuration.
30
+
31
+ :return: Parsed GlobalConfig instance
32
+ """
33
+ return load_global_config("https://ton.org/testnet-global-config.json")
@@ -66,6 +66,10 @@ class LiteServer(BaseModel):
66
66
  return socket.inet_ntoa(packed_id)
67
67
  return str(self.ip)
68
68
 
69
+ @property
70
+ def endpoint(self) -> str:
71
+ return f"{self.host}:{self.port}"
72
+
69
73
 
70
74
  class Block(BaseModel):
71
75
  """