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