tonutils 2.0.1b5__tar.gz → 2.0.1b6__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 (127) hide show
  1. {tonutils-2.0.1b5/tonutils.egg-info → tonutils-2.0.1b6}/PKG-INFO +1 -1
  2. tonutils-2.0.1b6/tonutils/__meta__.py +1 -0
  3. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/__init__.py +10 -10
  4. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/balancer.py +21 -24
  5. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/client.py +21 -24
  6. tonutils-2.0.1b6/tonutils/clients/adnl/provider/config.py +48 -0
  7. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/base.py +17 -11
  8. tonutils-2.0.1b6/tonutils/clients/http/__init__.py +23 -0
  9. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/http/balancer.py +11 -11
  10. tonutils-2.0.1b6/tonutils/clients/http/clients/__init__.py +13 -0
  11. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/http/clients/chainstack.py +3 -3
  12. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/http/clients/quicknode.py +2 -3
  13. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/http/clients/tatum.py +3 -3
  14. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/http/clients/tonapi.py +9 -10
  15. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/http/clients/toncenter.py +50 -23
  16. {tonutils-2.0.1b5/tonutils/clients/http/providers → tonutils-2.0.1b6/tonutils/clients/http/provider}/__init__.py +4 -1
  17. {tonutils-2.0.1b5/tonutils/clients/http/providers → tonutils-2.0.1b6/tonutils/clients/http/provider}/base.py +71 -7
  18. {tonutils-2.0.1b5/tonutils/clients/http/providers/toncenter → tonutils-2.0.1b6/tonutils/clients/http/provider}/models.py +43 -1
  19. tonutils-2.0.1b5/tonutils/clients/http/providers/tonapi/provider.py → tonutils-2.0.1b6/tonutils/clients/http/provider/tonapi.py +8 -8
  20. tonutils-2.0.1b5/tonutils/clients/http/providers/toncenter/provider.py → tonutils-2.0.1b6/tonutils/clients/http/provider/toncenter.py +22 -14
  21. tonutils-2.0.1b6/tonutils/clients/limiter.py +117 -0
  22. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/protocol.py +2 -2
  23. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/base.py +2 -3
  24. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/messages.py +4 -8
  25. tonutils-2.0.1b6/tonutils/tonconnect/bridge/__init__.py +0 -0
  26. tonutils-2.0.1b6/tonutils/tonconnect/events.py +0 -0
  27. tonutils-2.0.1b6/tonutils/tonconnect/models/__init__.py +0 -0
  28. tonutils-2.0.1b6/tonutils/tonconnect/storage.py +0 -0
  29. tonutils-2.0.1b6/tonutils/tonconnect/tonconnect.py +0 -0
  30. tonutils-2.0.1b6/tonutils/tools/block_scanner/__init__.py +9 -0
  31. tonutils-2.0.1b6/tonutils/tools/block_scanner/events.py +72 -0
  32. tonutils-2.0.1b6/tonutils/tools/block_scanner/scanner.py +407 -0
  33. tonutils-2.0.1b6/tonutils/tools/block_scanner/storage.py +11 -0
  34. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/utils.py +0 -48
  35. {tonutils-2.0.1b5 → tonutils-2.0.1b6/tonutils.egg-info}/PKG-INFO +1 -1
  36. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils.egg-info/SOURCES.txt +11 -13
  37. tonutils-2.0.1b5/tonutils/__meta__.py +0 -1
  38. tonutils-2.0.1b5/tonutils/clients/adnl/provider/config.py +0 -33
  39. tonutils-2.0.1b5/tonutils/clients/http/__init__.py +0 -23
  40. tonutils-2.0.1b5/tonutils/clients/http/clients/__init__.py +0 -13
  41. tonutils-2.0.1b5/tonutils/clients/http/providers/response.py +0 -85
  42. tonutils-2.0.1b5/tonutils/clients/http/providers/tonapi/__init__.py +0 -3
  43. tonutils-2.0.1b5/tonutils/clients/http/providers/tonapi/models.py +0 -47
  44. tonutils-2.0.1b5/tonutils/clients/http/providers/toncenter/__init__.py +0 -3
  45. tonutils-2.0.1b5/tonutils/clients/limiter.py +0 -115
  46. tonutils-2.0.1b5/tonutils/tools/block_scanner/__init__.py +0 -16
  47. tonutils-2.0.1b5/tonutils/tools/block_scanner/annotations.py +0 -23
  48. tonutils-2.0.1b5/tonutils/tools/block_scanner/dispatcher.py +0 -141
  49. tonutils-2.0.1b5/tonutils/tools/block_scanner/events.py +0 -31
  50. tonutils-2.0.1b5/tonutils/tools/block_scanner/scanner.py +0 -313
  51. tonutils-2.0.1b5/tonutils/tools/block_scanner/traversal.py +0 -97
  52. tonutils-2.0.1b5/tonutils/tools/block_scanner/where.py +0 -53
  53. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/LICENSE +0 -0
  54. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/README.md +0 -0
  55. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/pyproject.toml +0 -0
  56. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/setup.cfg +0 -0
  57. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/__init__.py +0 -0
  58. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/cli.py +0 -0
  59. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/__init__.py +0 -0
  60. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/provider/__init__.py +0 -0
  61. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/provider/models.py +0 -0
  62. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/provider/provider.py +0 -0
  63. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/provider/transport.py +0 -0
  64. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/provider/workers/__init__.py +0 -0
  65. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/provider/workers/base.py +0 -0
  66. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/provider/workers/pinger.py +0 -0
  67. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/provider/workers/reader.py +0 -0
  68. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/provider/workers/updater.py +0 -0
  69. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/adnl/utils.py +0 -0
  70. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/clients/http/utils.py +0 -0
  71. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/__init__.py +0 -0
  72. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/base.py +0 -0
  73. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/codes.py +0 -0
  74. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/dns/__init__.py +0 -0
  75. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/dns/collection.py +0 -0
  76. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/dns/item.py +0 -0
  77. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/dns/methods.py +0 -0
  78. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/dns/tlb.py +0 -0
  79. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/jetton/__init__.py +0 -0
  80. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/jetton/master.py +0 -0
  81. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/jetton/methods.py +0 -0
  82. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/jetton/tlb.py +0 -0
  83. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/jetton/wallet.py +0 -0
  84. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/nft/__init__.py +0 -0
  85. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/nft/collection.py +0 -0
  86. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/nft/item.py +0 -0
  87. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/nft/methods.py +0 -0
  88. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/nft/tlb.py +0 -0
  89. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/opcodes.py +0 -0
  90. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/protocol.py +0 -0
  91. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/telegram/__init__.py +0 -0
  92. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/telegram/collection.py +0 -0
  93. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/telegram/item.py +0 -0
  94. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/telegram/methods.py +0 -0
  95. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/telegram/tlb.py +0 -0
  96. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/vanity/__init__.py +0 -0
  97. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/vanity/models.py +0 -0
  98. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/vanity/tlb.py +0 -0
  99. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/vanity/vanity.py +0 -0
  100. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/versions.py +0 -0
  101. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/__init__.py +0 -0
  102. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/configs.py +0 -0
  103. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/methods.py +0 -0
  104. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/params.py +0 -0
  105. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/protocol.py +0 -0
  106. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/tlb.py +0 -0
  107. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/versions/__init__.py +0 -0
  108. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/versions/hw.py +0 -0
  109. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/versions/pp.py +0 -0
  110. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/versions/v1.py +0 -0
  111. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/versions/v2.py +0 -0
  112. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/versions/v3.py +0 -0
  113. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/versions/v4.py +0 -0
  114. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/contracts/wallet/versions/v5.py +0 -0
  115. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/exceptions.py +0 -0
  116. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/py.typed +0 -0
  117. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/tonconnect/__init__.py +0 -0
  118. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/tools/__init__.py +0 -0
  119. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/tools/status_monitor/__init__.py +0 -0
  120. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/tools/status_monitor/console.py +0 -0
  121. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/tools/status_monitor/models.py +0 -0
  122. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/tools/status_monitor/monitor.py +0 -0
  123. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils/types.py +0 -0
  124. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils.egg-info/dependency_links.txt +0 -0
  125. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils.egg-info/entry_points.txt +0 -0
  126. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils.egg-info/requires.txt +0 -0
  127. {tonutils-2.0.1b5 → tonutils-2.0.1b6}/tonutils.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tonutils
