tonutils 2.0.1b5__py3-none-any.whl → 2.0.1b6__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 (47) hide show
  1. tonutils/__meta__.py +1 -1
  2. tonutils/clients/__init__.py +10 -10
  3. tonutils/clients/adnl/balancer.py +21 -24
  4. tonutils/clients/adnl/client.py +21 -24
  5. tonutils/clients/adnl/provider/config.py +22 -7
  6. tonutils/clients/base.py +17 -11
  7. tonutils/clients/http/__init__.py +11 -11
  8. tonutils/clients/http/balancer.py +11 -11
  9. tonutils/clients/http/clients/__init__.py +10 -10
  10. tonutils/clients/http/clients/chainstack.py +3 -3
  11. tonutils/clients/http/clients/quicknode.py +2 -3
  12. tonutils/clients/http/clients/tatum.py +3 -3
  13. tonutils/clients/http/clients/tonapi.py +9 -10
  14. tonutils/clients/http/clients/toncenter.py +50 -23
  15. tonutils/clients/http/{providers → provider}/__init__.py +4 -1
  16. tonutils/clients/http/{providers → provider}/base.py +71 -7
  17. tonutils/clients/http/{providers/toncenter → provider}/models.py +43 -1
  18. tonutils/clients/http/{providers/tonapi/provider.py → provider/tonapi.py} +8 -8
  19. tonutils/clients/http/{providers/toncenter/provider.py → provider/toncenter.py} +22 -14
  20. tonutils/clients/limiter.py +61 -59
  21. tonutils/clients/protocol.py +2 -2
  22. tonutils/contracts/wallet/base.py +2 -3
  23. tonutils/contracts/wallet/messages.py +4 -8
  24. tonutils/tonconnect/bridge/__init__.py +0 -0
  25. tonutils/tonconnect/events.py +0 -0
  26. tonutils/tonconnect/models/__init__.py +0 -0
  27. tonutils/tonconnect/storage.py +0 -0
  28. tonutils/tonconnect/tonconnect.py +0 -0
  29. tonutils/tools/block_scanner/__init__.py +2 -9
  30. tonutils/tools/block_scanner/events.py +48 -7
  31. tonutils/tools/block_scanner/scanner.py +316 -222
  32. tonutils/tools/block_scanner/storage.py +11 -0
  33. tonutils/utils.py +0 -48
  34. {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b6.dist-info}/METADATA +1 -1
  35. {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b6.dist-info}/RECORD +39 -41
  36. {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b6.dist-info}/WHEEL +1 -1
  37. tonutils/clients/http/providers/response.py +0 -85
  38. tonutils/clients/http/providers/tonapi/__init__.py +0 -3
  39. tonutils/clients/http/providers/tonapi/models.py +0 -47
  40. tonutils/clients/http/providers/toncenter/__init__.py +0 -3
  41. tonutils/tools/block_scanner/annotations.py +0 -23
  42. tonutils/tools/block_scanner/dispatcher.py +0 -141
  43. tonutils/tools/block_scanner/traversal.py +0 -97
  44. tonutils/tools/block_scanner/where.py +0 -53
  45. {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b6.dist-info}/entry_points.txt +0 -0
  46. {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b6.dist-info}/licenses/LICENSE +0 -0
  47. {tonutils-2.0.1b5.dist-info → tonutils-2.0.1b6.dist-info}/top_level.txt +0 -0
@@ -7,11 +7,8 @@ from aiohttp import ClientSession
7
7
  from pytoniq_core import Cell, Slice, Transaction
8
8
 
9
9
  from tonutils.clients.base import BaseClient
10
- from tonutils.clients.http.providers.toncenter.models import (
11
- SendBocPayload,
12
- RunGetMethodPayload,
13
- )
14
- from tonutils.clients.http.providers.toncenter.provider import ToncenterHttpProvider
10
+ from tonutils.clients.http.provider.models import SendBocPayload, RunGetMethodPayload
11
+ from tonutils.clients.http.provider.toncenter import ToncenterHttpProvider
15
12
  from tonutils.clients.http.utils import decode_toncenter_stack, encode_toncenter_stack
16
13
  from tonutils.exceptions import ClientError, RunGetMethodError
