{"id":13409994,"url":"https://github.com/yungwine/pytoniq","last_synced_at":"2025-05-16T10:05:34.845Z","repository":{"id":169376680,"uuid":"645308861","full_name":"yungwine/pytoniq","owner":"yungwine","description":"TON Blockchain SDK with native ADNL protocols implementations","archived":false,"fork":false,"pushed_at":"2025-02-07T07:15:40.000Z","size":419,"stargazers_count":114,"open_issues_count":19,"forks_count":38,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-28T11:49:38.129Z","etag":null,"topics":["adnl","blockchain","python","ton"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yungwine.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-05-25T11:19:33.000Z","updated_at":"2025-04-14T16:53:30.000Z","dependencies_parsed_at":"2024-01-12T12:31:29.180Z","dependency_job_id":"372a968b-2c45-48d9-8fae-dc17196a0b2e","html_url":"https://github.com/yungwine/pytoniq","commit_stats":null,"previous_names":["yungwine/tonpylib"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yungwine%2Fpytoniq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yungwine%2Fpytoniq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yungwine%2Fpytoniq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yungwine%2Fpytoniq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yungwine","download_url":"https://codeload.github.com/yungwine/pytoniq/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254509476,"owners_count":22082891,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adnl","blockchain","python","ton"],"created_at":"2024-07-30T20:01:04.403Z","updated_at":"2025-05-16T10:05:34.827Z","avatar_url":"https://github.com/yungwine.png","language":"Python","funding_links":[],"categories":["🧑‍💻 Development"],"sub_categories":["Libraries \u0026 SDKs"],"readme":"# pytoniq\n\n[![PyPI version](https://badge.fury.io/py/pytoniq.svg)](https://badge.fury.io/py/pytoniq) \n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pytoniq)](https://pypi.org/project/pytoniq/)\n[![Downloads](https://static.pepy.tech/badge/pytoniq)](https://pepy.tech/project/pytoniq)\n[![Downloads](https://static.pepy.tech/badge/pytoniq/month)](https://pepy.tech/project/pytoniq)\n[![](https://img.shields.io/badge/%F0%9F%92%8E-TON-grey)](https://ton.org)\n\nPytoniq is a Python SDK for the TON Blockchain. This library extends [pytoniq-core](https://github.com/yungwine/pytoniq-core) with native `LiteClient` and `ADNL`.\n\nIf you have any questions join Python - TON [developers chat](https://t.me/pythonnton).\n\n## Documentation\n[GitBook](https://yungwine.gitbook.io/pytoniq-doc/)\n\n## Installation\n\n```commandline\npip install pytoniq \n```\n\n## Examples\nYou can find them in the [examples](examples/) folder.\n\n## LiteClient\n\n### General LiteClient usage examples\n\n#### Client initializing\n\n```python\nfrom pytoniq import LiteClient\n\n\nasync def main():\n    client = LiteClient.from_mainnet_config(  # choose mainnet, testnet or custom config dict\n        ls_i=0,  # index of liteserver from config\n        trust_level=2,  # trust level to liteserver\n        timeout=15  # timeout not includes key blocks synchronization as it works in pytonlib\n    )\n\n    await client.connect()\n    \n    await client.get_masterchain_info()\n\n    await client.reconnect()  # can reconnect to an exising object if had any errors\n\n    await client.close()\n    \n    \"\"\" or use it with context manager: \"\"\"\n    async with LiteClient.from_mainnet_config(ls_i=0, trust_level=2, timeout=15) as client:\n        await client.get_masterchain_info()\n\n```\n\n#### Blocks transactions scanning\n\nSee `BlockScanner` code [here](examples/blocks/block_scanner.py).\n\n```python\nfrom pytoniq_core import BlockIdExt\nfrom pytoniq import LiteClient\nfrom examples.blocks.block_scanner import BlockScanner  # this import is not available if downloaded from pypi\n\nasync def handle_block(block: BlockIdExt):\n    if block.workchain == -1:  # skip masterchain blocks\n        return\n    print(block)\n    transactions = await client.raw_get_block_transactions_ext(block)\n    for transaction in transactions:\n        print(transaction.in_msg)\n\n\nclient = LiteClient.from_mainnet_config(ls_i=14, trust_level=0, timeout=20)\n\n\nasync def main():\n\n    await client.connect()\n    await BlockScanner(client=client, block_handler=handle_block).run()\n```\n\n## LiteBalancer\n\n`LiteBalancer` is constantly pinging LiteServers to identify \"alive\" peers.\nWhen you make a request through `LiteBalancer`, it forwards the request to the \"best\" peer - \nthe \"alive\" peer with the maximum last masterchain block seqno among all and minimum average response time.\n\n`LiteBalancer` can also retry the request if a `asyncio.TimeoutError` occurs, but this must be explicitly set using the\n`LiteBalancer.set_max_retries(retries_num)` method.\n\n```python\nclient = LiteBalancer.from_mainnet_config(trust_level=1)\n\nawait client.start_up()\n\nresult = await client.run_get_method(address='EQBvW8Z5huBkMJYdnfAEM5JqTNkuWX3diqYENkWsIL0XggGG', method='seqno', stack=[])\n\nawait client.close_all()\n\n\"\"\" or use it with context manager: \"\"\"\n\nasync with LiteBalancer.from_mainnet_config(trust_level=1) as client:\n    result = await client.run_get_method(address='EQBvW8Z5huBkMJYdnfAEM5JqTNkuWX3diqYENkWsIL0XggGG', method='seqno', stack=[])\n\n```\n\nMoreover, one of the most important features of `LiteBalancer` is that it detects [archival](https://docs.ton.org/participate/run-nodes/archive-node#overview) LiteServers,\nso you can do requests only to archival LiteServers providing `True` for argument `only_archive` in **any** method:\n\n```python\n# ask for very very old block\nblk, _ = await client.lookup_block(-1, -2**63, 100, only_archive=True)  \n\n# ask for old block and run get method for that block:\nblk, _ = await client.lookup_block(-1, -2**63, 25000000, only_archive=True)\nresult = await client.run_get_method(address='EQBvW8Z5huBkMJYdnfAEM5JqTNkuWX3diqYENkWsIL0XggGG', method='seqno',\n                                             stack=[], block=blk, only_archive=True)\n\n```\n\n\n### Blockstore\nThe library can prove all data it receives from a Liteserver (Learn about trust levels [here](https://yungwine.gitbook.io/pytoniq-doc/liteclient/trust-levels)).\nIf you want to use `LiteClient` or `LiteBalancer` with the zero trust level, at the first time run library will prove block link from the `init_block` to the last masterchain block.\nLast proved blocks will be stored in the `.blockstore` folder. The file data contains `ttl` and `gen_utime` of the last synced key block, its data serialized according to the `BlockIdExt` TL scheme (but in big–endian), last synced masterchain block data. \nFilename is first 88 bytes of data described above with init block hash.\n\n## ADNL\n\n```python\nfrom pytoniq.adnl.adnl import AdnlTransport, Node\n\nadnl = AdnlTransport(timeout=3)\n\n# start adnl receiving server\nawait adnl.start()\n\n# take peer from public config\npeer = Node('172.104.59.125', 14432, \"/YDNd+IwRUgL0mq21oC0L3RxrS8gTu0nciSPUrhqR78=\", adnl)\nawait adnl.connect_to_peer(peer)\n# or await peer.connect()\n\nawait peer.disconnect()\n\n# send pings\nawait asyncio.sleep(10)\n\n# stop adnl receiving server\nawait adnl.close()\n```\n\n## DHT\n\n```python\nimport time\n\nfrom pytoniq.adnl.adnl import AdnlTransport\nfrom pytoniq.adnl.dht import DhtClient, DhtNode\n\n\nadnl = AdnlTransport(timeout=5)\nclient = DhtClient.from_mainnet_config(adnl)\n\nawait adnl.start()\n\nfoundation_adnl_addr = '516618cf6cbe9004f6883e742c9a2e3ca53ed02e3e36f4cef62a98ee1e449174'\nresp = await client.find_value(key=DhtClient.get_dht_key_id(bytes.fromhex(foundation_adnl_addr)))\nprint(resp)\n#  {'@type': 'dht.valueFound', 'value': {'key': {'key': {'id': '516618cf6cbe9004f6883e742c9a2e3ca53ed02e3e36f4cef62a98ee1e449174', 'name': b'address', 'idx': 0, '@type': 'dht.key'}, 'id': {'key': '927d3e71e3ce651c3f172134d39163f70e4c792169e39f3d520bfad9388ad4ca', '@type': 'pub.ed25519'}, 'update_rule': {'@type': 'dht.updateRule.signature'}, 'signature': b\"g\\x08\\xf8yo\\xed1\\xb83\\x17\\xb9\\x10\\xb4\\x8f\\x00\\x17]D\\xd2\\xae\\xfa\\x87\\x9f\\xf7\\xfa\\x192\\x971\\xee'2\\x83\\x0fk\\x03w\\xbb0\\xfcU\\xc8\\x89Zm\\x8e\\xba\\xce \\xfc\\xde\\xf2F\\xdb\\x0cI*\\xe0\\xaeN\\xef\\xc2\\x9e\\r\", '@type': 'dht.keyDescription'}, 'value': {'@type': 'adnl.addressList', 'addrs': [{'@type': 'adnl.address.udp', 'ip': -1537433966, 'port': 3333}], 'version': 1694227845, 'reinit_date': 1694227845, 'priority': 0, 'expire_at': 0}, 'ttl': 1695832194, 'signature': b'z\\x8aW\\x80k\\xceXQ\\xff\\xb9D{C\\x98T\\x02e\\xef\u0026\\xfc\\xb6\\xde\\x80y\\xf7\\xb4\\x92\\xae\\xd2\\xd0\\xbakU}3\\xfa\\xec\\x03\\xb6v\\x98\\xb0\\xcb\\xe8\\x05\\xb9\\xd0\\x07o\\xb6\\xa0)I\\x17\\xcb\\x1a\\xc4(Dt\\xe6y\\x18\\x0b', '@type': 'dht.value'}}\n\nkey = client.get_dht_key(id_=adnl.client.get_key_id())\nts = int(time.time())\nvalue_data = {\n    'addrs': [\n        {\n            \"@type\": \"adnl.address.udp\",\n            \"ip\": 1111111,\n            \"port\": 12000\n        }\n    ],\n    'version': ts,\n    'reinit_date': ts,\n    'priority': 0,\n    'expire_at': 0,\n}\n\nvalue = client.schemas.serialize(client.schemas.get_by_name('adnl.addressList'), value_data)\n\nstored = await client.store_value(  # store our address list in dht as value\n    key=key,\n    value=value,\n    private_key=adnl.client.ed25519_private.encode(),\n    ttl=100,\n    try_find_after=False\n)\n\nprint(stored)  # True if value was stored, False otherwise\n\n# disconnect from all peers\nawait client.close()\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyungwine%2Fpytoniq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyungwine%2Fpytoniq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyungwine%2Fpytoniq/lists"}