3
- Version: 2.0.1b5
3
+ Version: 2.0.1b6
4
4
  Summary: Tonutils is a high-level, object-oriented Python library designed to facilitate seamless interactions with the TON blockchain.
5
5
  Author: nessshon
6
6
  Maintainer: nessshon
@@ -0,0 +1 @@
1
+ __version__ = "2.0.1b6"
@@ -5,12 +5,12 @@ from .adnl import (
5
5
  )
6
6
  from .http import (
7
7
  HttpBalancer,
8
- ChainstackHttpClient,
9
- QuicknodeHttpClient,
10
- TatumHttpClient,
11
- TonapiHttpClient,
8
+ ChainstackClient,
9
+ QuicknodeClient,
10
+ TatumClient,
11
+ TonapiClient,
12
12
  TonapiHttpProvider,
13
- ToncenterHttpClient,
13
+ ToncenterClient,
14
14
  ToncenterHttpProvider,
15
15
  )
16
16
 
@@ -19,11 +19,11 @@ __all__ = [
19
19
  "LiteClient",
20
20
  "AdnlProvider",
21
21
  "HttpBalancer",
22
- "ChainstackHttpClient",
23
- "QuicknodeHttpClient",
24
- "TatumHttpClient",
25
- "TonapiHttpClient",
22
+ "ChainstackClient",
23
+ "QuicknodeClient",
24
+ "TatumClient",
25
+ "TonapiClient",
26
26
  "TonapiHttpProvider",
27
- "ToncenterHttpClient",
27
+ "ToncenterClient",
28
28
  "ToncenterHttpProvider",
29
29
  ]