17
14
  from tonutils.types import (
@@ -24,15 +21,15 @@ from tonutils.types import (
24
21
  from tonutils.utils import cell_to_hex, parse_stack_config
25
22
 
26
23
 
27
- class ToncenterHttpClient(BaseClient):
24
+ class ToncenterClient(BaseClient):
28
25
  """TON blockchain client using Toncenter HTTP API as transport."""
29
26
 
30
27
  TYPE = ClientType.HTTP
31
28
 
32
29
  def __init__(
33
30
  self,
34
- *,
35
31
  network: NetworkGlobalID = NetworkGlobalID.MAINNET,
32
+ *,
36
33
  api_key: t.Optional[str] = None,
37
34
  base_url: t.Optional[str] = None,
38
35
  timeout: float = 10.0,
@@ -81,7 +78,7 @@ class ToncenterHttpClient(BaseClient):
81
78
  session = self._provider.session
82
79
  return session is not None and not session.closed
83
80
 
84
- async def __aenter__(self) -> ToncenterHttpClient:
81
+ async def __aenter__(self) -> ToncenterClient:
85
82
  await self._provider.connect()
86
83
  return self
87
84
 
@@ -166,28 +163,58 @@ class ToncenterHttpClient(BaseClient):
166
163
 
167
164
  return contract_info
168
165
 
169
- async def _get_contract_transactions(
166
+ async def _get_transactions(
170
167
  self,
171
168
  address: str,
172
169
  limit: int = 100,
173
170
  from_lt: t.Optional[int] = None,
174
- to_lt: int = 0,
171
+ to_lt: t.Optional[int] = None,
175
172
  ) -> t.List[Transaction]:
176
- if from_lt is not None:
177
- from_lt += 1
173
+ to_lt = 0 if to_lt is None else to_lt
174
+ transactions: t.List[Transaction] = []
178
175
 
179
- request = await self.provider.get_transaction(
180
- address=address,
181
- limit=limit,
182
- from_lt=from_lt,
183
- to_lt=to_lt,
184
- )
176
+ curr_lt: t.Optional[int] = None
177
+ curr_hash: t.Optional[str] = None
178
+
179
+ while len(transactions) < limit:
180
+ request = await self.provider.get_transactions(
181
+ address=address,
182
+ limit=100,
183
+ lt=curr_lt,
184
+ from_hash=curr_hash,
185
+ to_lt=to_lt if to_lt > 0 else None,
186
+ )
187
+
188
+ batch = []
189
+ for tx in request.result or []:
190
+ if tx.data is not None:
191
+ tx_slice = Slice.one_from_boc(tx.data)
192
+ batch.append(Transaction.deserialize(tx_slice))
193
+
194
+ if not batch:
195
+ break
196
+
197
+ for tx in batch:
198
+ # Skip transactions above from_lt (if specified)
199
+ if from_lt is not None and tx.lt > from_lt:
200
+ continue
201
+
202
+ # Stop if we've reached the lower bound
203
+ if to_lt > 0 and tx.lt <= to_lt:
204
+ return transactions[:limit]
205
+
206
+ transactions.append(tx)
207
+
208
+ if len(transactions) >= limit:
209
+ return transactions
210
+
211
+ # Setup for next iteration
212
+ last_tx = batch[-1]
213
+ if last_tx.prev_trans_lt == 0:
214
+ break
185
215
 
186
- transactions = []
187
- for tx in request.result or []:
188
- if tx.data is not None:
189
- tx_slice = Slice.one_from_boc(tx.data)
190
- transactions.append(Transaction.deserialize(tx_slice))
216
+ curr_lt = last_tx.prev_trans_lt
217
+ curr_hash = last_tx.prev_trans_hash.hex()
191
218
 
192
219
  return transactions
193
220
 
@@ -1,4 +1,7 @@
1
1
  from .tonapi import TonapiHttpProvider
2
2
  from .toncenter import ToncenterHttpProvider
3
3
 
4
- __all__ = ["TonapiHttpProvider", "ToncenterHttpProvider"]
4
+ __all__ = [
5
+ "TonapiHttpProvider",
6
+ "ToncenterHttpProvider",
7
+ ]
@@ -1,17 +1,18 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
+ import json
4
5
  import typing as t
5
6
 
6
7
  import aiohttp
7
8
 
8
- from tonutils.clients.http.providers.response import HttpResponse
9
9
  from tonutils.clients.limiter import RateLimiter
10
10
  from tonutils.exceptions import (
11
11
  NotConnectedError,
12
12
  ProviderResponseError,
13
13
  ProviderTimeoutError,
14
14
  RetryLimitError,
15
+ CDN_CHALLENGE_MARKERS,
15
16
  )
16
17
  from tonutils.types import RetryPolicy
17
18
 
@@ -90,6 +91,34 @@ class HttpProvider:
90
91
  await self._session.close()
91
92
  self._session = None
92
93
 
94
+ @classmethod
95
+ async def _read_response(cls, resp: aiohttp.ClientResponse) -> t.Any:
96
+ body = await resp.read()
97
+ if not body:
98
+ return ""
99
+
100
+ data = body.decode("utf-8", errors="replace").strip()
101
+ if not data:
102
+ return ""
103
+
104
+ try:
105
+ return json.loads(data)
106
+ except (Exception,):
107
+ return data
108
+
109
+ @classmethod
110
+ def _raise_error(cls, status: int, url: str, data: t.Any) -> None:
111
+ exc = cls._detect_proxy_error(data, status=status, url=url)
112
+ if exc is not None:
113
+ raise exc
114
+
115
+ message = cls._extract_error_message(data)
116
+ raise ProviderResponseError(
117
+ code=status,
118
+ message=message,
119
+ endpoint=url,
120
+ )
121
+
93
122
  async def _send_once(
94
123
  self,
95
124
  method: str,
@@ -126,13 +155,9 @@ class HttpProvider:
126
155
  params=params,
127
156
  json=json_data,
128
157
  ) as resp:
129
- data = await HttpResponse.read(resp)
158
+ data = await self._read_response(resp)
130
159
  if resp.status >= 400:
131
- HttpResponse.raise_error(
132
- status=int(resp.status),
133
- url=url,
134
- data=data,
135
- )
160
+ self._raise_error(int(resp.status), url, data)
136
161
  return data
137
162
 
138
163
  except asyncio.TimeoutError as exc:
@@ -199,3 +224,42 @@ class HttpProvider:
199
224
  ) from e
200
225
 
201
226
  await asyncio.sleep(rule.delay(attempts[key] - 1))
227
+
228
+ @classmethod
229
+ def _detect_proxy_error(
230
+ cls,
231
+ data: t.Any,
232
+ status: int,
233
+ url: str,
234
+ ) -> t.Optional[ProviderResponseError]:
235
+ body = (
236
+ " ".join(str(v) for v in data.values())
237
+ if isinstance(data, dict)
238
+ else str(data)
239
+ ).lower()
240
+
241
+ for marker, message in CDN_CHALLENGE_MARKERS.items():
242
+ if marker in body:
243
+ return ProviderResponseError(
244
+ code=status,
245
+ message=message,
246
+ endpoint=url,
247
+ )
248
+
249
+ return None
250
+
251
+ @staticmethod
252
+ def _extract_error_message(data: t.Any) -> str:
253
+ if isinstance(data, dict):
254
+ lowered = {k.lower(): v for k, v in data.items()}
255
+ for key in ("error", "message", "detail", "description"):
256
+ if key in lowered and isinstance(lowered[key], str):
257
+ return lowered[key]
258
+ string_values = [str(v) for v in data.values() if isinstance(v, str)]
259
+ return "; ".join(string_values) if string_values else str(data)
260
+
261
+ if isinstance(data, list):
262
+ return "; ".join(map(str, data))
263
+ if isinstance(data, str):
264
+ return data
265
+ return repr(data)
@@ -6,6 +6,48 @@ from tonutils.types import ContractState
6
6
  from tonutils.utils import to_cell, cell_to_b64
7
7
 
8
8
 
9
+ class BlockchainMessagePayload(BaseModel):
10
+ """Payload for /blockchain/message endpoint."""
11
+
12
+ boc: str
13
+
14
+
15
+ class BlockchainConfigResult(BaseModel):
16
+ """Result model for /blockchain/config."""
17
+
18
+ raw: t.Optional[str] = None
19
+
20
+
21
+ class BlockchainAccountResult(BaseModel):
22
+ """Result model for /blockchain/accounts/{address}."""
23
+
24
+ balance: int = 0
25
+ status: str = ContractState.NONEXIST.value
26
+ code: t.Optional[str] = None
27
+ data: t.Optional[str] = None
28
+ last_transaction_lt: t.Optional[int] = None
29
+ last_transaction_hash: t.Optional[str] = None
30
+
31
+
32
+ class _BlockchainAccountTransaction(BaseModel):
33
+ """Single account transaction with raw BoC payload."""
34
+
35
+ raw: t.Optional[str] = None
36
+
37
+
38
+ class BlockchainAccountTransactionsResult(BaseModel):
39
+ """Result model for /blockchain/accounts/{address}/transactions."""
40
+
41
+ transactions: t.Optional[t.List[_BlockchainAccountTransaction]] = None
42
+
43
+
44
+ class BlockchainAccountMethodResult(BaseModel):
45
+ """Result model for /blockchain/accounts/{address}/methods/{method_name}."""
46
+
47
+ stack: t.Optional[t.List[t.Any]] = None
48
+ exit_code: int
49
+
50
+
9
51
  class SendBocPayload(BaseModel):
10
52
  """
11
53
  Payload for /sendBoc endpoint.
@@ -77,7 +119,7 @@ class _Transaction(BaseModel):
77
119
  data: t.Optional[str] = None
78
120
 
79
121
 
80
- class GetTransactionResult(BaseModel):
122
+ class GetTransactionsResult(BaseModel):
81
123
  """Result wrapper for /getTransactions."""
82
124
 
83
125
  result: t.Optional[t.List[_Transaction]] = None
@@ -5,13 +5,13 @@ import typing as t
5
5
  import aiohttp
6
6
  from pydantic import BaseModel
7
7
 
8
- from tonutils.clients.http.providers.base import HttpProvider
9
- from tonutils.clients.http.providers.tonapi.models import (
10
- BlockchainAccountMethodResult,
8
+ from tonutils.clients.http.provider.base import HttpProvider
9
+ from tonutils.clients.http.provider.models import (
10
+ BlockchainMessagePayload,
11
+ BlockchainConfigResult,
11
12
  BlockchainAccountResult,
12
13
  BlockchainAccountTransactionsResult,
13
- BlockchainConfigResult,
14
- BlockchainMessagePayload,
14
+ BlockchainAccountMethodResult,
15
15
  )
16
16
  from tonutils.types import NetworkGlobalID, RetryPolicy
17
17
 
@@ -21,6 +21,7 @@ class TonapiHttpProvider(HttpProvider):
21
21
  def __init__(
22
22
  self,
23
23
  network: NetworkGlobalID,
24
+ *,
24
25
  api_key: str,
25
26
  base_url: t.Optional[str] = None,
26
27
  timeout: float = 10.0,
@@ -92,12 +93,11 @@ class TonapiHttpProvider(HttpProvider):
92
93
  limit: int = 100,
93
94
  after_lt: t.Optional[int] = None,
94
95
  before_lt: t.Optional[int] = None,
95
- sort_order: str = "desc",
96
96
  ) -> BlockchainAccountTransactionsResult:
97
- params = {"limit": limit, "sort_order": sort_order}
97
+ params = {"limit": limit}
98
98
  if after_lt is not None:
99
99
  params["after_lt"] = after_lt
100
- if before_lt is not None and before_lt > 0:
100
+ if before_lt is not None:
101
101
  params["before_lt"] = before_lt
102
102
 
103
103
  return self._model(
@@ -3,14 +3,14 @@ import typing as t
3
3
  import aiohttp
4
4
  from pydantic import BaseModel
5
5
 
6
- from tonutils.clients.http.providers.base import HttpProvider
7
- from tonutils.clients.http.providers.toncenter.models import (
8
- GetAddressInformationResult,
9
- GetConfigAllResult,
10
- GetTransactionResult,
11
- RunGetMethodResul,
6
+ from tonutils.clients.http.provider.base import HttpProvider
7
+ from tonutils.clients.http.provider.models import (
12
8
  SendBocPayload,
9
+ GetConfigAllResult,
10
+ GetAddressInformationResult,
11
+ GetTransactionsResult,
13
12
  RunGetMethodPayload,
13
+ RunGetMethodResul,
14
14
  )
15
15
  from tonutils.types import NetworkGlobalID, RetryPolicy
16
16
 
@@ -20,6 +20,7 @@ class ToncenterHttpProvider(HttpProvider):
20
20
  def __init__(
21
21
  self,
22
22
  network: NetworkGlobalID,
23
+ *,
23
24
  api_key: t.Optional[str] = None,
24
25
  base_url: t.Optional[str] = None,
25
26
  timeout: float = 10.0,
@@ -85,19 +86,26 @@ class ToncenterHttpProvider(HttpProvider):
85
86
  ),
86
87
  )
87
88
 
88
- async def get_transaction(
89
+ async def get_transactions(
89
90
  self,
90
91
  address: str,
91
92
  limit: int = 100,
92
- from_lt: t.Optional[int] = None,
93
- to_lt: int = 0,
94
- ) -> GetTransactionResult:
95
- params = {"address": address, "limit": limit, "to_lt": to_lt}
96
- if from_lt is not None:
97
- params["from_lt"] = from_lt
93
+ lt: t.Optional[int] = None,
94
+ from_hash: t.Optional[str] = None,
95
+ to_lt: t.Optional[int] = None,
96
+ ) -> GetTransactionsResult:
97
+ params = {"address": address, "limit": limit, "archival": "true"}
98
+
99
+ # lt and hash must be used together
100
+ if lt is not None and from_hash is not None:
101
+ params["lt"] = lt
102
+ params["hash"] = from_hash
103
+
104
+ if to_lt is not None:
105
+ params["to_lt"] = to_lt
98
106
 
99
107
  return self._model(
100
- GetTransactionResult,
108
+ GetTransactionsResult,
101
109
  await self.send_http_request(
102
110
  "GET",
103
111
  "/getTransactions",
@@ -4,11 +4,10 @@ import time
4
4
 
5
5
  class RateLimiter:
6
6
  """
7
- Asynchronous token-bucket rate limiter with optional priority acquisition.
7
+ Asynchronous token-bucket rate limiter with priority support.
8
8
 
9
- Limits the number of acquire operations per time period and supports
10
- priority waiters that can bypass non-priority requests when tokens
11
- become available.
9
+ Priority requests are served before non-priority requests when
10
+ tokens become available.
12
11
  """
13
12
 
14
13
  __slots__ = (
@@ -26,7 +25,7 @@ class RateLimiter:
26
25
 
27
26
  :param max_rate: Maximum number of acquisitions allowed per period.
28
27
  :param period: Period length in seconds.
29
- :raises ValueError: If ``max_rate`` or ``period`` is not positive.
28
+ :raises ValueError: If max_rate or period is not positive.
30
29
  """
31
30
  if max_rate <= 0:
32
31
  raise ValueError("max_rate must be > 0")
@@ -40,76 +39,79 @@ class RateLimiter:
40
39
  self._cond = asyncio.Condition()
41
40
  self._priority_waiters = 0
42
41
 
43
- def when_ready(self) -> float:
44
- """
45
- Calculate delay until the next token becomes available.
46
-
47
- :return: Number of seconds to wait before a token can be acquired,
48
- or ``0`` if a token is available immediately.
49
- """
42
+ def _refill(self) -> None:
43
+ """Refill tokens based on elapsed time."""
50
44
  now = time.monotonic()
51
- tokens = self._peek_tokens(now)
52
- if tokens >= 1.0:
45
+ elapsed = now - self._updated_at
46
+ if elapsed > 0:
47
+ rate = self._max_rate / self._period
48
+ self._tokens = min(float(self._max_rate), self._tokens + elapsed * rate)
49
+ self._updated_at = now
50
+
51
+ def _seconds_to_token(self) -> float:
52
+ """Calculate seconds until next token is available."""
53
+ if self._tokens >= 1.0:
53
54
  return 0.0
54
- return self._seconds_to_one_token(tokens)
55
+ missing = 1.0 - self._tokens
56
+ rate = self._max_rate / self._period
57
+ return missing / rate
55
58
 
56
59
  async def acquire(self, priority: bool = False) -> None:
57
60
  """
58
- Acquire a single token, waiting asynchronously if necessary.
61
+ Acquire a single token, waiting if necessary.
59
62
 
60
- Priority acquisitions are allowed to bypass non-priority waiters
61
- when tokens become available.
63
+ Priority requests bypass non-priority waiters when tokens
64
+ become available.
62
65
 
63
- :param priority: Whether to acquire the token with priority.
66
+ :param priority: Whether to acquire with priority.
64
67
  """
65
- if priority:
66
- async with self._cond:
67
- self._priority_waiters += 1
68
+ async with self._cond:
69
+ is_waiting = False
68
70
 
69
71
  try:
70
- await self._acquire(priority=True)
72
+ while True:
73
+ self._refill()
74
+
75
+ # Check if token available
76
+ if self._tokens >= 1.0:
77
+ # Priority always takes; non-priority only if no priority waiting
78
+ if priority or self._priority_waiters == 0:
79
+ self._tokens -= 1.0
80
+ self._cond.notify_all()
81
+ return
82
+
83
+ # Register as priority waiter only when actually waiting
84
+ if priority and not is_waiting:
85
+ self._priority_waiters += 1
86
+ is_waiting = True
87
+
88
+ # Wait for token
89
+ wait_time = self._seconds_to_token()
90
+ if wait_time > 0:
91
+ try:
92
+ await asyncio.wait_for(self._cond.wait(), timeout=wait_time)
93
+ except asyncio.TimeoutError:
94
+ pass # Expected — token should be ready now
95
+ else:
96
+ # Token available but blocked by priority — wait for notify
97
+ await self._cond.wait()
98
+
71
99
  finally:
72
- async with self._cond:
100
+ if is_waiting:
73
101
  self._priority_waiters -= 1
74
102
  self._cond.notify_all()
75
- return
76
103
 
77
- await self._acquire(priority=False)
78
-
79
- async def _acquire(self, priority: bool) -> None:
80
- while True:
81
- async with self._cond:
82
- now = time.monotonic()
83
- self._refill(now)
84
-
85
- if self._tokens >= 1.0 and (priority or self._priority_waiters == 0):
86
- self._tokens -= 1.0
87
- self._cond.notify_all()
88
- return
89
-
90
- if self._tokens < 1.0:
91
- timeout = self._seconds_to_one_token(self._tokens)
92
- await asyncio.wait_for(self._cond.wait(), timeout=timeout)
93
- else:
94
- await self._cond.wait()
104
+ def when_ready(self) -> float:
105
+ """
106
+ Calculate delay until the next token becomes available.
95
107
 
96
- def _peek_tokens(self, now: float) -> float:
108
+ :return: Seconds to wait, or 0 if ready immediately.
109
+ """
110
+ now = time.monotonic()
97
111
  elapsed = now - self._updated_at
98
- if elapsed <= 0.0:
99
- return self._tokens
100
-
101
112
  rate = self._max_rate / self._period
102
- tokens = self._tokens + elapsed * rate
103
- return min(float(self._max_rate), tokens)
104
-
105
- def _refill(self, now: float) -> None:
106
- self._tokens = self._peek_tokens(now)
107
- self._updated_at = now
113
+ tokens = min(float(self._max_rate), self._tokens + elapsed * rate)
108
114
 
109
- def _seconds_to_one_token(self, tokens: float) -> float:
110
- missing = 1.0 - tokens
111
- if missing <= 0.0:
115
+ if tokens >= 1.0:
112
116
  return 0.0
113
-
114
- rate = self._max_rate / self._period
115
- return missing / rate
117
+ return (1.0 - tokens) / rate
@@ -55,12 +55,12 @@ class ClientProtocol(t.Protocol):
55
55
  ) -> ContractStateInfo:
56
56
  """Fetch basic contract state information."""
57
57
 
58
- async def get_contract_transactions(
58
+ async def get_transactions(
59
59
  self,
60
60
  address: AddressLike,
61
61
  limit: int = 100,
62
62
  from_lt: t.Optional[int] = None,
63
- to_lt: int = 0,
63
+ to_lt: t.Optional[int] = None,
64
64
  ) -> t.List[Transaction]:
65
65
  """Fetch contract transactions."""
66
66
 
@@ -29,7 +29,7 @@ from tonutils.types import (
29
29
  WorkchainID,
30
30
  DEFAULT_SENDMODE,
31
31
  )
32
- from tonutils.utils import resolve_wallet_address, to_cell
32
+ from tonutils.utils import to_cell
33
33
 
34
34
  _D = t.TypeVar("_D", bound=BaseWalletData)
35
35
  _C = t.TypeVar("_C", bound=BaseWalletConfig)
@@ -325,7 +325,7 @@ class BaseWallet(BaseContract, WalletProtocol[_D, _C, _P], abc.ABC):
325
325
  """
326
326
  Build and send a transfer to a single destination.
327
327
 
328
- :param destination: Recipient address (Address, string, or domain)
328
+ :param destination: Recipient address
329
329
  :param amount: Amount to send in nanotons
330
330
  :param body: Optional message body (Cell or text comment)
331
331
  :param state_init: Optional StateInit for contract deployment
@@ -334,7 +334,6 @@ class BaseWallet(BaseContract, WalletProtocol[_D, _C, _P], abc.ABC):
334
334
  :param params: Optional transaction parameters
335
335
  :return: Signed external message that was sent
336
336
  """
337
- destination = await resolve_wallet_address(self.client, destination)
338
337
  message = TONTransferBuilder(
339
338
  destination=destination,
340
339
  amount=amount,
@@ -23,7 +23,6 @@ from tonutils.utils import (
23
23
  cell_to_b64,
24
24
  normalize_hash,
25
25
  to_nano,
26
- resolve_wallet_address,
27
26
  )
28
27
 
29
28
 
@@ -191,7 +190,7 @@ class TONTransferBuilder(BaseMessageBuilder):
191
190
  """
192
191
  Initialize TON transfer builder.
193
192
 
194
- :param destination: Recipient address (Address, string, or domain)
193
+ :param destination: Recipient address
195
194
  :param amount: Amount to send in nanotons
196
195
  :param body: Optional message body (Cell or text comment string)
197
196
  :param state_init: Optional StateInit for contract deployment
@@ -214,11 +213,10 @@ class TONTransferBuilder(BaseMessageBuilder):
214
213
  :param wallet: Wallet instance to build message for
215
214
  :return: WalletMessage with TON transfer
216
215
  """
217
- destination = await resolve_wallet_address(wallet.client, self.destination)
218
216
  return WalletMessage(
219
217
  send_mode=self.send_mode,
220
218
  message=InternalMessage(
221
- dest=destination,
219
+ dest=self.destination,
222
220
  value=self.amount,
223
221
  body=self.body,
224
222
  state_init=self.state_init,
@@ -277,9 +275,8 @@ class NFTTransferBuilder(BaseMessageBuilder):
277
275
  :param wallet: Wallet instance to build message for
278
276
  :return: WalletMessage with NFT transfer
279
277
  """
280
- destination = await resolve_wallet_address(wallet.client, self.destination)
281
278
  body = NFTTransferBody(
282
- destination=destination,
279
+ destination=self.destination,
283
280
  response_address=self.response_address or wallet.address,
284
281
  custom_payload=self.custom_payload,
285
282
  forward_payload=self.forward_payload,
@@ -358,7 +355,6 @@ class JettonTransferBuilder(BaseMessageBuilder):
358
355
  :param wallet: Wallet instance to build message for
359
356
  :return: WalletMessage with jetton transfer
360
357
  """
361
- destination = await resolve_wallet_address(wallet.client, self.destination)
362
358
  jetton_wallet_address = self.jetton_wallet_address
363
359
  if self.jetton_wallet_address is None:
364
360
  jetton_wallet_address = await get_wallet_address_get_method(
@@ -367,7 +363,7 @@ class JettonTransferBuilder(BaseMessageBuilder):
367
363
  owner_address=wallet.address,
368
364
  )
369
365
  body = JettonTransferBody(
370
- destination=destination,
366
+ destination=self.destination,
371
367
  jetton_amount=self.jetton_amount,
372
368
  response_address=self.response_address or wallet.address,
373
369
  custom_payload=self.custom_payload,
File without changes
File without changes
File without changes
File without changes
File without changes