Skip to content

Commit

Permalink
Merge branch 'yungwine:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
crazyministr authored Feb 15, 2024
2 parents 7f86bf5 + 12508f0 commit 5c1aab2
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 68 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest pytest-asyncio
python -m pip install flake8 pytest==7.4.2 pytest-asyncio
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
Expand Down
1 change: 1 addition & 0 deletions pytoniq/contract/wallets/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .wallet import WalletError, Wallet, BaseWallet, WalletV3, WalletV4, WalletV3R1, WalletV3R2, WalletV4R2, WalletV3Data, WalletV4Data, WalletMessage
from .highload import HighloadWallet
2 changes: 1 addition & 1 deletion pytoniq/contract/wallets/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def create_wallet_internal_message(destination: Address, send_mode: int = 3, val
if isinstance(body, str):
body = Builder()\
.store_uint(0, 32)\
.store_string(body)\
.store_snake_string(body)\
.end_cell()

message = Contract.create_internal_msg(dest=destination, value=value, body=body, state_init=state_init, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion pytoniq/liteclient/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import typing

from .client import LiteClient, LiteClientError, RunGetMethodError, BlockId, BlockIdExt
from .client import LiteClient, LiteClientError, RunGetMethodError, BlockId, BlockIdExt, LiteServerError
from .balancer import LiteBalancer, BalancerError

LiteClientLike = typing.Union[LiteClient, LiteBalancer]
73 changes: 37 additions & 36 deletions pytoniq/liteclient/balancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def _check_errors(self, client: LiteClient):
if not task.cancelled():
self._logger.debug(f'client task {task} failed with exception: {task.exception()}')
return True
return False
return False

async def _check_peers(self):
while True:
Expand Down Expand Up @@ -213,14 +213,14 @@ def _delete_unsync_peers(self):
self._alive_peers.discard(i)

async def execute_method(self, method_name_: str, *args, **kwargs) -> typing.Union[dict, typing.Any]:
only_archive = kwargs.pop('only_archive', False)
choose_random = kwargs.pop('choose_random', False)

for _ in range(self.max_retries):

if not len(self._alive_peers):
raise BalancerError(f'have no alive peers')

only_archive = kwargs.pop('only_archive', False)
choose_random = kwargs.pop('choose_random', False)

if only_archive and choose_random:
raise BalancerError('Currently you cant execute method for both random and archive peer')

Expand Down Expand Up @@ -267,97 +267,98 @@ def _get_args(locals_: dict):
"""CODE BELOW IS AUTOGENERATED. DO NOT EDIT MANUALLY"""

async def get_masterchain_info(self, **kwargs):
return await self.execute_method('get_masterchain_info', **self._get_args(locals()))
return await self.execute_method('get_masterchain_info', **self._get_args(locals()))

async def raw_wait_masterchain_seqno(self, seqno: int, timeout_ms: int, suffix: bytes = b'', **kwargs):
return await self.execute_method('raw_wait_masterchain_seqno', **self._get_args(locals()))
return await self.execute_method('raw_wait_masterchain_seqno', **self._get_args(locals()))

async def wait_masterchain_seqno(self, seqno: int, timeout_ms: int, schema_name: str, data: dict = None, **kwargs):
return await self.execute_method('wait_masterchain_seqno', **self._get_args(locals()))
return await self.execute_method('wait_masterchain_seqno', **self._get_args(locals()))

async def get_masterchain_info_ext(self, **kwargs):
return await self.execute_method('get_masterchain_info_ext', **self._get_args(locals()))
return await self.execute_method('get_masterchain_info_ext', **self._get_args(locals()))

async def get_time(self, **kwargs):
return await self.execute_method('get_time', **self._get_args(locals()))
return await self.execute_method('get_time', **self._get_args(locals()))

async def get_version(self, **kwargs):
return await self.execute_method('get_version', **self._get_args(locals()))
return await self.execute_method('get_version', **self._get_args(locals()))

async def get_state(self, wc: int, shard: typing.Optional[int],
seqno: int, root_hash: typing.Union[str, bytes],
file_hash: typing.Union[str, bytes]
, **kwargs) -> dict:
return await self.execute_method('get_state', **self._get_args(locals()))
return await self.execute_method('get_state', **self._get_args(locals()))

async def raw_get_block_header(self, block: BlockIdExt, **kwargs) -> Block:
return await self.execute_method('raw_get_block_header', **self._get_args(locals()))
return await self.execute_method('raw_get_block_header', **self._get_args(locals()))

async def get_block_header(self, wc: int, shard: typing.Optional[int], seqno: int,
root_hash: typing.Union[str, bytes],
file_hash: typing.Union[str, bytes]
, **kwargs) -> Block:
return await self.execute_method('get_block_header', **self._get_args(locals()))
return await self.execute_method('get_block_header', **self._get_args(locals()))

async def lookup_block(self, wc: int, shard: int, seqno: int = -1,
lt: typing.Optional[int] = None,
utime: typing.Optional[int] = None, **kwargs) -> typing.Tuple[BlockIdExt, Block]:
return await self.execute_method('lookup_block', **self._get_args(locals()))
return await self.execute_method('lookup_block', **self._get_args(locals()))

async def raw_get_block(self, block: BlockIdExt, **kwargs) -> Block:
return await self.execute_method('raw_get_block', **self._get_args(locals()))
return await self.execute_method('raw_get_block', **self._get_args(locals()))

async def get_block(self, wc: int, shard: typing.Optional[int],
seqno: int, root_hash: typing.Union[str, bytes],
file_hash: typing.Union[str, bytes], **kwargs) -> Block:
return await self.execute_method('get_block', **self._get_args(locals()))
return await self.execute_method('get_block', **self._get_args(locals()))

async def raw_get_account_state(self, address: typing.Union[str, Address],
block: typing.Optional[BlockIdExt] = None
, **kwargs) -> typing.Tuple[typing.Optional[Account], typing.Optional[ShardAccount]]:
return await self.execute_method('raw_get_account_state', **self._get_args(locals()))
return await self.execute_method('raw_get_account_state', **self._get_args(locals()))

async def get_account_state(self, address: typing.Union[str, Address], **kwargs) -> SimpleAccount:
return await self.execute_method('get_account_state', **self._get_args(locals()))
return await self.execute_method('get_account_state', **self._get_args(locals()))

async def run_get_method(self, address: typing.Union[Address, str],
method: typing.Union[int, str], stack: list,
block: BlockIdExt = None
, **kwargs) -> list:
return await self.execute_method('run_get_method', **self._get_args(locals()))
return await self.execute_method('run_get_method', **self._get_args(locals()))

async def raw_get_shard_info(self, block: typing.Optional[BlockIdExt] = None,
wc: int = 0, shard: int = -9223372036854775808,
exact: bool = True
, **kwargs) -> ShardDescr:
return await self.execute_method('raw_get_shard_info', **self._get_args(locals()))
return await self.execute_method('raw_get_shard_info', **self._get_args(locals()))

async def raw_get_all_shards_info(self, block: typing.Optional[BlockIdExt] = None, **kwargs) -> typing.Dict[int, BinTree]:
return await self.execute_method('raw_get_all_shards_info', **self._get_args(locals()))
return await self.execute_method('raw_get_all_shards_info', **self._get_args(locals()))

async def get_all_shards_info(self, block: typing.Optional[BlockIdExt] = None, **kwargs) -> typing.List[BlockIdExt]:
return await self.execute_method('get_all_shards_info', **self._get_args(locals()))
return await self.execute_method('get_all_shards_info', **self._get_args(locals()))

async def get_one_transaction(self, address: typing.Union[Address, str],
lt: int, block: BlockIdExt
, **kwargs) -> typing.Optional[Transaction]:
return await self.execute_method('get_one_transaction', **self._get_args(locals()))
return await self.execute_method('get_one_transaction', **self._get_args(locals()))

async def raw_get_transactions(self, address: typing.Union[Address, str], count: int,
from_lt: int = None, from_hash: typing.Optional[bytes] = None
, **kwargs) -> typing.Tuple[typing.List[Transaction], typing.List[BlockIdExt]]:
return await self.execute_method('raw_get_transactions', **self._get_args(locals()))
return await self.execute_method('raw_get_transactions', **self._get_args(locals()))

async def get_transactions(self, address: typing.Union[Address, str], count: int,
from_lt: int = None, from_hash: typing.Optional[bytes] = None
from_lt: int = None, from_hash: typing.Optional[bytes] = None,
to_lt: int = 0
, **kwargs) -> typing.List[Transaction]:
return await self.execute_method('get_transactions', **self._get_args(locals()))
return await self.execute_method('get_transactions', **self._get_args(locals()))

async def raw_get_block_transactions(self, block: BlockIdExt, count: int = 1024, **kwargs) -> typing.List[dict]:
return await self.execute_method('raw_get_block_transactions', **self._get_args(locals()))
return await self.execute_method('raw_get_block_transactions', **self._get_args(locals()))

async def raw_get_block_transactions_ext(self, block: BlockIdExt, count: int = 1024, **kwargs) -> typing.List[Transaction]:
return await self.execute_method('raw_get_block_transactions_ext', **self._get_args(locals()))
return await self.execute_method('raw_get_block_transactions_ext', **self._get_args(locals()))

async def raw_get_mc_block_proof(self, known_block: BlockIdExt, target_block: typing.Optional[BlockIdExt] = None,
return_best_key_block=False
Expand All @@ -367,28 +368,28 @@ async def raw_get_mc_block_proof(self, known_block: BlockIdExt, target_block: ty
typing.Optional[BlockIdExt],
typing.Optional[int]
]:
return await self.execute_method('raw_get_mc_block_proof', **self._get_args(locals()))
return await self.execute_method('raw_get_mc_block_proof', **self._get_args(locals()))

async def get_mc_block_proof(self, known_block: BlockIdExt,
target_block: BlockIdExt,
return_best_key_block=False
, **kwargs) -> typing.Tuple[typing.Optional[BlockIdExt], int]:
return await self.execute_method('get_mc_block_proof', **self._get_args(locals()))
return await self.execute_method('get_mc_block_proof', **self._get_args(locals()))

async def prove_block(self, target_block: BlockIdExt, **kwargs) -> None:
return await self.execute_method('prove_block', **self._get_args(locals()))
return await self.execute_method('prove_block', **self._get_args(locals()))

async def get_config_all(self, blk: typing.Optional[BlockIdExt] = None, **kwargs) -> dict:
return await self.execute_method('get_config_all', **self._get_args(locals()))
return await self.execute_method('get_config_all', **self._get_args(locals()))

async def get_config_params(self, params: typing.List[int], blk: typing.Optional[BlockIdExt] = None, **kwargs) -> dict:
return await self.execute_method('get_config_params', **self._get_args(locals()))
return await self.execute_method('get_config_params', **self._get_args(locals()))

async def get_libraries(self, library_list: typing.List[bytes], **kwargs):
return await self.execute_method('get_libraries', **self._get_args(locals()))
async def get_libraries(self, library_list: typing.List[typing.Union[bytes, str]], **kwargs):
return await self.execute_method('get_libraries', **self._get_args(locals()))

async def get_shard_block_proof(self, blk: BlockIdExt, prove_mc: bool = False, **kwargs):
return await self.execute_method('get_shard_block_proof', **self._get_args(locals()))
return await self.execute_method('get_shard_block_proof', **self._get_args(locals()))

"""CODE ABOVE IS AUTOGENERATED. DO NOT EDIT MANUALLY"""

Expand Down
46 changes: 38 additions & 8 deletions pytoniq/liteclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,19 @@ class LiteClientError(Exception):
pass


class LiteServerError(LiteClientError):
def __init__(self, code, message):
self.code = code
self.message = message
super().__init__(f'Liteserver crashed with {code} code. Message: {message}')


class RunGetMethodError(LiteClientError):
def __init__(self, address: typing.Any, method: typing.Any, exit_code: int):
self.address = address
self.method = method
self.exit_code = exit_code
super().__init__(f'get method "{method}" for account {address} returned exit code {exit_code}')
super().__init__(f'Get method "{method}" for account {address} returned exit code {exit_code}')


class LiteClient:
Expand Down Expand Up @@ -246,7 +253,7 @@ async def liteserver_query(self, query: bytes, qid: str) -> dict:
result = resp.result()

if 'code' in result and 'message' in result:
raise LiteClientError(f'LiteClient crashed with {result["code"]} code. Message: {result["message"]}')
raise LiteServerError(result["code"], result["message"])

return resp.result()

Expand Down Expand Up @@ -639,21 +646,32 @@ async def raw_get_transactions(self, address: typing.Union[Address, str], count:
return tr_result, block_ids

async def get_transactions(self, address: typing.Union[Address, str], count: int,
from_lt: int = None, from_hash: typing.Optional[bytes] = None
from_lt: int = None, from_hash: typing.Optional[bytes] = None,
to_lt: int = 0
) -> typing.List[Transaction]:
"""
Returns account transactions
:param address:
:param count:
:param from_lt:
:param from_hash:
:param to_lt:
:return:
"""
result: typing.List[Transaction] = []
reach_lt = False

for i in range(0, count, 16):
amount = min(16, count - i)
tr_result, block_ids = await self.raw_get_transactions(address, amount, from_lt, from_hash)
tr_result, _ = await self.raw_get_transactions(address, amount, from_lt, from_hash)
if to_lt > 0 and tr_result[-1].lt <= to_lt:
for j, t in enumerate(tr_result):
if t.lt <= to_lt:
result += tr_result[:j]
reach_lt = True
break
if reach_lt:
break
result += tr_result
from_lt, from_hash = result[-1].prev_trans_lt, result[-1].prev_trans_hash
if from_lt == 0:
Expand Down Expand Up @@ -905,12 +923,22 @@ async def get_config_params(self, params: typing.List[int], blk: typing.Optional
state_proof = Cell.one_from_boc(result['state_proof'])
return self.unpack_config(blk, config_proof, state_proof)

async def get_libraries(self, library_list: typing.List[bytes]):
async def get_libraries(self, library_list: typing.List[typing.Union[bytes, str]]):
if len(library_list) > 16:
raise LiteClientError('maximum libraries num could be requested is 16')
library_list = [lib.hex() if isinstance(lib, bytes) else lib for lib in library_list]
data = {'library_list': library_list}

result = await self.liteserver_request('getLibraries', data)

return result['result']
libs = result['result']

if self.trust_level < 2:
for i, lib in enumerate(libs):
if Cell.one_from_boc(lib['data']).hash.hex() != library_list[i]:
raise LiteClientError('library hash mismatch')

return libs

async def get_shard_block_proof(self, blk: BlockIdExt, prove_mc: bool = False):
data = {'id': blk.to_dict()}
Expand All @@ -928,10 +956,12 @@ def check_shard_in_master(proof: Cell, blk: BlockIdExt):
shard = None
for sh in shards:
sh: ShardDescr
if sh.seq_no == blk.seqno and sh.next_validator_shard_signed == blk.shard:
if sh is not None and sh.seq_no == blk.seqno and sh.next_validator_shard_signed == blk.shard:
shard = sh.__dict__

if shard is None:
raise LiteClientError('shard not found in masterchain')
shardblk = BlockIdExt.from_dict(shard)
shardblk.shard = shard['next_validator_shard_signed']
shardblk.seqno = shard['seq_no']
shardblk.workchain = blk.workchain
return shardblk
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="pytoniq",
version="0.1.24",
version="0.1.30",
author="Maksim Kurbatov",
author_email="[email protected]",
description="TON Blockchain SDK",
Expand All @@ -22,7 +22,7 @@
python_requires='>=3.9',
py_modules=["pytoniq"],
install_requires=[
"pytoniq-core>=0.1.15",
"pytoniq-core>=0.1.23",
"requests>=2.31.0",
"setuptools>=65.5.1",
]
Expand Down
Loading

0 comments on commit 5c1aab2

Please sign in to comment.