tonutils 2.0.1b5__py3-none-any.whl → 2.0.1b7__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.
- tonutils/__meta__.py +1 -1
- tonutils/clients/__init__.py +10 -10
- tonutils/clients/adnl/balancer.py +135 -361
- tonutils/clients/adnl/client.py +35 -208
- tonutils/clients/adnl/mixin.py +268 -0
- tonutils/clients/adnl/provider/config.py +22 -7
- tonutils/clients/adnl/provider/provider.py +61 -16
- tonutils/clients/adnl/provider/transport.py +13 -4
- tonutils/clients/adnl/provider/workers/pinger.py +1 -1
- tonutils/clients/adnl/utils.py +5 -5
- tonutils/clients/base.py +61 -95
- tonutils/clients/http/__init__.py +11 -11
- tonutils/clients/http/balancer.py +103 -100
- tonutils/clients/http/clients/__init__.py +10 -10
- tonutils/clients/http/clients/chainstack.py +3 -3
- tonutils/clients/http/clients/quicknode.py +2 -3
- tonutils/clients/http/clients/tatum.py +4 -3
- tonutils/clients/http/clients/tonapi.py +20 -33
- tonutils/clients/http/clients/toncenter.py +64 -55
- tonutils/clients/http/{providers → provider}/__init__.py +4 -1
- tonutils/clients/http/{providers → provider}/base.py +140 -61
- tonutils/clients/http/{providers/toncenter → provider}/models.py +44 -2
- tonutils/clients/http/{providers/tonapi/provider.py → provider/tonapi.py} +8 -13
- tonutils/clients/http/{providers/toncenter/provider.py → provider/toncenter.py} +25 -21
- tonutils/clients/limiter.py +61 -59
- tonutils/clients/protocol.py +8 -8
- tonutils/contracts/base.py +32 -32
- tonutils/contracts/protocol.py +9 -9
- tonutils/contracts/wallet/base.py +7 -8
- tonutils/contracts/wallet/messages.py +4 -8
- tonutils/contracts/wallet/versions/v5.py +2 -2
- tonutils/exceptions.py +29 -13
- tonutils/tonconnect/bridge/__init__.py +0 -0
- tonutils/tonconnect/events.py +0 -0
- tonutils/tonconnect/models/__init__.py +0 -0
- tonutils/tonconnect/storage.py +0 -0
- tonutils/tonconnect/tonconnect.py +0 -0
- tonutils/tools/block_scanner/__init__.py +2 -5
- tonutils/tools/block_scanner/events.py +48 -7
- tonutils/tools/block_scanner/scanner.py +316 -222
- tonutils/tools/block_scanner/storage.py +11 -0
- tonutils/tools/status_monitor/monitor.py +6 -6
- tonutils/types.py +2 -2
- tonutils/utils.py +0 -48
- {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b7.dist-info}/METADATA +3 -18
- {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b7.dist-info}/RECORD +50 -51
- {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b7.dist-info}/WHEEL +1 -1
- tonutils/clients/http/providers/response.py +0 -85
- tonutils/clients/http/providers/tonapi/__init__.py +0 -3
- tonutils/clients/http/providers/tonapi/models.py +0 -47
- tonutils/clients/http/providers/toncenter/__init__.py +0 -3
- tonutils/tools/block_scanner/annotations.py +0 -23
- tonutils/tools/block_scanner/dispatcher.py +0 -141
- tonutils/tools/block_scanner/traversal.py +0 -97
- tonutils/tools/block_scanner/where.py +0 -53
- {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b7.dist-info}/entry_points.txt +0 -0
- {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b7.dist-info}/licenses/LICENSE +0 -0
- {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b7.dist-info}/top_level.txt +0 -0
|
@@ -14,6 +14,7 @@ from pytoniq_core import (
|
|
|
14
14
|
Transaction,
|
|
15
15
|
VmStack,
|
|
16
16
|
deserialize_shard_hashes,
|
|
17
|
+
ShardAccount,
|
|
17
18
|
)
|
|
18
19
|
from pytoniq_core.crypto.ciphers import get_random
|
|
19
20
|
from pytoniq_core.crypto.crc import crc16
|
|
@@ -41,7 +42,7 @@ from tonutils.exceptions import (
|
|
|
41
42
|
ProviderResponseError,
|
|
42
43
|
)
|
|
43
44
|
from tonutils.types import (
|
|
44
|
-
|
|
45
|
+
ContractInfo,
|
|
45
46
|
RetryPolicy,
|
|
46
47
|
WorkchainID,
|
|
47
48
|
)
|
|
@@ -95,13 +96,13 @@ class AdnlProvider:
|
|
|
95
96
|
self._connect_lock: asyncio.Lock = asyncio.Lock()
|
|
96
97
|
|
|
97
98
|
@property
|
|
98
|
-
def
|
|
99
|
+
def connected(self) -> bool:
|
|
99
100
|
"""
|
|
100
101
|
Whether the underlying transport is currently connected.
|
|
101
102
|
|
|
102
103
|
:return: True if connected, False otherwise
|
|
103
104
|
"""
|
|
104
|
-
return self.transport.
|
|
105
|
+
return self.transport.connected
|
|
105
106
|
|
|
106
107
|
@property
|
|
107
108
|
def last_mc_block(self) -> BlockIdExt:
|
|
@@ -165,7 +166,7 @@ class AdnlProvider:
|
|
|
165
166
|
|
|
166
167
|
Establishes transport, performs handshake and starts background workers.
|
|
167
168
|
"""
|
|
168
|
-
if self.
|
|
169
|
+
if self.connected:
|
|
169
170
|
return
|
|
170
171
|
|
|
171
172
|
self.loop = asyncio.get_running_loop()
|
|
@@ -215,8 +216,12 @@ class AdnlProvider:
|
|
|
215
216
|
:param priority: Whether to use priority slot in the limiter
|
|
216
217
|
:return: Lite-server response payload as a decoded dictionary
|
|
217
218
|
"""
|
|
218
|
-
if not self.
|
|
219
|
-
raise NotConnectedError(
|
|
219
|
+
if not self.connected or self.loop is None:
|
|
220
|
+
raise NotConnectedError(
|
|
221
|
+
component="AdnlProvider",
|
|
222
|
+
endpoint=self.node.endpoint,
|
|
223
|
+
operation="request",
|
|
224
|
+
)
|
|
220
225
|
|
|
221
226
|
if self._limiter is not None:
|
|
222
227
|
await self._limiter.acquire(priority=priority)
|
|
@@ -492,7 +497,7 @@ class AdnlProvider:
|
|
|
492
497
|
|
|
493
498
|
return block_id, block_obj
|
|
494
499
|
|
|
495
|
-
async def
|
|
500
|
+
async def get_block_transactions(
|
|
496
501
|
self,
|
|
497
502
|
block: BlockIdExt,
|
|
498
503
|
count: int = 1024,
|
|
@@ -591,7 +596,7 @@ class AdnlProvider:
|
|
|
591
596
|
for sh in v.list
|
|
592
597
|
]
|
|
593
598
|
|
|
594
|
-
async def
|
|
599
|
+
async def run_get_method(
|
|
595
600
|
self,
|
|
596
601
|
address: Address,
|
|
597
602
|
method_name: str,
|
|
@@ -643,7 +648,7 @@ class AdnlProvider:
|
|
|
643
648
|
cs = Slice.one_from_boc(result["result"])
|
|
644
649
|
return VmStack.deserialize(cs)
|
|
645
650
|
|
|
646
|
-
async def
|
|
651
|
+
async def get_config(
|
|
647
652
|
self,
|
|
648
653
|
*,
|
|
649
654
|
priority: bool = False,
|
|
@@ -667,18 +672,18 @@ class AdnlProvider:
|
|
|
667
672
|
config_proof = Cell.one_from_boc(result.get("config_proof"))
|
|
668
673
|
return build_config_all(config_proof)
|
|
669
674
|
|
|
670
|
-
async def
|
|
675
|
+
async def get_info(
|
|
671
676
|
self,
|
|
672
677
|
address: Address,
|
|
673
678
|
*,
|
|
674
679
|
priority: bool = False,
|
|
675
|
-
) ->
|
|
680
|
+
) -> ContractInfo:
|
|
676
681
|
"""
|
|
677
682
|
Fetch contract state at the latest masterchain block.
|
|
678
683
|
|
|
679
684
|
:param address: Contract address
|
|
680
685
|
:param priority: Whether to use priority slot in the limiter
|
|
681
|
-
:return:
|
|
686
|
+
:return: ContractInfo with balance, code, data and last tx
|
|
682
687
|
"""
|
|
683
688
|
if self.last_mc_block is None:
|
|
684
689
|
await self.updater.refresh()
|
|
@@ -693,7 +698,7 @@ class AdnlProvider:
|
|
|
693
698
|
priority=priority,
|
|
694
699
|
)
|
|
695
700
|
if not result["state"]:
|
|
696
|
-
return
|
|
701
|
+
return ContractInfo(balance=0)
|
|
697
702
|
|
|
698
703
|
account_state_root = Cell.one_from_boc(result["state"])
|
|
699
704
|
account = Account.deserialize(account_state_root.begin_parse())
|
|
@@ -755,9 +760,9 @@ class AdnlProvider:
|
|
|
755
760
|
for i, cell in enumerate(cells):
|
|
756
761
|
curr_hash = cell.get_hash(0).hex()
|
|
757
762
|
if curr_hash != prev_tr_hash:
|
|
758
|
-
raise
|
|
759
|
-
|
|
760
|
-
f"expected {prev_tr_hash}, got {curr_hash}"
|
|
763
|
+
raise ProviderError(
|
|
764
|
+
"getTransactions failed: transaction hash mismatch "
|
|
765
|
+
f"(expected {prev_tr_hash}, got {curr_hash})"
|
|
761
766
|
)
|
|
762
767
|
|
|
763
768
|
tx = Transaction.deserialize(cell.begin_parse())
|
|
@@ -765,3 +770,43 @@ class AdnlProvider:
|
|
|
765
770
|
transactions.append(tx)
|
|
766
771
|
|
|
767
772
|
return transactions
|
|
773
|
+
|
|
774
|
+
async def get_account_state(
|
|
775
|
+
self,
|
|
776
|
+
address: Address,
|
|
777
|
+
*,
|
|
778
|
+
priority: bool = False,
|
|
779
|
+
) -> t.Tuple[t.Optional[Account], t.Optional[ShardAccount]]:
|
|
780
|
+
"""
|
|
781
|
+
Fetch account state and shard account from lite-server.
|
|
782
|
+
|
|
783
|
+
:param address: Account address
|
|
784
|
+
:param priority: Whether to use priority slot in the limiter
|
|
785
|
+
:return: Tuple of (Account | None, ShardAccount | None)
|
|
786
|
+
"""
|
|
787
|
+
if self.last_mc_block is None:
|
|
788
|
+
await self.updater.refresh()
|
|
789
|
+
|
|
790
|
+
data = {
|
|
791
|
+
"id": self.last_mc_block.to_dict(),
|
|
792
|
+
"account": address.to_tl_account_id(),
|
|
793
|
+
}
|
|
794
|
+
result = await self.send_liteserver_query(
|
|
795
|
+
method="getAccountState",
|
|
796
|
+
data=data,
|
|
797
|
+
priority=priority,
|
|
798
|
+
)
|
|
799
|
+
if not result.get("state"):
|
|
800
|
+
return None, None
|
|
801
|
+
|
|
802
|
+
account_state_root = Cell.one_from_boc(result["state"])
|
|
803
|
+
account = Account.deserialize(account_state_root.begin_parse())
|
|
804
|
+
|
|
805
|
+
shrd_blk = BlockIdExt.from_dict(result["shardblk"])
|
|
806
|
+
shard_account = build_shard_account(
|
|
807
|
+
account_state_root=account_state_root,
|
|
808
|
+
shard_account_descr=result["proof"],
|
|
809
|
+
shrd_blk=shrd_blk,
|
|
810
|
+
address=address,
|
|
811
|
+
)
|
|
812
|
+
return account, shard_account
|
|
@@ -64,7 +64,7 @@ class AdnlTcpTransport:
|
|
|
64
64
|
self._closing = False
|
|
65
65
|
|
|
66
66
|
@property
|
|
67
|
-
def
|
|
67
|
+
def connected(self) -> bool:
|
|
68
68
|
"""Check if the transport is currently connected."""
|
|
69
69
|
return self._connected
|
|
70
70
|
|
|
@@ -178,7 +178,7 @@ class AdnlTcpTransport:
|
|
|
178
178
|
"connect", f"timeout after {self.connect_timeout}s"
|
|
179
179
|
) from exc
|
|
180
180
|
except OSError as exc:
|
|
181
|
-
raise self._error("connect",
|
|
181
|
+
raise self._error("connect", str(exc)) from exc
|
|
182
182
|
|
|
183
183
|
if self.writer is None or self.reader is None:
|
|
184
184
|
raise self._error("connect", "stream init failed")
|
|
@@ -218,7 +218,11 @@ class AdnlTcpTransport:
|
|
|
218
218
|
:param payload: Raw ADNL packet bytes
|
|
219
219
|
"""
|
|
220
220
|
if not self._connected or self.writer is None:
|
|
221
|
-
raise NotConnectedError(
|
|
221
|
+
raise NotConnectedError(
|
|
222
|
+
component="ADNL transport",
|
|
223
|
+
endpoint=self.node.endpoint,
|
|
224
|
+
operation="send",
|
|
225
|
+
)
|
|
222
226
|
|
|
223
227
|
packet = self._build_frame(payload)
|
|
224
228
|
encrypted = self.encrypt_frame(packet)
|
|
@@ -233,7 +237,12 @@ class AdnlTcpTransport:
|
|
|
233
237
|
Blocks until a complete packet is available from the background reader.
|
|
234
238
|
"""
|
|
235
239
|
if not self._connected:
|
|
236
|
-
raise NotConnectedError(
|
|
240
|
+
raise NotConnectedError(
|
|
241
|
+
component="ADNL transport",
|
|
242
|
+
endpoint=self.node.endpoint,
|
|
243
|
+
operation="recv",
|
|
244
|
+
)
|
|
245
|
+
|
|
237
246
|
return await self._incoming.get()
|
|
238
247
|
|
|
239
248
|
async def read_frame(self, discard: bool = False) -> t.Optional[bytes]:
|
tonutils/clients/adnl/utils.py
CHANGED
|
@@ -15,7 +15,7 @@ from pytoniq_core import (
|
|
|
15
15
|
VmTuple,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
|
-
from tonutils.types import ContractState,
|
|
18
|
+
from tonutils.types import ContractState, ContractInfo, StackItems, StackItem
|
|
19
19
|
from tonutils.utils import cell_to_hex, norm_stack_num, norm_stack_cell
|
|
20
20
|
|
|
21
21
|
|
|
@@ -72,17 +72,17 @@ def build_contract_state_info(
|
|
|
72
72
|
address: Address,
|
|
73
73
|
account: Account,
|
|
74
74
|
shard_account: ShardAccount,
|
|
75
|
-
) ->
|
|
75
|
+
) -> ContractInfo:
|
|
76
76
|
"""
|
|
77
|
-
Build a high-level
|
|
77
|
+
Build a high-level ContractInfo object from raw account data.
|
|
78
78
|
|
|
79
79
|
:param address: Contract address
|
|
80
80
|
:param account: Raw Account data structure
|
|
81
81
|
:param shard_account: Parsed ShardAccount entry
|
|
82
|
-
:return: Filled
|
|
82
|
+
:return: Filled ContractInfo instance
|
|
83
83
|
"""
|
|
84
84
|
simple_account = SimpleAccount.from_raw(account, address)
|
|
85
|
-
info =
|
|
85
|
+
info = ContractInfo(balance=simple_account.balance)
|
|
86
86
|
|
|
87
87
|
if simple_account.state is not None:
|
|
88
88
|
state_init = simple_account.state.state_init
|
tonutils/clients/base.py
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import abc
|
|
4
|
+
import asyncio
|
|
4
5
|
import typing as t
|
|
6
|
+
from contextlib import suppress
|
|
5
7
|
|
|
6
8
|
from pytoniq_core import Address, Cell, Transaction, begin_cell
|
|
7
9
|
|
|
10
|
+
from tonutils.exceptions import ProviderError
|
|
8
11
|
from tonutils.types import (
|
|
9
12
|
AddressLike,
|
|
10
|
-
|
|
13
|
+
ContractInfo,
|
|
11
14
|
ClientType,
|
|
12
15
|
DNSCategory,
|
|
13
16
|
NetworkGlobalID,
|
|
@@ -36,85 +39,48 @@ class BaseClient(abc.ABC):
|
|
|
36
39
|
|
|
37
40
|
@property
|
|
38
41
|
@abc.abstractmethod
|
|
39
|
-
def
|
|
42
|
+
def connected(self) -> bool:
|
|
40
43
|
"""
|
|
41
|
-
|
|
44
|
+
Check whether provider resources are initialized and usable.
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
type (HTTP session, ADNL transport, etc.).
|
|
46
|
+
:return: True if client has an active session/connection, False otherwise
|
|
45
47
|
"""
|
|
46
|
-
raise NotImplementedError
|
|
47
48
|
|
|
49
|
+
@property
|
|
48
50
|
@abc.abstractmethod
|
|
49
|
-
|
|
51
|
+
def provider(self) -> t.Any:
|
|
50
52
|
"""
|
|
51
|
-
|
|
53
|
+
Underlying transport/provider backend used for all requests.
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
Expected to expose network I/O primitives appropriate for the client
|
|
56
|
+
type (HTTP session, ADNL transport, etc.).
|
|
54
57
|
"""
|
|
55
|
-
raise NotImplementedError
|
|
56
58
|
|
|
57
59
|
@abc.abstractmethod
|
|
58
|
-
async def
|
|
59
|
-
|
|
60
|
-
exc_type: t.Optional[t.Type[BaseException]],
|
|
61
|
-
exc_value: t.Optional[BaseException],
|
|
62
|
-
traceback: t.Optional[t.Any],
|
|
63
|
-
) -> None:
|
|
64
|
-
"""
|
|
65
|
-
Release allocated client resources.
|
|
66
|
-
|
|
67
|
-
Called automatically when the async context ends.
|
|
68
|
-
"""
|
|
69
|
-
raise NotImplementedError
|
|
60
|
+
async def connect(self) -> None:
|
|
61
|
+
"""Initialize any required provider resources (sessions, transports, etc.)."""
|
|
70
62
|
|
|
71
63
|
@abc.abstractmethod
|
|
72
|
-
async def
|
|
73
|
-
"""
|
|
74
|
-
Send an external message to the network using the underlying provider.
|
|
75
|
-
|
|
76
|
-
:param boc: Message body serialized as BoC string,
|
|
77
|
-
in a format accepted by the underlying provider
|
|
78
|
-
"""
|
|
79
|
-
raise NotImplementedError
|
|
64
|
+
async def close(self) -> None:
|
|
65
|
+
"""Close provider resources. Should be safe to call multiple times."""
|
|
80
66
|
|
|
81
67
|
@abc.abstractmethod
|
|
82
|
-
async def
|
|
83
|
-
"""
|
|
84
|
-
Fetch full blockchain configuration from the underlying provider.
|
|
85
|
-
|
|
86
|
-
:return: Mapping of configuration parameter ID to parsed value
|
|
87
|
-
"""
|
|
88
|
-
raise NotImplementedError
|
|
68
|
+
async def _send_message(self, boc: str) -> None: ...
|
|
89
69
|
|
|
90
70
|
@abc.abstractmethod
|
|
91
|
-
async def
|
|
92
|
-
"""
|
|
93
|
-
Retrieve basic contract state information from the provider.
|
|
71
|
+
async def _get_config(self) -> t.Dict[int, t.Any]: ...
|
|
94
72
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
"""
|
|
98
|
-
raise NotImplementedError
|
|
73
|
+
@abc.abstractmethod
|
|
74
|
+
async def _get_info(self, address: str) -> ContractInfo: ...
|
|
99
75
|
|
|
100
76
|
@abc.abstractmethod
|
|
101
|
-
async def
|
|
77
|
+
async def _get_transactions(
|
|
102
78
|
self,
|
|
103
79
|
address: str,
|
|
104
80
|
limit: int = 100,
|
|
105
81
|
from_lt: t.Optional[int] = None,
|
|
106
|
-
to_lt: int =
|
|
107
|
-
) -> t.List[Transaction]:
|
|
108
|
-
"""
|
|
109
|
-
Fetch a list of recent contract transactions from the provider.
|
|
110
|
-
|
|
111
|
-
:param address: Contract address in raw
|
|
112
|
-
: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
|
|
115
|
-
:return: List of Transaction objects ordered from newest to oldest
|
|
116
|
-
"""
|
|
117
|
-
raise NotImplementedError
|
|
82
|
+
to_lt: t.Optional[int] = None,
|
|
83
|
+
) -> t.List[Transaction]: ...
|
|
118
84
|
|
|
119
85
|
@abc.abstractmethod
|
|
120
86
|
async def _run_get_method(
|
|
@@ -122,83 +88,79 @@ class BaseClient(abc.ABC):
|
|
|
122
88
|
address: str,
|
|
123
89
|
method_name: str,
|
|
124
90
|
stack: t.Optional[t.List[t.Any]] = None,
|
|
125
|
-
) -> t.List[t.Any]:
|
|
126
|
-
"""
|
|
127
|
-
Execute a contract get-method via the provider.
|
|
91
|
+
) -> t.List[t.Any]: ...
|
|
128
92
|
|
|
129
|
-
|
|
130
|
-
:param method_name: Name of the get-method to execute
|
|
131
|
-
:param stack: Optional initial TVM stack items for the call
|
|
132
|
-
:return: Decoded TVM stack items returned by the method
|
|
93
|
+
async def __aenter__(self) -> BaseClient:
|
|
133
94
|
"""
|
|
134
|
-
|
|
95
|
+
Prepare client resources for use.
|
|
135
96
|
|
|
136
|
-
|
|
137
|
-
@abc.abstractmethod
|
|
138
|
-
def is_connected(self) -> bool:
|
|
97
|
+
Should initialize network connections or sessions as required.
|
|
139
98
|
"""
|
|
140
|
-
|
|
99
|
+
await self.connect()
|
|
100
|
+
return self
|
|
141
101
|
|
|
142
|
-
|
|
102
|
+
async def __aexit__(
|
|
103
|
+
self,
|
|
104
|
+
exc_type: t.Optional[t.Type[BaseException]],
|
|
105
|
+
exc_value: t.Optional[BaseException],
|
|
106
|
+
traceback: t.Optional[t.Any],
|
|
107
|
+
) -> None:
|
|
143
108
|
"""
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
@abc.abstractmethod
|
|
147
|
-
async def connect(self) -> None:
|
|
148
|
-
"""Initialize any required provider resources (sessions, transports, etc.)."""
|
|
149
|
-
raise NotImplementedError
|
|
109
|
+
Release allocated client resources.
|
|
150
110
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
111
|
+
Called automatically when the async context ends.
|
|
112
|
+
"""
|
|
113
|
+
with suppress(asyncio.CancelledError):
|
|
114
|
+
await self.close()
|
|
155
115
|
|
|
156
|
-
async def
|
|
116
|
+
async def send_message(self, boc: str) -> None:
|
|
157
117
|
"""
|
|
158
118
|
Send an external message to the blockchain.
|
|
159
119
|
|
|
160
120
|
:param boc: Message body serialized as BoC string, in a format accepted by the underlying provider
|
|
161
121
|
"""
|
|
162
|
-
await self.
|
|
122
|
+
await self._send_message(boc)
|
|
163
123
|
|
|
164
|
-
async def
|
|
124
|
+
async def get_config(self) -> t.Dict[int, t.Any]:
|
|
165
125
|
"""
|
|
166
126
|
Fetch and decode global blockchain configuration.
|
|
167
127
|
|
|
168
128
|
:return: Mapping of configuration parameter ID to parsed value
|
|
169
129
|
"""
|
|
170
|
-
return await self.
|
|
130
|
+
return await self._get_config()
|
|
171
131
|
|
|
172
|
-
async def
|
|
132
|
+
async def get_info(self, address: AddressLike) -> ContractInfo:
|
|
173
133
|
"""
|
|
174
134
|
Fetch basic state information for a smart contract.
|
|
175
135
|
|
|
176
136
|
:param address: Contract address as Address object or string
|
|
177
|
-
:return:
|
|
137
|
+
:return: ContractInfo with code, data, balance and last tx data
|
|
178
138
|
"""
|
|
179
139
|
if isinstance(address, Address):
|
|
180
140
|
address = Address(address).to_str(is_user_friendly=False)
|
|
181
|
-
return await self.
|
|
141
|
+
return await self._get_info(address=address)
|
|
182
142
|
|
|
183
|
-
async def
|
|
143
|
+
async def get_transactions(
|
|
184
144
|
self,
|
|
185
145
|
address: AddressLike,
|
|
186
146
|
limit: int = 100,
|
|
187
147
|
from_lt: t.Optional[int] = None,
|
|
188
|
-
to_lt: int =
|
|
148
|
+
to_lt: t.Optional[int] = None,
|
|
189
149
|
) -> t.List[Transaction]:
|
|
190
150
|
"""
|
|
191
151
|
Fetch transaction history for a contract.
|
|
192
152
|
|
|
193
153
|
:param address: Contract address as Address object or string
|
|
194
154
|
:param limit: Maximum number of transactions to return
|
|
195
|
-
:param from_lt:
|
|
196
|
-
|
|
155
|
+
:param from_lt: Upper bound logical time (inclusive).
|
|
156
|
+
If None, starts from the most recent transaction.
|
|
157
|
+
:param to_lt: Lower bound logical time (exclusive).
|
|
158
|
+
If None or 0, no lower bound is applied.
|
|
197
159
|
:return: List of Transaction objects ordered from newest to oldest
|
|
198
160
|
"""
|
|
199
161
|
if isinstance(address, Address):
|
|
200
162
|
address = Address(address).to_str(is_user_friendly=False)
|
|
201
|
-
return await self.
|
|
163
|
+
return await self._get_transactions(
|
|
202
164
|
address=address,
|
|
203
165
|
limit=limit,
|
|
204
166
|
from_lt=from_lt,
|
|
@@ -256,7 +218,7 @@ class BaseClient(abc.ABC):
|
|
|
256
218
|
if isinstance(domain, str):
|
|
257
219
|
domain = encode_dns_name(domain)
|
|
258
220
|
if dns_root_address is None:
|
|
259
|
-
blockchain_config = await self.
|
|
221
|
+
blockchain_config = await self.get_config()
|
|
260
222
|
hash_part = blockchain_config[4].dns_root_addr
|
|
261
223
|
dns_root_address = Address((WorkchainID.MASTERCHAIN.value, hash_part))
|
|
262
224
|
|
|
@@ -268,7 +230,9 @@ class BaseClient(abc.ABC):
|
|
|
268
230
|
stack=[domain_cell.to_slice(), category.value],
|
|
269
231
|
)
|
|
270
232
|
if len(res) < 2:
|
|
271
|
-
raise
|
|
233
|
+
raise ProviderError(
|
|
234
|
+
f"dnsresolve failed: invalid response (expected 2 stack items, got {len(res)})"
|
|
235
|
+
)
|
|
272
236
|
|
|
273
237
|
blen = len(domain) * 8
|
|
274
238
|
rlen = t.cast(int, res[0])
|
|
@@ -279,7 +243,9 @@ class BaseClient(abc.ABC):
|
|
|
279
243
|
return None
|
|
280
244
|
|
|
281
245
|
if rlen % 8 != 0 or rlen > blen:
|
|
282
|
-
raise
|
|
246
|
+
raise ProviderError(
|
|
247
|
+
f"dnsresolve failed: invalid resolved length {rlen} bits (domain {blen} bits)"
|
|
248
|
+
)
|
|
283
249
|
if rlen == blen:
|
|
284
250
|
# noinspection PyProtectedMember
|
|
285
251
|
tcls = DNSRecords._DNS_RECORDS_CLASSES.get(category.name.lower())
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
from .balancer import HttpBalancer
|
|
2
2
|
from .clients import (
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
ChainstackClient,
|
|
4
|
+
QuicknodeClient,
|
|
5
|
+
TatumClient,
|
|
6
|
+
TonapiClient,
|
|
7
|
+
ToncenterClient,
|
|
8
8
|
)
|
|
9
|
-
from .
|
|
9
|
+
from .provider import (
|
|
10
10
|
TonapiHttpProvider,
|
|
11
11
|
ToncenterHttpProvider,
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
__all__ = [
|
|
15
15
|
"HttpBalancer",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
16
|
+
"ChainstackClient",
|
|
17
|
+
"QuicknodeClient",
|
|
18
|
+
"TatumClient",
|
|
19
|
+
"TonapiClient",
|
|
20
20
|
"TonapiHttpProvider",
|
|
21
|
-
"
|
|
21
|
+
"ToncenterClient",
|
|
22
22
|
"ToncenterHttpProvider",
|
|
23
23
|
]
|