@@ -64,8 +64,8 @@ class LiteBalancer(BaseClient):
64
64
 
65
65
  def __init__(
66
66
  self,
67
- *,
68
67
  network: NetworkGlobalID = NetworkGlobalID.MAINNET,
68
+ *,
69
69
  clients: t.List[LiteClient],
70
70
  connect_timeout: float = 2.0,
71
71
  request_timeout: float = 12.0,
@@ -206,8 +206,8 @@ class LiteBalancer(BaseClient):
206
206
  @classmethod
207
207
  def from_config(
208
208
  cls,
209
- *,
210
209
  network: NetworkGlobalID = NetworkGlobalID.MAINNET,
210
+ *,
211
211
  config: t.Union[GlobalConfig, t.Dict[str, t.Any]],
212
212
  connect_timeout: float = 2.0,
213
213
  request_timeout: float = 12.0,
@@ -285,8 +285,8 @@ class LiteBalancer(BaseClient):
285
285
  @classmethod
286
286
  def from_network_config(
287
287
  cls,
288
- *,
289
288
  network: NetworkGlobalID = NetworkGlobalID.MAINNET,
289
+ *,
290
290
  connect_timeout: float = 2.0,
291
291
  request_timeout: float = 12.0,
292
292
  client_connect_timeout: float = 1.5,
@@ -513,13 +513,14 @@ class LiteBalancer(BaseClient):
513
513
 
514
514
  return await self._with_failover(_call)
515
515
 
516
- async def _get_contract_transactions(
516
+ async def _get_transactions(
517
517
  self,
518
518
  address: str,
519
519
  limit: int = 100,
520
520
  from_lt: t.Optional[int] = None,
521
- to_lt: int = 0,
521
+ to_lt: t.Optional[int] = None,
522
522
  ) -> t.List[Transaction]:
523
+ to_lt = 0 if to_lt is None else to_lt
523
524
  state = await self._get_contract_info(address)
524
525
  account = Address(address).to_tl_account_id()
525
526
 
@@ -530,41 +531,37 @@ class LiteBalancer(BaseClient):
530
531
  curr_hash = state.last_transaction_hash
531
532
  transactions: t.List[Transaction] = []
532
533
 
533
- while len(transactions) < limit and curr_lt != 0:
534
- batch_size = min(16, limit - len(transactions))
534
+ while curr_lt != 0:
535
+ fetch_lt = curr_lt
536
+ fetch_hash = curr_hash
535
537
 
536
538
  async def _call(provider: AdnlProvider) -> t.List[Transaction]:
537
539
  return await provider.get_transactions(
538
540
  account=account,
539
- count=batch_size,
540
- from_lt=curr_lt,
541
- from_hash=curr_hash,
541
+ count=16,
542
+ from_lt=fetch_lt,
543
+ from_hash=fetch_hash,
542
544
  )
543
545
 
544
546
  txs = await self._with_failover(_call)
545
547
  if not txs:
546
548
  break
547
549
 
548
- if to_lt > 0 and txs[-1].lt <= to_lt:
549
- trimmed: t.List[Transaction] = []
550
- for tx in txs:
551
- if tx.lt <= to_lt:
552
- break
553
- trimmed.append(tx)
554
- transactions.extend(trimmed)
555
- break
550
+ for tx in txs:
551
+ if from_lt is not None and tx.lt > from_lt:
552
+ continue
553
+ if to_lt > 0 and tx.lt <= to_lt:
554
+ return transactions[:limit]
556
555
 
557
- transactions.extend(txs)
556
+ transactions.append(tx)
557
+ if len(transactions) >= limit:
558
+ return transactions
558
559
 
559
560
  last_tx = txs[-1]
560
561
  curr_lt = last_tx.prev_trans_lt
561
562
  curr_hash = last_tx.prev_trans_hash.hex()
562
563
 
563
- return (
564
- [tx for tx in transactions if tx.lt < from_lt]
565
- if from_lt is not None
566
- else transactions
567
- )
564
+ return transactions[:limit]
568
565
 
569
566
  async def _run_get_method(
570
567
  self,
@@ -34,8 +34,8 @@ class LiteClient(BaseClient):
34
34
 
35
35
  def __init__(
36
36
  self,
37
- *,
38
37
  network: NetworkGlobalID = NetworkGlobalID.MAINNET,
38
+ *,
39
39
  ip: t.Union[str, int],
40
40
  port: int,
41
41
  public_key: BinaryLike,
@@ -119,8 +119,8 @@ class LiteClient(BaseClient):
119
119
  @classmethod
120
120
  def from_config(
121
121
  cls,
122
- *,
123
122
  network: NetworkGlobalID = NetworkGlobalID.MAINNET,
123
+ *,
124
124
  config: t.Union[GlobalConfig, t.Dict[str, t.Any]],
125
125
  index: int,
126
126
  connect_timeout: float = 2.0,
@@ -170,8 +170,8 @@ class LiteClient(BaseClient):
170
170
  @classmethod
171
171
  def from_network_config(
172
172
  cls,
173
- *,
174
173
  network: NetworkGlobalID = NetworkGlobalID.MAINNET,
174
+ *,
175
175
  index: int,
176
176
  connect_timeout: float = 2.0,
177
177
  request_timeout: float = 10.0,
@@ -225,13 +225,14 @@ class LiteClient(BaseClient):
225
225
  async def _get_contract_info(self, address: str) -> ContractStateInfo:
226
226
  return await self.provider.get_account_state(Address(address))
227
227
 
228
- async def _get_contract_transactions(
228
+ async def _get_transactions(
229
229
  self,
230
230
  address: str,
231
231
  limit: int = 100,
232
232
  from_lt: t.Optional[int] = None,
233
- to_lt: int = 0,
233
+ to_lt: t.Optional[int] = None,
234
234
  ) -> t.List[Transaction]:
235
+ to_lt = 0 if to_lt is None else to_lt
235
236
  state = await self._get_contract_info(address)
236
237
  account = Address(address).to_tl_account_id()
237
238
 
@@ -242,38 +243,34 @@ class LiteClient(BaseClient):
242
243
  curr_hash = state.last_transaction_hash
243
244
  transactions: t.List[Transaction] = []
244
245
 
245
- while len(transactions) < limit and curr_lt != 0:
246
- batch_size = min(16, limit - len(transactions))
246
+ while curr_lt != 0:
247
+ fetch_lt = curr_lt
248
+ fetch_hash = curr_hash
247
249
 
248
250
  txs = await self.provider.get_transactions(
249
251
  account=account,
250
- count=batch_size,
251
- from_lt=curr_lt,
252
- from_hash=curr_hash,
252
+ count=16,
253
+ from_lt=fetch_lt,
254
+ from_hash=fetch_hash,
253
255
  )
254
256
  if not txs:
255
257
  break
256
258
 
257
- if to_lt > 0 and txs[-1].lt <= to_lt:
258
- trimmed: t.List[Transaction] = []
259
- for tx in txs:
260
- if tx.lt <= to_lt:
261
- break
262
- trimmed.append(tx)
263
- transactions.extend(trimmed)
264
- break
259
+ for tx in txs:
260
+ if from_lt is not None and tx.lt > from_lt:
261
+ continue
262
+ if to_lt > 0 and tx.lt <= to_lt:
263
+ return transactions[:limit]
265
264
 
266
- transactions.extend(txs)
265
+ transactions.append(tx)
266
+ if len(transactions) >= limit:
267
+ return transactions
267
268
 
268
269
  last_tx = txs[-1]
269
270
  curr_lt = last_tx.prev_trans_lt
270
271
  curr_hash = last_tx.prev_trans_hash.hex()
271
272
 
272
- return (
273
- [tx for tx in transactions if tx.lt < from_lt]
274
- if from_lt is not None
275
- else transactions
276
- )
273
+ return transactions[:limit]
277
274
 
278
275
  async def _run_get_method(
279
276
  self,
@@ -0,0 +1,48 @@
1
+ import json
2
+ import urllib.request
3
+ from pathlib import Path
4
+ from urllib.error import HTTPError, URLError
5
+
6
+ from pydantic import ValidationError
7
+
8
+ from tonutils.clients.adnl.provider.models import GlobalConfig
9
+
10
+
11
+ def load_global_config(source: str) -> GlobalConfig:
12
+ try:
13
+ if source.startswith(("http://", "https://")):
14
+ with urllib.request.urlopen(source) as r:
15
+ data = json.loads(r.read().decode("utf-8"))
16
+ else:
17
+ data = json.loads(Path(source).read_text(encoding="utf-8"))
18
+ return GlobalConfig.model_validate(data)
19
+ except HTTPError as e:
20
+ raise RuntimeError(f"Config fetch failed: {e} ({source})") from e
21
+ except URLError as e:
22
+ raise RuntimeError(f"Config fetch failed: {e.reason} ({source})") from e
23
+ except json.JSONDecodeError as e:
24
+ raise RuntimeError(f"Config JSON is invalid: {e.msg} ({source})") from e
25
+ except ValidationError as e:
26
+ raise RuntimeError(f"Config validation failed: {e} ({source})") from e
27
+ except OSError as e:
28
+ raise RuntimeError(f"Config read failed: {e} ({source})") from e
29
+ except Exception as e:
30
+ raise RuntimeError(f"Config load failed: {e} ({source})") from e
31
+
32
+
33
+ def get_mainnet_global_config() -> GlobalConfig:
34
+ """
35
+ Fetch mainnet global configuration.
36
+
37
+ :return: Parsed GlobalConfig instance
38
+ """
39
+ return load_global_config("https://ton.org/global-config.json")
40
+
41
+
42
+ def get_testnet_global_config() -> GlobalConfig:
43
+ """
44
+ Fetch testnet global configuration.
45
+
46
+ :return: Parsed GlobalConfig instance
47
+ """
48
+ return load_global_config("https://ton.org/testnet-global-config.json")
@@ -98,20 +98,23 @@ class BaseClient(abc.ABC):
98
98
  raise NotImplementedError
99
99
 
100
100
  @abc.abstractmethod
101
- async def _get_contract_transactions(
101
+ async def _get_transactions(
102
102
  self,
103
103
  address: str,
104
104
  limit: int = 100,
105
105
  from_lt: t.Optional[int] = None,
106
- to_lt: int = 0,
106
+ to_lt: t.Optional[int] = None,
107
107
  ) -> t.List[Transaction]:
108
108
  """
109
- Fetch a list of recent contract transactions from the provider.
109
+ Fetch transaction history for a contract.
110
+ Returns transactions in the range (to_lt, from_lt), ordered from newest to oldest.
110
111
 
111
- :param address: Contract address in raw
112
+ :param address: Contract address as string
112
113
  :param limit: Maximum number of transactions to return
113
- :param from_lt: Optional lower bound (exclusive) logical time
114
- :param to_lt: Upper bound (inclusive) logical time, 0 means latest
114
+ :param from_lt: Upper bound logical time (inclusive).
115
+ If None, starts from the most recent transaction.
116
+ :param to_lt: Lower bound logical time (exclusive).
117
+ If None or 0, no lower bound is applied.
115
118
  :return: List of Transaction objects ordered from newest to oldest
116
119
  """
117
120
  raise NotImplementedError
@@ -180,25 +183,28 @@ class BaseClient(abc.ABC):
180
183
  address = Address(address).to_str(is_user_friendly=False)
181
184
  return await self._get_contract_info(address=address)
182
185
 
183
- async def get_contract_transactions(
186
+ async def get_transactions(
184
187
  self,
185
188
  address: AddressLike,
186
189
  limit: int = 100,
187
190
  from_lt: t.Optional[int] = None,
188
- to_lt: int = 0,
191
+ to_lt: t.Optional[int] = None,
189
192
  ) -> t.List[Transaction]:
190
193
  """
191
194
  Fetch transaction history for a contract.
195
+ Returns transactions in the range (to_lt, from_lt), ordered from newest to oldest.
192
196
 
193
197
  :param address: Contract address as Address object or string
194
198
  :param limit: Maximum number of transactions to return
195
- :param from_lt: Optional lower bound (exclusive) logical time
196
- :param to_lt: Upper bound (inclusive) logical time, 0 means latest
199
+ :param from_lt: Upper bound logical time (inclusive).
200
+ If None, starts from the most recent transaction.
201
+ :param to_lt: Lower bound logical time (exclusive).
202
+ If None or 0, no lower bound is applied.
197
203
  :return: List of Transaction objects ordered from newest to oldest
198
204
  """
199
205
  if isinstance(address, Address):
200
206
  address = Address(address).to_str(is_user_friendly=False)
201
- return await self._get_contract_transactions(
207
+ return await self._get_transactions(
202
208
  address=address,
203
209
  limit=limit,
204
210
  from_lt=from_lt,
@@ -0,0 +1,23 @@
1
+ from .balancer import HttpBalancer
2
+ from .clients import (
3
+ ChainstackClient,
4
+ QuicknodeClient,
5
+ TatumClient,
6
+ TonapiClient,
7
+ ToncenterClient,
8
+ )
9
+ from .provider import (
10
+ TonapiHttpProvider,
11
+ ToncenterHttpProvider,
12
+ )
13
+
14
+ __all__ = [
15
+ "HttpBalancer",
16
+ "ChainstackClient",
17
+ "QuicknodeClient",
18
+ "TatumClient",
19
+ "TonapiClient",
20
+ "TonapiHttpProvider",
21
+ "ToncenterClient",
22
+ "ToncenterHttpProvider",
23
+ ]
@@ -10,7 +10,7 @@ from itertools import cycle
10
10
  from pytoniq_core import Transaction
11
11
 
12
12
  from tonutils.clients.base import BaseClient
13
- from tonutils.clients.http.clients.quicknode import QuicknodeHttpClient
13
+ from tonutils.clients.http.clients.quicknode import QuicknodeClient
14
14
  from tonutils.exceptions import (
15
15
  BalancerError,
16
16
  ClientError,
@@ -50,8 +50,8 @@ class HttpBalancer(BaseClient):
50
50
 
51
51
  def __init__(
52
52
  self,
53
- *,
54
53
  network: NetworkGlobalID = NetworkGlobalID.MAINNET,
54
+ *,
55
55
  clients: t.List[BaseClient],
56
56
  request_timeout: float = 12.0,
57
57
  ) -> None:
@@ -60,15 +60,15 @@ class HttpBalancer(BaseClient):
60
60
 
61
61
  Each supported HTTP client requires its own credentials or endpoint
62
62
  configuration. You can obtain them from the corresponding provider:
63
- - ToncenterHttpClient:
63
+ - ToncenterClient:
64
64
  API key available via Telegram bot: https://t.me/toncenter
65
- - TonapiHttpClient:
65
+ - TonapiClient:
66
66
  API key available on the Tonconsole website: https://tonconsole.com/
67
- - ChainstackHttpClient:
67
+ - ChainstackClient:
68
68
  Personal endpoint available on: https://chainstack.com/
69
- - QuicknodeHttpClient:
69
+ - QuicknodeClient:
70
70
  Personal endpoint available on: https://www.quicknode.com/
71
- - TatumHttpClient:
71
+ - TatumClient:
72
72
  API key available on: https://tatum.io/
73
73
 
74
74
  :param network: Target TON network (mainnet or testnet)
@@ -102,7 +102,7 @@ class HttpBalancer(BaseClient):
102
102
  )
103
103
 
104
104
  if (
105
- isinstance(client, QuicknodeHttpClient)
105
+ isinstance(client, QuicknodeClient)
106
106
  and self.network == NetworkGlobalID.TESTNET
107
107
  ):
108
108
  raise ClientError(
@@ -356,15 +356,15 @@ class HttpBalancer(BaseClient):
356
356
 
357
357
  return await self._with_failover(_call)
358
358
 
359
- async def _get_contract_transactions(
359
+ async def _get_transactions(
360
360
  self,
361
361
  address: str,
362
362
  limit: int = 100,
363
363
  from_lt: t.Optional[int] = None,
364
- to_lt: int = 0,
364
+ to_lt: t.Optional[int] = None,
365
365
  ) -> t.List[Transaction]:
366
366
  async def _call(client: BaseClient) -> t.List[Transaction]:
367
- return await client._get_contract_transactions(
367
+ return await client._get_transactions(
368
368
  address=address,
369
369
  limit=limit,
370
370
  from_lt=from_lt,
@@ -0,0 +1,13 @@
1
+ from .chainstack import ChainstackClient
2
+ from .quicknode import QuicknodeClient
3
+ from .tatum import TatumClient
4
+ from .tonapi import TonapiClient
5
+ from .toncenter import ToncenterClient
6
+
7
+ __all__ = [
8
+ "ChainstackClient",
9
+ "QuicknodeClient",
10
+ "TatumClient",
11
+ "TonapiClient",
12
+ "ToncenterClient",
13
+ ]
@@ -2,16 +2,16 @@ import typing as t
2
2
 
3
3
  from aiohttp import ClientSession
4
4
 
5
- from tonutils.clients.http.clients.toncenter import ToncenterHttpClient
5
+ from tonutils.clients.http.clients.toncenter import ToncenterClient
6
6
  from tonutils.types import NetworkGlobalID, RetryPolicy
7
7
 
8
8
 
9
- class ChainstackHttpClient(ToncenterHttpClient):
9
+ class ChainstackClient(ToncenterClient):
10
10
 
11
11
  def __init__(
12
12
  self,
13
- *,
14
13
  network: NetworkGlobalID,
14
+ *,
15
15
  http_provider_url: str,
16
16
  timeout: float = 10.0,
17
17
  session: t.Optional[ClientSession] = None,
@@ -2,11 +2,11 @@ import typing as t
2
2
 
3
3
  from aiohttp import ClientSession
4
4
 
5
- from tonutils.clients.http.clients.toncenter import ToncenterHttpClient
5
+ from tonutils.clients.http.clients.toncenter import ToncenterClient
6
6
  from tonutils.types import NetworkGlobalID, RetryPolicy
7
7
 
8
8
 
9
- class QuicknodeHttpClient(ToncenterHttpClient):
9
+ class QuicknodeClient(ToncenterClient):
10
10
 
11
11
  def __init__(
12
12
  self,
@@ -33,7 +33,6 @@ class QuicknodeHttpClient(ToncenterHttpClient):
33
33
  :param rps_period: Rate limit period in seconds.
34
34
  :param retry_policy: Optional retry policy that defines per-error-code retry rules
35
35
  """
36
-
37
36
  super().__init__(
38
37
  network=NetworkGlobalID.MAINNET,
39
38
  base_url=http_provider_url,
@@ -2,16 +2,16 @@ import typing as t
2
2
 
3
3
  from aiohttp import ClientSession
4
4
 
5
- from tonutils.clients.http.clients.toncenter import ToncenterHttpClient
5
+ from tonutils.clients.http.clients.toncenter import ToncenterClient
6
6
  from tonutils.types import NetworkGlobalID, RetryPolicy
7
7
 
8
8
 
9
- class TatumHttpClient(ToncenterHttpClient):
9
+ class TatumClient(ToncenterClient):
10
10
 
11
11
  def __init__(
12
12
  self,
13
- *,
14
13
  network: NetworkGlobalID,
14
+ *,
15
15
  api_key: str,
16
16
  base_url: t.Optional[str] = None,
17
17
  timeout: float = 10.0,
@@ -6,8 +6,8 @@ from aiohttp import ClientSession
6
6
  from pytoniq_core import Cell, Slice, Transaction
7
7
 
8
8
  from tonutils.clients.base import BaseClient
9
- from tonutils.clients.http.providers.tonapi.models import BlockchainMessagePayload
10
- from tonutils.clients.http.providers.tonapi.provider import TonapiHttpProvider
9
+ from tonutils.clients.http.provider.models import BlockchainMessagePayload
10
+ from tonutils.clients.http.provider.tonapi import TonapiHttpProvider
11
11
  from tonutils.clients.http.utils import encode_tonapi_stack, decode_tonapi_stack
12
12
  from tonutils.exceptions import ClientError, RunGetMethodError
13
13
  from tonutils.types import (
@@ -23,15 +23,15 @@ from tonutils.utils import (
23
23
  )
24
24
 
25
25
 
26
- class TonapiHttpClient(BaseClient):
26
+ class TonapiClient(BaseClient):
27
27
  """TON blockchain client using Tonapi HTTP API as transport."""
28
28
 
29
29
  TYPE = ClientType.HTTP
30
30
 
31
31
  def __init__(
32
32
  self,
33
- *,
34
33
  network: NetworkGlobalID = NetworkGlobalID.MAINNET,
34
+ *,
35
35
  api_key: str,
36
36
  base_url: t.Optional[str] = None,
37
37
  timeout: float = 10.0,
@@ -80,7 +80,7 @@ class TonapiHttpClient(BaseClient):
80
80
  session = self._provider.session
81
81
  return session is not None and not session.closed
82
82
 
83
- async def __aenter__(self) -> TonapiHttpClient:
83
+ async def __aenter__(self) -> TonapiClient:
84
84
  await self._provider.connect()
85
85
  return self
86
86
 
@@ -122,21 +122,20 @@ class TonapiHttpClient(BaseClient):
122
122
 
123
123
  return contract_info
124
124
 
125
- async def _get_contract_transactions(
125
+ async def _get_transactions(
126
126
  self,
127
127
  address: str,
128
128
  limit: int = 100,
129
129
  from_lt: t.Optional[int] = None,
130
- to_lt: int = 0,
130
+ to_lt: t.Optional[int] = None,
131
131
  ) -> t.List[Transaction]:
132
- if from_lt is not None:
133
- from_lt += 1
132
+ before_lt = from_lt + 1 if from_lt is not None else None
134
133
 
135
134
  result = await self.provider.blockchain_account_transactions(
136
135
  address=address,
137
136
  limit=limit,
138
137
  after_lt=to_lt,
139
- before_lt=from_lt,
138
+ before_lt=before_lt,
140
139
  )
141
140
 
142
141
  transactions = []