├── .github └── workflows │ └── python-app.yml ├── .gitignore ├── README.md ├── examples └── transfer_usdc_via_theaptosbridge.py ├── poetry.lock ├── pyproject.toml ├── requirements.txt ├── src ├── __init__.py ├── apps │ ├── __init__.py │ ├── bridge.py │ └── lz_app.py ├── const.py ├── endpoint.py ├── executor.py ├── executor_config.py ├── sdk │ ├── __init__.py │ ├── aptos_sdk.py │ └── base_sdk.py ├── uln │ ├── __init__.py │ ├── uln_config.py │ └── uln_signer.py └── utils.py └── tests ├── __init__.py └── unit ├── __init__.py └── test_utils.py /.github/workflows/python-app.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a single version of Python 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python 3 | 4 | name: Python application 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | pull_request: 10 | branches: [ "main" ] 11 | 12 | permissions: 13 | contents: read 14 | 15 | jobs: 16 | build: 17 | 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | - name: Set up Python 3.10 23 | uses: actions/setup-python@v3 24 | with: 25 | python-version: "3.10" 26 | - name: Install dependencies 27 | run: | 28 | python -m pip install --upgrade pip 29 | pip install flake8 pytest 30 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 31 | - name: Lint with flake8 32 | run: | 33 | # stop the build if there are Python syntax errors or undefined names 34 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 35 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 36 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 37 | - name: Test with pytest 38 | run: | 39 | pytest tests 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | js/node_modules 2 | .idea 3 | src/venv 4 | *.pyc 5 | /.pytest_cache/ 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | LayerZero-python-aptos 3 |

4 | 5 |

6 | Brought to you by Let's Code 7 |

8 | 9 |

10 | 13 | 14 | Follow @LetsCodeWeb3 15 | 16 |

17 | 18 | ## About Us 19 | 20 | Since our entrance into the cryptocurrency sphere in 2017, we've discovered that composability is a critical factor for institutions seeking to apply real-world use cases. The companies we've advised come from diverse backgrounds and utilize a wide variety of tech stacks, including PHP, C#, and C++. In this diverse landscape, Aptos has made a significant contribution by offering an official Python SDK, positioning Python as a universal language for scripting various DeFi scenarios. 21 | 22 | However, our enthusiasm was dampened when LayerZero, a key piece in the multichain puzzle, did not follow suit and only provided a JavaScript SDK. Recognizing this gap, we took the initiative to translate the JavaScript SDK into Python, rigorously testing it to ensure a high level of confidence in its functionality. We are excited to make this translated SDK available to the public. 23 | 24 | Our goal was to maintain a code structure and layout similar to the original JavaScript version to keep maintenance costs as low as possible. We look forward to seeing how the community utilizes this tool and any contributions they might make. 25 | 26 | Donations to support our work are greatly appreciated. 27 | 28 | ## Description 29 | The idea behind this repo is to replicate some core bridging functionality 30 | to make someting like LayerZero-aptos-sdk but for Python. 31 | 32 | ## Documentation 33 | 34 | TBD: [@ikapeykin](https://github.com/ikapeykin) 35 | 36 | ## 👨‍💻 Contributors 37 | We are incredibly grateful to all the contributors in open source, and we highly appreciate your efforts. Each commit warms our hearts <3 38 | 39 | [bobu4](https://github.com/bobu4) 40 | -------------------------------------------------------------------------------- /examples/transfer_usdc_via_theaptosbridge.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from aptos_sdk.account import Account 4 | from aptos_sdk.client import RestClient 5 | 6 | from src.apps.bridge import Bridge 7 | from src.endpoint import Endpoint 8 | from src.executor import Executor 9 | 10 | WALLET_RPC = "https://fullnode.mainnet.aptoslabs.com/v1" 11 | 12 | 13 | def get_usdc_balance_aptos_wallet(address: str) -> int: 14 | client = RestClient(WALLET_RPC) 15 | 16 | return int(client.account_resource( 17 | account_address=address, # noqa 18 | resource_type="0x1::coin::CoinStore<0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa::asset::USDC>", 19 | # noqa 20 | )['data']['coin']['value']) 21 | 22 | 23 | def transfer_usdc_via_theaptosbridge(private_key: str, evm_address: str, dst_chain_id: int, amount: int) -> str: 24 | client = RestClient(WALLET_RPC) 25 | account = Account.load_key(private_key) 26 | 27 | bridge = Bridge(private_key=private_key) 28 | endpoint = Endpoint(client) 29 | executor = Executor(client) 30 | adapter_params = executor.get_default_adapter_params(dst_chain_id) 31 | 32 | fee = endpoint.quote_fee( 33 | ua_address=account.address().hex(), 34 | dst_chain_id=dst_chain_id, 35 | adapter_params=adapter_params, 36 | payload_size=74, # CONST 37 | ) 38 | 39 | tx_hash = bridge.send_coin( 40 | amount=amount, 41 | dst_chain_id=dst_chain_id, 42 | dst_receiver=evm_address, 43 | fee=fee, 44 | adapter_params=adapter_params, 45 | ) 46 | 47 | return tx_hash 48 | 49 | 50 | def main(private_key: str, evm_address: str, dst_chain_id: int): 51 | account = Account.load_key(private_key) 52 | 53 | amount = get_usdc_balance_aptos_wallet(address=account.address().hex()) 54 | tx_hash = transfer_usdc_via_theaptosbridge( 55 | private_key=private_key, evm_address=evm_address, dst_chain_id=dst_chain_id, amount=amount 56 | ) 57 | print(f"Transaction hash: {tx_hash}") 58 | 59 | 60 | if __name__ == "__main__": 61 | parser = argparse.ArgumentParser( 62 | description="Example code for transfers from Aptos chain to EVM chain via theaptosbridge." 63 | ) 64 | parser.add_argument( 65 | "--private-key", type=str, required=True, 66 | help="Aptos chain private key", 67 | ) 68 | parser.add_argument( 69 | "--evm-address", type=str, required=True, 70 | help="Destination EVM (Avalanche, Polygon, etc.) public key aka address", 71 | ) 72 | parser.add_argument( 73 | "--dst-chain-id", type=int, required=True, 74 | help="Layerzero destination chain id, e.g. 106 is Avalanche", 75 | ) 76 | 77 | args = parser.parse_args() 78 | main( 79 | private_key=args.private_key, 80 | evm_address=args.evm_address, 81 | dst_chain_id=args.dst_chain_id, 82 | ) 83 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "anyio" 5 | version = "3.7.0" 6 | description = "High level compatibility layer for multiple asynchronous event loop implementations" 7 | optional = false 8 | python-versions = ">=3.7" 9 | files = [ 10 | {file = "anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0"}, 11 | {file = "anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce"}, 12 | ] 13 | 14 | [package.dependencies] 15 | exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} 16 | idna = ">=2.8" 17 | sniffio = ">=1.1" 18 | 19 | [package.extras] 20 | doc = ["Sphinx (>=6.1.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme", "sphinxcontrib-jquery"] 21 | test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] 22 | trio = ["trio (<0.22)"] 23 | 24 | [[package]] 25 | name = "aptos-sdk" 26 | version = "0.6.3" 27 | description = "Aptos SDK" 28 | optional = false 29 | python-versions = ">=3.7,<4.0" 30 | files = [ 31 | {file = "aptos_sdk-0.6.3-py3-none-any.whl", hash = "sha256:f79d4e7e1fb16bcce69e4b032d749f7607b590f801ca9bca6c253a3df3e71d26"}, 32 | {file = "aptos_sdk-0.6.3.tar.gz", hash = "sha256:e94d44e604fbf8da082bf681b33bcc8ccf2d695cf91a11db0f0ae52dac7b88f3"}, 33 | ] 34 | 35 | [package.dependencies] 36 | h2 = ">=4.1.0,<5.0.0" 37 | httpx = ">=0.23.0,<0.24.0" 38 | PyNaCl = ">=1.5.0,<2.0.0" 39 | 40 | [[package]] 41 | name = "certifi" 42 | version = "2023.5.7" 43 | description = "Python package for providing Mozilla's CA Bundle." 44 | optional = false 45 | python-versions = ">=3.6" 46 | files = [ 47 | {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, 48 | {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, 49 | ] 50 | 51 | [[package]] 52 | name = "cffi" 53 | version = "1.15.1" 54 | description = "Foreign Function Interface for Python calling C code." 55 | optional = false 56 | python-versions = "*" 57 | files = [ 58 | {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, 59 | {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, 60 | {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, 61 | {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, 62 | {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, 63 | {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, 64 | {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, 65 | {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, 66 | {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, 67 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, 68 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, 69 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, 70 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, 71 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, 72 | {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, 73 | {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, 74 | {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, 75 | {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, 76 | {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, 77 | {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, 78 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, 79 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, 80 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, 81 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, 82 | {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, 83 | {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, 84 | {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, 85 | {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, 86 | {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, 87 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, 88 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, 89 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, 90 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, 91 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, 92 | {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, 93 | {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, 94 | {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, 95 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, 96 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, 97 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, 98 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, 99 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, 100 | {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, 101 | {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, 102 | {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, 103 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, 104 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, 105 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, 106 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, 107 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, 108 | {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, 109 | {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, 110 | {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, 111 | {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, 112 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, 113 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, 114 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, 115 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, 116 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, 117 | {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, 118 | {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, 119 | {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, 120 | {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, 121 | {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, 122 | ] 123 | 124 | [package.dependencies] 125 | pycparser = "*" 126 | 127 | [[package]] 128 | name = "cytoolz" 129 | version = "0.12.1" 130 | description = "Cython implementation of Toolz: High performance functional utilities" 131 | optional = false 132 | python-versions = ">=3.6" 133 | files = [ 134 | {file = "cytoolz-0.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c59bb4ca88e1c69931468bf21f91c8f64d8bf1999eb163b7a2df336f60c304a"}, 135 | {file = "cytoolz-0.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4d700e011156ff112966c6d77faaae125fcaf538f4cec2b9ce8957de82858f0f"}, 136 | {file = "cytoolz-0.12.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23c3f57c48eb939d2986eba4aeaeedf930ebf94d58c91a42d4e0fc45ed5427dc"}, 137 | {file = "cytoolz-0.12.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25ff13c468c06da9ef26651dc389e7e8bb7af548f8c1dfb96305f57f18d398a8"}, 138 | {file = "cytoolz-0.12.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a734511144309ea6e105406633affb74e303a3df07d8a3954f9b01946e27ecb1"}, 139 | {file = "cytoolz-0.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48bc2f30d1b2646d675bb8e7778ab59379bf9edc59fe06fb0e7f85ba1271bf44"}, 140 | {file = "cytoolz-0.12.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30936ae8fa68b6a1ac8ad6c4bacb5a8a00d51bc6c89f9614a1557b0105d09f8a"}, 141 | {file = "cytoolz-0.12.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:efd1b2da3ee577fcfa723a214f73186aef9674dd5b28242d90443c7a82722b0f"}, 142 | {file = "cytoolz-0.12.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6805b007af3557ee6c20dab491b6e55a8177f5b6845d9e6c653374d540366ba7"}, 143 | {file = "cytoolz-0.12.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a6e63fc67b23830947b51e0a488992e3c904fce825ead565f3904dcf621d05f7"}, 144 | {file = "cytoolz-0.12.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:9e324a94856d88ecf10f34c102d0ded67d7c3cf644153d77e34a29720ce6aa47"}, 145 | {file = "cytoolz-0.12.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:02975e2b1e61e47e9afa311f4c1783d155136fad37c54a1cebfe991c5a0798a1"}, 146 | {file = "cytoolz-0.12.1-cp310-cp310-win32.whl", hash = "sha256:b6569f6038133909cd658dbdcc6fc955f791dc47a7f5b55d2066f742253dcbfe"}, 147 | {file = "cytoolz-0.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:1be368623e46ad3c1ce807e7a436acb119c26001507b31f92ceb21b86e08c386"}, 148 | {file = "cytoolz-0.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:849f461bffa1e7700ccfcb5186df29cd4cdcc9efdb7199cb8b5681dc37045d72"}, 149 | {file = "cytoolz-0.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4284120c978fb7039901bf6e66832cb3e82ac1b2a107512e735bdb04fd5533ed"}, 150 | {file = "cytoolz-0.12.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ec296f01c29c809698eaf677211b6255691295c2b35caab2131e1e7eaadfbac"}, 151 | {file = "cytoolz-0.12.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:37c53f456a1c84566a7d911eec57c4c6280b915ab0600e7671582793cc2769fe"}, 152 | {file = "cytoolz-0.12.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1b6761791973b1e839b8309d5853b40eeb413368e31beaf5f2b6ed44c6fc7cf0"}, 153 | {file = "cytoolz-0.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff478682e8ee6dbaa37201bb71bf4a6eee744006ab000e8f5cea05066fc7c845"}, 154 | {file = "cytoolz-0.12.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:867bebe6be30ee36a836f9b835790762a74f46be8cc339ea57b68dcecdbc1133"}, 155 | {file = "cytoolz-0.12.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7e903df991f0957e2b271a37bb25d28e0d260c52825ae67507d15ca55a935961"}, 156 | {file = "cytoolz-0.12.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e797c4afb1b7962d3205b1959e1051f7e6bfbba29da44042a9efc2391f1feb38"}, 157 | {file = "cytoolz-0.12.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b8eceaa12b7f152b046b67cb053ec2b5b00f73593983de69bc5e63a8aca4a7a8"}, 158 | {file = "cytoolz-0.12.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b575393dd431b8e211de35bd593d831dac870172b16e2b7934f3566b8fc89377"}, 159 | {file = "cytoolz-0.12.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3032c0ba42dee5836d6b57a72a569b65df2c29e8ed266cb900d569003cf933a9"}, 160 | {file = "cytoolz-0.12.1-cp311-cp311-win32.whl", hash = "sha256:c576bd63495150385b8d05eaae775387f378be2fd9805d3ffb4d17c87271fbad"}, 161 | {file = "cytoolz-0.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:421b224dc4157a0d66625acb5798cf50858cfa06a5232d39a8bd6cf1fa88aca3"}, 162 | {file = "cytoolz-0.12.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:be5a454a95797343d0fb1ed02caecae73a023b1393c112951c84f17ec9f4076c"}, 163 | {file = "cytoolz-0.12.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:061387aa39b9c1576c25d0c59142513c09e77a2a07bd5d6211a43c7a758b6f45"}, 164 | {file = "cytoolz-0.12.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14f4dbc3f0ec8f6fc68865489af21dcf042ff007d2737c27bfd73296f15db544"}, 165 | {file = "cytoolz-0.12.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a816bff6bf424753e1ac2441902ceaf37ae6718b745a53f6aa1a60c617fb4f5f"}, 166 | {file = "cytoolz-0.12.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:633f19d1990b1cf9c67dce9c28bf8b5a18e42785d15548607a100e1236384d5d"}, 167 | {file = "cytoolz-0.12.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fa7009c843667868aa8bdb3d68e5ef3d6356dd418b17ed5ca4e1340e82483a5"}, 168 | {file = "cytoolz-0.12.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:1c29dd04e282ddfd45b457e3551075beec9128aa9271245e58ce924bf6e055f8"}, 169 | {file = "cytoolz-0.12.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd35c0be4c46274129dd1678bb911dd4e93d23968b26f4e39cd55bc7cb3b1bac"}, 170 | {file = "cytoolz-0.12.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5158ae6d8dd112d003f677039a3613ca7d2592bfe35d7accf23684edb961fc26"}, 171 | {file = "cytoolz-0.12.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:7eb9e6fa8a82c3d2f519f7d3942898a97792e3895569e9501b9431048289b82f"}, 172 | {file = "cytoolz-0.12.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ac6784cc43aec51a86cf9058a2a343084f8cf46a9281bea5762bfa608127c53b"}, 173 | {file = "cytoolz-0.12.1-cp36-cp36m-win32.whl", hash = "sha256:794cce219bbcb2f36ca220f27d5afd64eaa854e04901bd6f240be156a578b607"}, 174 | {file = "cytoolz-0.12.1-cp36-cp36m-win_amd64.whl", hash = "sha256:695dd8231e4f1bfb9a2363775a6e4e56ad9d2058058f817203a49614f4bfe33b"}, 175 | {file = "cytoolz-0.12.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1bd8017ef0da935a20106272c5f5ff6b1114add1ccb09cfed1ff7ec5cc01c6d"}, 176 | {file = "cytoolz-0.12.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56e1ebf6eb4438b8c45cbe7e7b22fc65df0c9efa97a70d3bf2f51e08b19756a5"}, 177 | {file = "cytoolz-0.12.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:816c2038008ebf50d81171ddfae377f1af9e71d504ec609469dcb0906bfcf2ae"}, 178 | {file = "cytoolz-0.12.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bebe58f7a160db7838eb70990c704db4bdc2d58bd364290fd69be0587be8bac"}, 179 | {file = "cytoolz-0.12.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a72440305f634604827f96810e4469877b89f5c060d6852267650a49b0e3768c"}, 180 | {file = "cytoolz-0.12.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b46ebc463bb45f278a2b94e630061c26e10077cb68d4c93583d8f4199699a5ef"}, 181 | {file = "cytoolz-0.12.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e75e287787e6adafed9d8c3d3e7647c0b5eb460221f9f92d7dfe48b45ba77c0d"}, 182 | {file = "cytoolz-0.12.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:03ab22c9aeb1535f8647d23b6520b0c3d41aaa18d04ef42b352dde1931f2e2b1"}, 183 | {file = "cytoolz-0.12.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b2ac288f27a2689d9e39f4cf4df5437a8eb038eaae515169586c77f9f8fb343a"}, 184 | {file = "cytoolz-0.12.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:97a24c0d0806fcf9a6e75fc18aeb95adc37eb0baf6451f10a2de23ffd815329d"}, 185 | {file = "cytoolz-0.12.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:42c9e5cd2a48a257b1f2402334b48122501f249b8dcf77082f569f2680f185eb"}, 186 | {file = "cytoolz-0.12.1-cp37-cp37m-win32.whl", hash = "sha256:35fae4eaa0eaf9072a5fe2d244a79e65baae4e5ddbe9cc629c5037af800213a2"}, 187 | {file = "cytoolz-0.12.1-cp37-cp37m-win_amd64.whl", hash = "sha256:5af43ca7026ead3dd08b261e4f7163cd2cf3ceaa74fa5a81f7b7ea5d445e41d6"}, 188 | {file = "cytoolz-0.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fcc378fa97f02fbcef090b3611305425d72bd1c0afdd13ef4a82dc67d40638b6"}, 189 | {file = "cytoolz-0.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cc3645cf6b9246cb8e179db2803e4f0d148211d2a2cf22d5c9b5219111cd91a0"}, 190 | {file = "cytoolz-0.12.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b245b824f4705aef0e4a03fafef3ad6cb59ef43cc564cdbf683ee28dfc11ad5"}, 191 | {file = "cytoolz-0.12.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c1964dcb5f250fd13fac210944b20810d61ef4094a17fbbe502ab7a7eaeeace7"}, 192 | {file = "cytoolz-0.12.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f7194a22a4a24f3561cb6ad1cca9c9b2f2cf34cc8d4bce6d6a24c80960323fa8"}, 193 | {file = "cytoolz-0.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1c5434db53f3a94a37ad8aedb231901e001995d899af6ed1165f3d27fa04a6a"}, 194 | {file = "cytoolz-0.12.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b30cd083ef8af4ba66d9fe5cc75c653ede3f2655f97a032db1a14cc8a006719c"}, 195 | {file = "cytoolz-0.12.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bef934bd3e024d512c6c0ad1c66eb173f61d9ccb4dbca8d75f727a5604f7c2f6"}, 196 | {file = "cytoolz-0.12.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37320669c364f7d370392af33cc1034b4563da66c22cd3261e3530f4d30dbe4b"}, 197 | {file = "cytoolz-0.12.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3cb95d23defb2322cddf70efb4af6dac191d95edaa343e8c1f58f1afa4f92ecd"}, 198 | {file = "cytoolz-0.12.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ac5895d5f78dbd8646fe37266655ba4995f9cfec38a86595282fee69e41787da"}, 199 | {file = "cytoolz-0.12.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:499af2aff04f65b4c23de1df08e1d1484a93b23ddaaa0163e44b5070b68356eb"}, 200 | {file = "cytoolz-0.12.1-cp38-cp38-win32.whl", hash = "sha256:aa61e3da751a2dfe95aeca603f3ef510071a136ba9905f61ae6cb5d0696271ad"}, 201 | {file = "cytoolz-0.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:f5b43ce952a5a31441556c55f5f5f5a8e62c28581a0ff2a2c31c04ef992d73bd"}, 202 | {file = "cytoolz-0.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b8b8f88251b84b3877254cdd59c86a1dc6b2b39a03c6c9c067d344ef879562e0"}, 203 | {file = "cytoolz-0.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d72415b0110f7958dd3a5ee98a70166f47bd42ede85e3535669c794d06f57406"}, 204 | {file = "cytoolz-0.12.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8101ab6de5aa0b26a2b5032bc488d430010c91863e701812d65836b03a12f61"}, 205 | {file = "cytoolz-0.12.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2eed428b5e68c28abf2c71195e799850e040d67a27c05f7785319c611665b86a"}, 206 | {file = "cytoolz-0.12.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59641eb1f41cb688b3cb2f98c9003c493a5024325f76b5c02333d08dd972127c"}, 207 | {file = "cytoolz-0.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a48940ff0449ffcf690310bf9228bb57885f7571406ed2fe05c98e299987195"}, 208 | {file = "cytoolz-0.12.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bae431a5985cdb2014be09d37206c288e0d063940cf9539e9769bd2ec26b220"}, 209 | {file = "cytoolz-0.12.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cb8b10405960a8e6801a4702af98ea640130ec6ecfc1208195762de3f5503ba9"}, 210 | {file = "cytoolz-0.12.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c9a16a5b4f54d5c0a131f56b0ca65998a9a74958b5b36840c280edba4f8b907"}, 211 | {file = "cytoolz-0.12.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:49911cb533c96d275e31e7eaeb0742ac3f7afe386a1d8c40937814d75039a0f7"}, 212 | {file = "cytoolz-0.12.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:dbae37d48ef5a0ab90cfaf2b9312d96f034b1c828208a9cbe25377a1b19ba129"}, 213 | {file = "cytoolz-0.12.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c34e69be4429633fc614febe3127fa03aa418a1abb9252f29d9ba5b3394573a5"}, 214 | {file = "cytoolz-0.12.1-cp39-cp39-win32.whl", hash = "sha256:0d474dacbafbdbb44c7de986bbf71ff56ae62df0d52ab3b6fa966784dc88737a"}, 215 | {file = "cytoolz-0.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:3d6d0b0075731832343eb88229cea4bf39e96f3fc7acbc449aadbdfec2842703"}, 216 | {file = "cytoolz-0.12.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8506d1863f30d26f577c4ed59d2cfd03d2f39569f9cbaa02a764a9de73d312d5"}, 217 | {file = "cytoolz-0.12.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a1eae39656a1685e8b3f433eecfd72015ce5c1d7519e9c8f9402153c68331bb"}, 218 | {file = "cytoolz-0.12.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a0055943074c6c85b77fcc3f42f7c54010a3478daa2ed9d6243d0411c84a4d3"}, 219 | {file = "cytoolz-0.12.1-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8a7a325b8fe885a6dd91093616c703134f2dacbd869bc519970df3849c2a15b"}, 220 | {file = "cytoolz-0.12.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:7b60caf0fa5f1b49f1062f7dc0f66c7b23e2736bad50fa8296bfb845995e3051"}, 221 | {file = "cytoolz-0.12.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:980e7eb7205e01816a92f3290cfc80507957e64656b9271a0dfebb85fe3718c0"}, 222 | {file = "cytoolz-0.12.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06d38a40fe153f23cda0e823413fe9d9ebee89dd461827285316eff929fb121e"}, 223 | {file = "cytoolz-0.12.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d540e9c34a61b53b6a374ea108794a48388178f7889d772e364cdbd6df37774c"}, 224 | {file = "cytoolz-0.12.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:117871f036926e42d3abcee587eafa9dc7383f1064ac53a806d33e76604de311"}, 225 | {file = "cytoolz-0.12.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:31131b54a0c72efc0eb432dc66df546c6a54f2a7d396c9a34cf65ac1c26b1df8"}, 226 | {file = "cytoolz-0.12.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4534cbfad73cdb1a6dad495530d4186d57d73089c01e9cb0558caab50e46cb3b"}, 227 | {file = "cytoolz-0.12.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50db41e875e36aec11881b8b12bc69c6f4836b7dd9e88a9e5bbf26c2cb3ba6cd"}, 228 | {file = "cytoolz-0.12.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6716855f9c669c9e25a185d88e0f169839bf8553d16496796325acd114607c11"}, 229 | {file = "cytoolz-0.12.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f32452e833f0605b871626e6c61b71b0cba24233aad0e04accc3240497d4995"}, 230 | {file = "cytoolz-0.12.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ba74c239fc6cb6e962eabc420967c7565f3f363b776c89b3df5234caecf1f463"}, 231 | {file = "cytoolz-0.12.1.tar.gz", hash = "sha256:fc33909397481c90de3cec831bfb88d97e220dc91939d996920202f184b4648e"}, 232 | ] 233 | 234 | [package.dependencies] 235 | toolz = ">=0.8.0" 236 | 237 | [package.extras] 238 | cython = ["cython"] 239 | 240 | [[package]] 241 | name = "eth-abi" 242 | version = "4.1.0" 243 | description = "eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding" 244 | optional = false 245 | python-versions = ">=3.7.2, <4" 246 | files = [ 247 | {file = "eth_abi-4.1.0-py3-none-any.whl", hash = "sha256:15f9870ca054c09a8e474d2d7e81aff0c32421aebdac896193183fc143e31b50"}, 248 | {file = "eth_abi-4.1.0.tar.gz", hash = "sha256:fe738cdb24983adfe89abf727c723c288f8d0029e97fb08160b20bb5290ab475"}, 249 | ] 250 | 251 | [package.dependencies] 252 | eth-typing = ">=3.0.0" 253 | eth-utils = ">=2.0.0" 254 | parsimonious = ">=0.9.0,<0.10.0" 255 | 256 | [package.extras] 257 | dev = ["black (>=23)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "hypothesis (>=4.18.2,<5.0.0)", "ipython", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] 258 | doc = ["sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] 259 | lint = ["black (>=23)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)"] 260 | test = ["eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-xdist (>=2.4.0)"] 261 | tools = ["hypothesis (>=4.18.2,<5.0.0)"] 262 | 263 | [[package]] 264 | name = "eth-hash" 265 | version = "0.5.2" 266 | description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" 267 | optional = false 268 | python-versions = ">=3.7, <4" 269 | files = [ 270 | {file = "eth-hash-0.5.2.tar.gz", hash = "sha256:1b5f10eca7765cc385e1430eefc5ced6e2e463bb18d1365510e2e539c1a6fe4e"}, 271 | {file = "eth_hash-0.5.2-py3-none-any.whl", hash = "sha256:251f62f6579a1e247561679d78df37548bd5f59908da0b159982bf8293ad32f0"}, 272 | ] 273 | 274 | [package.extras] 275 | dev = ["black (>=23)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "ipython", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)", "pytest (>=7.0.0)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] 276 | doc = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] 277 | lint = ["black (>=23)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)"] 278 | pycryptodome = ["pycryptodome (>=3.6.6,<4)"] 279 | pysha3 = ["pysha3 (>=1.0.0,<2.0.0)", "safe-pysha3 (>=1.0.0)"] 280 | test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] 281 | 282 | [[package]] 283 | name = "eth-typing" 284 | version = "3.4.0" 285 | description = "eth-typing: Common type annotations for ethereum python packages" 286 | optional = false 287 | python-versions = ">=3.7.2, <4" 288 | files = [ 289 | {file = "eth-typing-3.4.0.tar.gz", hash = "sha256:7f49610469811ee97ac43eaf6baa294778ce74042d41e61ecf22e5ebe385590f"}, 290 | {file = "eth_typing-3.4.0-py3-none-any.whl", hash = "sha256:347d50713dd58ab50063b228d8271624ab2de3071bfa32d467b05f0ea31ab4c5"}, 291 | ] 292 | 293 | [package.extras] 294 | dev = ["black (>=23)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "ipython", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)", "pytest (>=7.0.0)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] 295 | doc = ["sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] 296 | lint = ["black (>=23)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)"] 297 | test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] 298 | 299 | [[package]] 300 | name = "eth-utils" 301 | version = "2.1.1" 302 | description = "eth-utils: Common utility functions for python code that interacts with Ethereum" 303 | optional = false 304 | python-versions = ">=3.7,<4" 305 | files = [ 306 | {file = "eth-utils-2.1.1.tar.gz", hash = "sha256:7cccfb0b0749431d0d001e327e9a7289bf07308316a73850ae3895020e5682f4"}, 307 | {file = "eth_utils-2.1.1-py3-none-any.whl", hash = "sha256:4938ab742f91cdf19bae024261af090664f63ccf83bdb1213e7146c14209e899"}, 308 | ] 309 | 310 | [package.dependencies] 311 | cytoolz = {version = ">=0.10.1", markers = "implementation_name == \"cpython\""} 312 | eth-hash = ">=0.3.1" 313 | eth-typing = ">=3.0.0" 314 | toolz = {version = ">0.8.2", markers = "implementation_name == \"pypy\""} 315 | 316 | [package.extras] 317 | dev = ["black (>=23)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "flake8 (==3.8.3)", "hypothesis (>=4.43.0)", "ipython", "isort (>=5.11.0)", "mypy (==0.971)", "pydocstyle (>=5.0.0)", "pytest (>=7.0.0)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "types-setuptools", "wheel"] 318 | doc = ["sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] 319 | lint = ["black (>=23)", "flake8 (==3.8.3)", "isort (>=5.11.0)", "mypy (==0.971)", "pydocstyle (>=5.0.0)", "types-setuptools"] 320 | test = ["hypothesis (>=4.43.0)", "mypy (==0.971)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "types-setuptools"] 321 | 322 | [[package]] 323 | name = "exceptiongroup" 324 | version = "1.1.1" 325 | description = "Backport of PEP 654 (exception groups)" 326 | optional = false 327 | python-versions = ">=3.7" 328 | files = [ 329 | {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, 330 | {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, 331 | ] 332 | 333 | [package.extras] 334 | test = ["pytest (>=6)"] 335 | 336 | [[package]] 337 | name = "h11" 338 | version = "0.14.0" 339 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 340 | optional = false 341 | python-versions = ">=3.7" 342 | files = [ 343 | {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, 344 | {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, 345 | ] 346 | 347 | [[package]] 348 | name = "h2" 349 | version = "4.1.0" 350 | description = "HTTP/2 State-Machine based protocol implementation" 351 | optional = false 352 | python-versions = ">=3.6.1" 353 | files = [ 354 | {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, 355 | {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, 356 | ] 357 | 358 | [package.dependencies] 359 | hpack = ">=4.0,<5" 360 | hyperframe = ">=6.0,<7" 361 | 362 | [[package]] 363 | name = "hpack" 364 | version = "4.0.0" 365 | description = "Pure-Python HPACK header compression" 366 | optional = false 367 | python-versions = ">=3.6.1" 368 | files = [ 369 | {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, 370 | {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, 371 | ] 372 | 373 | [[package]] 374 | name = "httpcore" 375 | version = "0.16.3" 376 | description = "A minimal low-level HTTP client." 377 | optional = false 378 | python-versions = ">=3.7" 379 | files = [ 380 | {file = "httpcore-0.16.3-py3-none-any.whl", hash = "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"}, 381 | {file = "httpcore-0.16.3.tar.gz", hash = "sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb"}, 382 | ] 383 | 384 | [package.dependencies] 385 | anyio = ">=3.0,<5.0" 386 | certifi = "*" 387 | h11 = ">=0.13,<0.15" 388 | sniffio = "==1.*" 389 | 390 | [package.extras] 391 | http2 = ["h2 (>=3,<5)"] 392 | socks = ["socksio (==1.*)"] 393 | 394 | [[package]] 395 | name = "httpx" 396 | version = "0.23.3" 397 | description = "The next generation HTTP client." 398 | optional = false 399 | python-versions = ">=3.7" 400 | files = [ 401 | {file = "httpx-0.23.3-py3-none-any.whl", hash = "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"}, 402 | {file = "httpx-0.23.3.tar.gz", hash = "sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9"}, 403 | ] 404 | 405 | [package.dependencies] 406 | certifi = "*" 407 | httpcore = ">=0.15.0,<0.17.0" 408 | rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} 409 | sniffio = "*" 410 | 411 | [package.extras] 412 | brotli = ["brotli", "brotlicffi"] 413 | cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<13)"] 414 | http2 = ["h2 (>=3,<5)"] 415 | socks = ["socksio (==1.*)"] 416 | 417 | [[package]] 418 | name = "hyperframe" 419 | version = "6.0.1" 420 | description = "HTTP/2 framing layer for Python" 421 | optional = false 422 | python-versions = ">=3.6.1" 423 | files = [ 424 | {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, 425 | {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, 426 | ] 427 | 428 | [[package]] 429 | name = "idna" 430 | version = "3.4" 431 | description = "Internationalized Domain Names in Applications (IDNA)" 432 | optional = false 433 | python-versions = ">=3.5" 434 | files = [ 435 | {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, 436 | {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, 437 | ] 438 | 439 | [[package]] 440 | name = "parsimonious" 441 | version = "0.9.0" 442 | description = "(Soon to be) the fastest pure-Python PEG parser I could muster" 443 | optional = false 444 | python-versions = "*" 445 | files = [ 446 | {file = "parsimonious-0.9.0.tar.gz", hash = "sha256:b2ad1ae63a2f65bd78f5e0a8ac510a98f3607a43f1db2a8d46636a5d9e4a30c1"}, 447 | ] 448 | 449 | [package.dependencies] 450 | regex = ">=2022.3.15" 451 | 452 | [[package]] 453 | name = "pycparser" 454 | version = "2.21" 455 | description = "C parser in Python" 456 | optional = false 457 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 458 | files = [ 459 | {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, 460 | {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, 461 | ] 462 | 463 | [[package]] 464 | name = "pynacl" 465 | version = "1.5.0" 466 | description = "Python binding to the Networking and Cryptography (NaCl) library" 467 | optional = false 468 | python-versions = ">=3.6" 469 | files = [ 470 | {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, 471 | {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, 472 | {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, 473 | {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, 474 | {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, 475 | {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, 476 | {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, 477 | {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, 478 | {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, 479 | {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, 480 | ] 481 | 482 | [package.dependencies] 483 | cffi = ">=1.4.1" 484 | 485 | [package.extras] 486 | docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] 487 | tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] 488 | 489 | [[package]] 490 | name = "regex" 491 | version = "2023.6.3" 492 | description = "Alternative regular expression module, to replace re." 493 | optional = false 494 | python-versions = ">=3.6" 495 | files = [ 496 | {file = "regex-2023.6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:824bf3ac11001849aec3fa1d69abcb67aac3e150a933963fb12bda5151fe1bfd"}, 497 | {file = "regex-2023.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:05ed27acdf4465c95826962528f9e8d41dbf9b1aa8531a387dee6ed215a3e9ef"}, 498 | {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b49c764f88a79160fa64f9a7b425620e87c9f46095ef9c9920542ab2495c8bc"}, 499 | {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8e3f1316c2293e5469f8f09dc2d76efb6c3982d3da91ba95061a7e69489a14ef"}, 500 | {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43e1dd9d12df9004246bacb79a0e5886b3b6071b32e41f83b0acbf293f820ee8"}, 501 | {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4959e8bcbfda5146477d21c3a8ad81b185cd252f3d0d6e4724a5ef11c012fb06"}, 502 | {file = "regex-2023.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af4dd387354dc83a3bff67127a124c21116feb0d2ef536805c454721c5d7993d"}, 503 | {file = "regex-2023.6.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2239d95d8e243658b8dbb36b12bd10c33ad6e6933a54d36ff053713f129aa536"}, 504 | {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:890e5a11c97cf0d0c550eb661b937a1e45431ffa79803b942a057c4fb12a2da2"}, 505 | {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a8105e9af3b029f243ab11ad47c19b566482c150c754e4c717900a798806b222"}, 506 | {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:25be746a8ec7bc7b082783216de8e9473803706723b3f6bef34b3d0ed03d57e2"}, 507 | {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:3676f1dd082be28b1266c93f618ee07741b704ab7b68501a173ce7d8d0d0ca18"}, 508 | {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:10cb847aeb1728412c666ab2e2000ba6f174f25b2bdc7292e7dd71b16db07568"}, 509 | {file = "regex-2023.6.3-cp310-cp310-win32.whl", hash = "sha256:dbbbfce33cd98f97f6bffb17801b0576e653f4fdb1d399b2ea89638bc8d08ae1"}, 510 | {file = "regex-2023.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:c5f8037000eb21e4823aa485149f2299eb589f8d1fe4b448036d230c3f4e68e0"}, 511 | {file = "regex-2023.6.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c123f662be8ec5ab4ea72ea300359023a5d1df095b7ead76fedcd8babbedf969"}, 512 | {file = "regex-2023.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9edcbad1f8a407e450fbac88d89e04e0b99a08473f666a3f3de0fd292badb6aa"}, 513 | {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcba6dae7de533c876255317c11f3abe4907ba7d9aa15d13e3d9710d4315ec0e"}, 514 | {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29cdd471ebf9e0f2fb3cac165efedc3c58db841d83a518b082077e612d3ee5df"}, 515 | {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12b74fbbf6cbbf9dbce20eb9b5879469e97aeeaa874145517563cca4029db65c"}, 516 | {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c29ca1bd61b16b67be247be87390ef1d1ef702800f91fbd1991f5c4421ebae8"}, 517 | {file = "regex-2023.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77f09bc4b55d4bf7cc5eba785d87001d6757b7c9eec237fe2af57aba1a071d9"}, 518 | {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ea353ecb6ab5f7e7d2f4372b1e779796ebd7b37352d290096978fea83c4dba0c"}, 519 | {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:10590510780b7541969287512d1b43f19f965c2ece6c9b1c00fc367b29d8dce7"}, 520 | {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e2fbd6236aae3b7f9d514312cdb58e6494ee1c76a9948adde6eba33eb1c4264f"}, 521 | {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:6b2675068c8b56f6bfd5a2bda55b8accbb96c02fd563704732fd1c95e2083461"}, 522 | {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74419d2b50ecb98360cfaa2974da8689cb3b45b9deff0dcf489c0d333bcc1477"}, 523 | {file = "regex-2023.6.3-cp311-cp311-win32.whl", hash = "sha256:fb5ec16523dc573a4b277663a2b5a364e2099902d3944c9419a40ebd56a118f9"}, 524 | {file = "regex-2023.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:09e4a1a6acc39294a36b7338819b10baceb227f7f7dbbea0506d419b5a1dd8af"}, 525 | {file = "regex-2023.6.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0654bca0cdf28a5956c83839162692725159f4cda8d63e0911a2c0dc76166525"}, 526 | {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:463b6a3ceb5ca952e66550a4532cef94c9a0c80dc156c4cc343041951aec1697"}, 527 | {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87b2a5bb5e78ee0ad1de71c664d6eb536dc3947a46a69182a90f4410f5e3f7dd"}, 528 | {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6343c6928282c1f6a9db41f5fd551662310e8774c0e5ebccb767002fcf663ca9"}, 529 | {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6192d5af2ccd2a38877bfef086d35e6659566a335b1492786ff254c168b1693"}, 530 | {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74390d18c75054947e4194019077e243c06fbb62e541d8817a0fa822ea310c14"}, 531 | {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:742e19a90d9bb2f4a6cf2862b8b06dea5e09b96c9f2df1779e53432d7275331f"}, 532 | {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8abbc5d54ea0ee80e37fef009e3cec5dafd722ed3c829126253d3e22f3846f1e"}, 533 | {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:c2b867c17a7a7ae44c43ebbeb1b5ff406b3e8d5b3e14662683e5e66e6cc868d3"}, 534 | {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:d831c2f8ff278179705ca59f7e8524069c1a989e716a1874d6d1aab6119d91d1"}, 535 | {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ee2d1a9a253b1729bb2de27d41f696ae893507c7db224436abe83ee25356f5c1"}, 536 | {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:61474f0b41fe1a80e8dfa70f70ea1e047387b7cd01c85ec88fa44f5d7561d787"}, 537 | {file = "regex-2023.6.3-cp36-cp36m-win32.whl", hash = "sha256:0b71e63226e393b534105fcbdd8740410dc6b0854c2bfa39bbda6b0d40e59a54"}, 538 | {file = "regex-2023.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bbb02fd4462f37060122e5acacec78e49c0fbb303c30dd49c7f493cf21fc5b27"}, 539 | {file = "regex-2023.6.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b862c2b9d5ae38a68b92e215b93f98d4c5e9454fa36aae4450f61dd33ff48487"}, 540 | {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:976d7a304b59ede34ca2921305b57356694f9e6879db323fd90a80f865d355a3"}, 541 | {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:83320a09188e0e6c39088355d423aa9d056ad57a0b6c6381b300ec1a04ec3d16"}, 542 | {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9427a399501818a7564f8c90eced1e9e20709ece36be701f394ada99890ea4b3"}, 543 | {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178bbc1b2ec40eaca599d13c092079bf529679bf0371c602edaa555e10b41c3"}, 544 | {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:837328d14cde912af625d5f303ec29f7e28cdab588674897baafaf505341f2fc"}, 545 | {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2d44dc13229905ae96dd2ae2dd7cebf824ee92bc52e8cf03dcead37d926da019"}, 546 | {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d54af539295392611e7efbe94e827311eb8b29668e2b3f4cadcfe6f46df9c777"}, 547 | {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7117d10690c38a622e54c432dfbbd3cbd92f09401d622902c32f6d377e2300ee"}, 548 | {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bb60b503ec8a6e4e3e03a681072fa3a5adcbfa5479fa2d898ae2b4a8e24c4591"}, 549 | {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:65ba8603753cec91c71de423a943ba506363b0e5c3fdb913ef8f9caa14b2c7e0"}, 550 | {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:271f0bdba3c70b58e6f500b205d10a36fb4b58bd06ac61381b68de66442efddb"}, 551 | {file = "regex-2023.6.3-cp37-cp37m-win32.whl", hash = "sha256:9beb322958aaca059f34975b0df135181f2e5d7a13b84d3e0e45434749cb20f7"}, 552 | {file = "regex-2023.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:fea75c3710d4f31389eed3c02f62d0b66a9da282521075061ce875eb5300cf23"}, 553 | {file = "regex-2023.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f56fcb7ff7bf7404becdfc60b1e81a6d0561807051fd2f1860b0d0348156a07"}, 554 | {file = "regex-2023.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d2da3abc88711bce7557412310dfa50327d5769a31d1c894b58eb256459dc289"}, 555 | {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a99b50300df5add73d307cf66abea093304a07eb017bce94f01e795090dea87c"}, 556 | {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5708089ed5b40a7b2dc561e0c8baa9535b77771b64a8330b684823cfd5116036"}, 557 | {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:687ea9d78a4b1cf82f8479cab23678aff723108df3edeac098e5b2498879f4a7"}, 558 | {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d3850beab9f527f06ccc94b446c864059c57651b3f911fddb8d9d3ec1d1b25d"}, 559 | {file = "regex-2023.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8915cc96abeb8983cea1df3c939e3c6e1ac778340c17732eb63bb96247b91d2"}, 560 | {file = "regex-2023.6.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:841d6e0e5663d4c7b4c8099c9997be748677d46cbf43f9f471150e560791f7ff"}, 561 | {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9edce5281f965cf135e19840f4d93d55b3835122aa76ccacfd389e880ba4cf82"}, 562 | {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b956231ebdc45f5b7a2e1f90f66a12be9610ce775fe1b1d50414aac1e9206c06"}, 563 | {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:36efeba71c6539d23c4643be88295ce8c82c88bbd7c65e8a24081d2ca123da3f"}, 564 | {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:cf67ca618b4fd34aee78740bea954d7c69fdda419eb208c2c0c7060bb822d747"}, 565 | {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b4598b1897837067a57b08147a68ac026c1e73b31ef6e36deeeb1fa60b2933c9"}, 566 | {file = "regex-2023.6.3-cp38-cp38-win32.whl", hash = "sha256:f415f802fbcafed5dcc694c13b1292f07fe0befdb94aa8a52905bd115ff41e88"}, 567 | {file = "regex-2023.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:d4f03bb71d482f979bda92e1427f3ec9b220e62a7dd337af0aa6b47bf4498f72"}, 568 | {file = "regex-2023.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ccf91346b7bd20c790310c4147eee6ed495a54ddb6737162a36ce9dbef3e4751"}, 569 | {file = "regex-2023.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b28f5024a3a041009eb4c333863d7894d191215b39576535c6734cd88b0fcb68"}, 570 | {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0bb18053dfcfed432cc3ac632b5e5e5c5b7e55fb3f8090e867bfd9b054dbcbf"}, 571 | {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a5bfb3004f2144a084a16ce19ca56b8ac46e6fd0651f54269fc9e230edb5e4a"}, 572 | {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c6b48d0fa50d8f4df3daf451be7f9689c2bde1a52b1225c5926e3f54b6a9ed1"}, 573 | {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:051da80e6eeb6e239e394ae60704d2b566aa6a7aed6f2890a7967307267a5dc6"}, 574 | {file = "regex-2023.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4c3b7fa4cdaa69268748665a1a6ff70c014d39bb69c50fda64b396c9116cf77"}, 575 | {file = "regex-2023.6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:457b6cce21bee41ac292d6753d5e94dcbc5c9e3e3a834da285b0bde7aa4a11e9"}, 576 | {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aad51907d74fc183033ad796dd4c2e080d1adcc4fd3c0fd4fd499f30c03011cd"}, 577 | {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0385e73da22363778ef2324950e08b689abdf0b108a7d8decb403ad7f5191938"}, 578 | {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c6a57b742133830eec44d9b2290daf5cbe0a2f1d6acee1b3c7b1c7b2f3606df7"}, 579 | {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3e5219bf9e75993d73ab3d25985c857c77e614525fac9ae02b1bebd92f7cecac"}, 580 | {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e5087a3c59eef624a4591ef9eaa6e9a8d8a94c779dade95d27c0bc24650261cd"}, 581 | {file = "regex-2023.6.3-cp39-cp39-win32.whl", hash = "sha256:20326216cc2afe69b6e98528160b225d72f85ab080cbdf0b11528cbbaba2248f"}, 582 | {file = "regex-2023.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:bdff5eab10e59cf26bc479f565e25ed71a7d041d1ded04ccf9aee1d9f208487a"}, 583 | {file = "regex-2023.6.3.tar.gz", hash = "sha256:72d1a25bf36d2050ceb35b517afe13864865268dfb45910e2e17a84be6cbfeb0"}, 584 | ] 585 | 586 | [[package]] 587 | name = "rfc3986" 588 | version = "1.5.0" 589 | description = "Validating URI References per RFC 3986" 590 | optional = false 591 | python-versions = "*" 592 | files = [ 593 | {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, 594 | {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, 595 | ] 596 | 597 | [package.dependencies] 598 | idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} 599 | 600 | [package.extras] 601 | idna2008 = ["idna"] 602 | 603 | [[package]] 604 | name = "sniffio" 605 | version = "1.3.0" 606 | description = "Sniff out which async library your code is running under" 607 | optional = false 608 | python-versions = ">=3.7" 609 | files = [ 610 | {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, 611 | {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, 612 | ] 613 | 614 | [[package]] 615 | name = "toolz" 616 | version = "0.12.0" 617 | description = "List processing tools and functional utilities" 618 | optional = false 619 | python-versions = ">=3.5" 620 | files = [ 621 | {file = "toolz-0.12.0-py3-none-any.whl", hash = "sha256:2059bd4148deb1884bb0eb770a3cde70e7f954cfbbdc2285f1f2de01fd21eb6f"}, 622 | {file = "toolz-0.12.0.tar.gz", hash = "sha256:88c570861c440ee3f2f6037c4654613228ff40c93a6c25e0eba70d17282c6194"}, 623 | ] 624 | 625 | [metadata] 626 | lock-version = "2.0" 627 | python-versions = "^3.8" 628 | content-hash = "33e48b550edbb2fec6f76a9052e30c683d153810068567e7173667688452fcf2" 629 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "layerzero-python-aptos" 3 | version = "1.0.0" 4 | description = "LayerZero bridging functionallity for Python" 5 | authors = ["Your Name "] 6 | readme = "README.md" 7 | packages = [{include = "layerzero_python_aptos"}] 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.8" 11 | eth-abi = "^4.1.0" 12 | aptos-sdk = "^0.6.3" 13 | 14 | 15 | [build-system] 16 | requires = ["poetry-core"] 17 | build-backend = "poetry.core.masonry.api" 18 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | aptos-sdk 3 | -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3engineering/LayerZero-python-aptos/a0dc0bd94d7a1d5615dcb6994da7f9ed32543455/src/__init__.py -------------------------------------------------------------------------------- /src/apps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3engineering/LayerZero-python-aptos/a0dc0bd94d7a1d5615dcb6994da7f9ed32543455/src/apps/__init__.py -------------------------------------------------------------------------------- /src/apps/bridge.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | from aptos_sdk.bcs import Serializer 4 | from aptos_sdk.transactions import EntryFunction, TransactionArgument 5 | from aptos_sdk.type_tag import TypeTag, StructTag 6 | 7 | from src.const import BRIDGE_ADDRESS, MAINNET 8 | from src.sdk.aptos_sdk import AptosSdk 9 | from src.utils import get_u64_raw_address, get_raw_address 10 | 11 | 12 | class Bridge: 13 | BRIDGE_ADDRESS = BRIDGE_ADDRESS[MAINNET] 14 | 15 | def __init__(self, private_key: str): 16 | self.sdk = AptosSdk(private_key=private_key) 17 | self.module = f'{self.BRIDGE_ADDRESS}::coin_bridge' 18 | self.module_name = 'bridge::coin_bridge' 19 | self.ua_type = f'{self.BRIDGE_ADDRESS}::coin_bridge::BridgeUA' 20 | 21 | def get_send_coin_payload( 22 | self, 23 | dst_chain_id: int, 24 | dst_receiver: str, 25 | amount: int, 26 | native_fee: int, 27 | zro_fee: int, 28 | unwrap: bool, 29 | adapter_params: str, 30 | msglib_params: list[str] 31 | ): 32 | dst_receiver = get_u64_raw_address(dst_receiver) 33 | adapter_params = get_raw_address(adapter_params) # adapter_params has HEX format, 0x000000000 34 | return { 35 | "module": self.module, 36 | "function": "send_coin_from", 37 | "type_arguments": [TypeTag(StructTag.from_str(f'{self.BRIDGE_ADDRESS}::asset::USDC'))], 38 | "arguments": [ 39 | TransactionArgument( 40 | dst_chain_id, Serializer.u64 # noqa 41 | ), 42 | TransactionArgument( 43 | list(binascii.unhexlify(dst_receiver)), Serializer.sequence_serializer(Serializer.u8) # noqa 44 | ), 45 | TransactionArgument( 46 | amount, Serializer.u64 # noqa 47 | ), 48 | TransactionArgument( 49 | int(native_fee), Serializer.u64 # noqa 50 | ), 51 | TransactionArgument( 52 | int(zro_fee), Serializer.u64 # noqa 53 | ), 54 | TransactionArgument( 55 | unwrap, Serializer.bool # noqa 56 | ), 57 | TransactionArgument( 58 | list(binascii.unhexlify(adapter_params)), Serializer.sequence_serializer(Serializer.u8) # noqa 59 | ), 60 | TransactionArgument( 61 | msglib_params, Serializer.sequence_serializer(Serializer.u8) # noqa 62 | ), 63 | ] 64 | } 65 | 66 | def get_claim_coin_payload(self): 67 | return { 68 | "module": self.module, 69 | "function": "claim_coin", 70 | "type_arguments": [ 71 | TypeTag( 72 | StructTag.from_str( 73 | f"{self.BRIDGE_ADDRESS}::asset::USDC" 74 | )), 75 | ], 76 | "arguments": [], 77 | } 78 | 79 | def send_coin(self, amount, dst_chain_id, dst_receiver, fee, adapter_params): 80 | send_coin_payload = self.get_send_coin_payload( 81 | dst_chain_id=dst_chain_id, 82 | dst_receiver=dst_receiver, 83 | amount=amount, 84 | native_fee=fee, 85 | zro_fee=0, 86 | unwrap=False, 87 | adapter_params=adapter_params, 88 | msglib_params=[], 89 | ) 90 | 91 | payload = EntryFunction.natural( 92 | send_coin_payload["module"], 93 | send_coin_payload["function"], 94 | send_coin_payload["type_arguments"], 95 | send_coin_payload["arguments"], 96 | ) 97 | 98 | return self.sdk.send_and_submit_transaction(payload) 99 | 100 | def claim_coin(self): 101 | claim_coin_payload = self.get_claim_coin_payload() 102 | 103 | payload = EntryFunction.natural( 104 | claim_coin_payload["module"], 105 | claim_coin_payload["function"], 106 | claim_coin_payload["type_arguments"], 107 | claim_coin_payload["arguments"], 108 | ) 109 | 110 | return self.sdk.send_and_submit_transaction(payload) 111 | -------------------------------------------------------------------------------- /src/apps/lz_app.py: -------------------------------------------------------------------------------- 1 | from aptos_sdk.client import RestClient 2 | 3 | 4 | class LzApp: 5 | def __init__(self, sdk: RestClient): 6 | self.sdk = sdk 7 | -------------------------------------------------------------------------------- /src/const.py: -------------------------------------------------------------------------------- 1 | APTOS_RPC = "https://fullnode.mainnet.aptoslabs.com/v1" 2 | 3 | SEND_PAYLOAD_LENGTH = 74 4 | 5 | MAINNET = "MAINNET" 6 | TESTNET = "TESTNET" 7 | DEVNET = "DEVNET" 8 | LOCAL = "LOCAL" 9 | TESTNET_SANDBOX = "TESTNET_SANDBOX" 10 | 11 | NODE_URL = { 12 | MAINNET: 'https://mainnet.aptoslabs.com/v1', 13 | TESTNET: 'https://fullnode.testnet.aptoslabs.com/v1', 14 | DEVNET: 'https://fullnode.devnet.aptoslabs.com/v1', 15 | LOCAL: 'http://127.0.0.1:8080/v1', 16 | } 17 | 18 | FAUCET_URL = { 19 | MAINNET: '', 20 | TESTNET: 'https://faucet.testnet.aptoslabs.com', 21 | DEVNET: 'https://faucet.devnet.aptoslabs.com', 22 | LOCAL: 'http://127.0.0.1:8081', 23 | } 24 | 25 | LAYERZERO_ADDRESS = { 26 | MAINNET: '0x54ad3d30af77b60d939ae356e6606de9a4da67583f02b962d2d3f2e481484e90', 27 | TESTNET: '0x1759cc0d3161f1eb79f65847d4feb9d1f74fb79014698a23b16b28b9cd4c37e3', 28 | TESTNET_SANDBOX: '0xcdc2c5597e2a96faf08135db560e3846e8c8c5683b0db868f6ad68f143906b3e', 29 | } 30 | 31 | LAYERZERO_APPS_ADDRESS = { 32 | MAINNET: '0x43d8cad89263e6936921a0adb8d5d49f0e236c229460f01b14dca073114df2b9', 33 | TESTNET: '0x2f972c173927006c83277b6e6ae38f83482eba560f343d022f145979020d3621', 34 | TESTNET_SANDBOX: '', 35 | } 36 | 37 | ORACLE_ADDRESS = { 38 | MAINNET: '0xc2846ea05319c339b3b52186ceae40b43d4e9cf6c7350336c3eb0b351d9394eb', 39 | TESTNET: '0x8ab85d94bf34808386b3ce0f9516db74d2b6d2f1166aa48f75ca641f3adb6c63', 40 | TESTNET_SANDBOX: '0x38ee7e8bc9d2601ec0934a5d6e23182a266380d87840e5f0850bfeb647297d3a', 41 | } 42 | 43 | ORACLE_SIGNER_ADDRESS = { 44 | MAINNET: '0x12e12de0af996d9611b0b78928cd9f4cbf50d94d972043cdd829baa77a78929b', 45 | TESTNET: '0x47a30bcdb5b5bdbf6af883c7325827f3e40b3f52c3538e9e677e68cf0c0db060', 46 | TESTNET_SANDBOX: '0x760b1ad2811b7c3e7e04a9dc38520320dc30850fbf001db61c18d1e36221d5c8', 47 | } 48 | 49 | RELAYER_SIGNER_ADDRESS = { 50 | MAINNET: '0x1d8727df513fa2a8785d0834e40b34223daff1affc079574082baadb74b66ee4', 51 | TESTNET: '0xc192864c4215741051321d44f89c3b7a54840a0b1b7ef5bec6149a07f9df4641', 52 | TESTNET_SANDBOX: '0xc180500ddac3fef70cb1e9fc0d75793850e2cef84d518ea0a3b3adfb93751ea7', 53 | } 54 | 55 | EXECUTOR_ADDRESS = { 56 | MAINNET: '0x1d8727df513fa2a8785d0834e40b34223daff1affc079574082baadb74b66ee4', 57 | TESTNET: '0xc192864c4215741051321d44f89c3b7a54840a0b1b7ef5bec6149a07f9df4641', 58 | TESTNET_SANDBOX: '0xc180500ddac3fef70cb1e9fc0d75793850e2cef84d518ea0a3b3adfb93751ea7', 59 | } 60 | 61 | EXECUTOR_PUBKEY = { 62 | MAINNET: '0x1d8727df513fa2a8785d0834e40b34223daff1affc079574082baadb74b66ee4', 63 | TESTNET: '0x6f8d3bd5454c8780bf75acec7e343663a1dcbbc357636fac3ea381058dbd6af4', 64 | TESTNET_SANDBOX: '0x2bd652fe4e0433ba9d4f37b9fbb39d3ac5a2149cad661736067952db3e716a3d', 65 | } 66 | 67 | BRIDGE_ADDRESS = { 68 | MAINNET: '0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa', 69 | TESTNET: '0xec84c05cc40950c86d8a8bed19552f1e8ebb783196bb021c916161d22dc179f7', 70 | TESTNET_SANDBOX: '0x808b4ffe04011cd20327a910518b4bff661f73fa907e9fc41ad690f84fa6f83e', 71 | } 72 | -------------------------------------------------------------------------------- /src/endpoint.py: -------------------------------------------------------------------------------- 1 | from aptos_sdk.client import RestClient 2 | from src.executor import Executor 3 | from src.executor_config import ExecutorConfig 4 | from src.uln.uln_config import UlnConfig 5 | 6 | 7 | class Endpoint: 8 | executor_address = '0x1d8727df513fa2a8785d0834e40b34223daff1affc079574082baadb74b66ee4' 9 | oracle_address = '0x12e12de0af996d9611b0b78928cd9f4cbf50d94d972043cdd829baa77a78929b' 10 | layerzero_address = '0x54ad3d30af77b60d939ae356e6606de9a4da67583f02b962d2d3f2e481484e90' 11 | bridge_address = '0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa' 12 | module = f'{layerzero_address}::endpoint' 13 | module_name = 'layerzero::endpoint' 14 | 15 | def __init__(self, sdk: RestClient): 16 | self.sdk = sdk 17 | self.uln_module = UlnConfig(sdk) 18 | self.executor = Executor(sdk) 19 | self.executor_config = ExecutorConfig(sdk) 20 | 21 | def initialize(self, signer: str, local_chain_id: str): 22 | txn = { 23 | "function": f"{self.module}::init", 24 | "type_arguments": [], 25 | "arguments": [local_chain_id], 26 | } 27 | # WTF? 28 | # return this.sdk.sendAndConfirmTransaction(signer, transaction); 29 | 30 | def get_UA_type_info(self, ua_address: str): 31 | resource = self.sdk.account_resource( 32 | self.layerzero_address, 33 | f"{self.module}::UaRegistry" 34 | ) 35 | 36 | type_info = self.sdk.get_table_item( 37 | resource['data']['handle'], 38 | key_type='address', 39 | value_type='0x1::type_info::TypeInfo', 40 | key=ua_address 41 | ) 42 | 43 | return { 44 | "account_address": type_info["account_address"], 45 | "module_name": type_info["module_name"], 46 | "struct_name": type_info["struct_name"], 47 | "type": f"{type_info['account_address']}::{type_info['module_name']}::{type_info['struct_name']}" 48 | } 49 | 50 | def get_oracle_fee(self, dst_chain_id: str): 51 | resource = self.sdk.account_resource( 52 | self.layerzero_address, 53 | f"{self.module}::FeeStore" 54 | ) 55 | 56 | response = self.sdk.get_table_item( 57 | resource['data']['handle'], 58 | key_type=f"{self.module}::QuoteKey", 59 | value_type="u64", 60 | key={ 61 | "agent": self.oracle_address, 62 | "chain_id": dst_chain_id, 63 | } 64 | ) 65 | 66 | return response 67 | 68 | def quote_fee(self, ua_address: str, dst_chain_id: int, adapter_params, payload_size): 69 | total_fee = self.uln_module.quote_fee(ua_address, dst_chain_id, payload_size) 70 | executor, _ = self.executor_config.get_executor(ua_address, dst_chain_id) 71 | total_fee += self.executor.quote_fee(executor, dst_chain_id, adapter_params) 72 | return total_fee 73 | 74 | -------------------------------------------------------------------------------- /src/executor.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | import struct 3 | from typing import Optional 4 | 5 | from aptos_sdk.client import RestClient 6 | 7 | 8 | class Executor: 9 | executor_address = '0x1d8727df513fa2a8785d0834e40b34223daff1affc079574082baadb74b66ee4' 10 | oracle_address = '0x12e12de0af996d9611b0b78928cd9f4cbf50d94d972043cdd829baa77a78929b' 11 | layerzero_address = '0x54ad3d30af77b60d939ae356e6606de9a4da67583f02b962d2d3f2e481484e90' 12 | module = f'{layerzero_address}::executor_v1' 13 | module_name = 'layerzero::executor_v1' 14 | type = f'${module}::Executor' 15 | 16 | def __init__(self, sdk: RestClient): 17 | self.sdk = sdk 18 | 19 | def decode_adapter_params(self, adapter_params: str): 20 | """ 21 | txType 1 22 | bytes [2 8 ] 23 | fields [txType extraGas] 24 | txType 2 25 | bytes [2 8 8 unfixed ] 26 | fields [txType extraGas airdropAmt airdropAddress] 27 | """ 28 | byte_array = bytes.fromhex(adapter_params[2:]) 29 | type_ = struct.unpack('>H', byte_array[:2])[0] 30 | if type_ == 1: 31 | # default 32 | assert len(byte_array) == 10, "invalid adapter params" 33 | return [type_, struct.unpack('!Q', byte_array[2:])[0], 0, ''] 34 | elif type_ == 2: 35 | # airdrop 36 | assert len(byte_array) > 18, "invalid adapter params" 37 | ua_gas, airdrop_amount = struct.unpack('!QQ', byte_array[2:18]) 38 | airdrop_address = "0x" + binascii.hexlify(byte_array[18:]).decode("utf-8") 39 | return [type_, ua_gas, airdrop_amount, airdrop_address] 40 | else: 41 | assert False, "invalid adapter params" 42 | 43 | def get_default_adapter_params(self, dst_chain_id: int): 44 | resource = self.sdk.account_resource( 45 | self.layerzero_address, 46 | f"{self.module}::AdapterParamsConfig" 47 | ) 48 | 49 | response = self.sdk.get_table_item( 50 | resource['data']['params']['handle'], 51 | 'u64', 52 | 'vector', 53 | str(dst_chain_id) 54 | ) 55 | 56 | return response 57 | 58 | def get_fee(self, executor: str, dst_chain_id: int): 59 | resource = self.sdk.account_resource( 60 | executor, 61 | f"{self.layerzero_address}::executor_v1::ExecutorConfig" 62 | ) 63 | 64 | response = self.sdk.get_table_item( 65 | resource['data']['fee']['handle'], 66 | 'u64', 67 | f'{self.module}::Fee', 68 | str(dst_chain_id) 69 | ) 70 | 71 | return { 72 | "airdrop_amt_cap": response['airdrop_amt_cap'], 73 | "gas_price": response["gas_price"], 74 | "price_ratio": response["price_ratio"] 75 | } 76 | 77 | def quote_fee(self, executor: str, dst_chain_id: int, adapter_params: Optional[list] = None) -> int: 78 | if not adapter_params: 79 | adapter_params = self.get_default_adapter_params(dst_chain_id) 80 | 81 | fee = self.get_fee(executor, dst_chain_id) 82 | _, ua_gas, airdrop_amount, _ = self.decode_adapter_params(adapter_params) 83 | 84 | return ((ua_gas * int(fee['gas_price']) + airdrop_amount) * int(fee['price_ratio'])) / 10000000000 85 | -------------------------------------------------------------------------------- /src/executor_config.py: -------------------------------------------------------------------------------- 1 | from aptos_sdk.client import RestClient 2 | 3 | 4 | class ExecutorConfig: 5 | executor_address = '0x1d8727df513fa2a8785d0834e40b34223daff1affc079574082baadb74b66ee4' 6 | oracle_address = '0x12e12de0af996d9611b0b78928cd9f4cbf50d94d972043cdd829baa77a78929b' 7 | layerzero_address = '0x54ad3d30af77b60d939ae356e6606de9a4da67583f02b962d2d3f2e481484e90' 8 | module = f'{layerzero_address}::executor_config' 9 | 10 | def __init__(self, sdk: RestClient): 11 | self.sdk = sdk 12 | 13 | def get_executor(self, ua_address: str, dst_chain_id: int): 14 | resource = self.sdk.account_resource( 15 | self.layerzero_address, 16 | f"{self.module}::ConfigStore", 17 | ) 18 | response = self.sdk.get_table_item( 19 | resource['data']['config']['handle'], 20 | key_type='u64', 21 | value_type=f"{self.module}::Config", 22 | key=str(dst_chain_id), 23 | ) 24 | 25 | return [response['executor'], response['version']] 26 | 27 | -------------------------------------------------------------------------------- /src/sdk/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3engineering/LayerZero-python-aptos/a0dc0bd94d7a1d5615dcb6994da7f9ed32543455/src/sdk/__init__.py -------------------------------------------------------------------------------- /src/sdk/aptos_sdk.py: -------------------------------------------------------------------------------- 1 | from aptos_sdk import ed25519 2 | from aptos_sdk.account import Account 3 | from aptos_sdk.authenticator import Authenticator, Ed25519Authenticator 4 | from aptos_sdk.client import RestClient 5 | from aptos_sdk.transactions import EntryFunction, TransactionPayload, RawTransaction, SignedTransaction 6 | from aptos_sdk.client import ApiError 7 | from src.const import APTOS_RPC 8 | from src.sdk.base_sdk import BaseSdk 9 | from typing import Any, Dict 10 | 11 | 12 | class AptosSdk(BaseSdk): 13 | def __init__(self, private_key: str | None = None): 14 | self.account = Account.load_key(private_key) if private_key else None 15 | self.client = RestClient(APTOS_RPC) 16 | 17 | def send_and_submit_transaction(self, payload: EntryFunction) -> str: 18 | GAS_SAFETY_FACTOR = 0.2 # 20% 19 | raw_transaction = self.client.create_bcs_transaction( 20 | self.account, TransactionPayload(payload) 21 | ) 22 | simulated_transaction = self.simulate_transaction_with_gas_estimate( 23 | transaction=raw_transaction, 24 | ) 25 | 26 | if not simulated_transaction[0]["success"]: # noqa 27 | raise ValueError(simulated_transaction[0]["vm_status"]) # noqa 28 | 29 | self.client.client_config.max_gas_amount = int( 30 | int(simulated_transaction[0]['gas_used'], base=10) * (1 + GAS_SAFETY_FACTOR) 31 | ) 32 | 33 | signed_transaction = self.client.create_bcs_signed_transaction( 34 | self.account, TransactionPayload(payload) 35 | ) 36 | txn = self.client.submit_bcs_transaction(signed_transaction) 37 | self.client.wait_for_transaction(txn) 38 | return txn 39 | 40 | def simulate_transaction_with_gas_estimate( 41 | self, 42 | transaction: RawTransaction 43 | ) -> Dict[str, Any]: 44 | authenticator = Authenticator( 45 | Ed25519Authenticator( 46 | self.account.public_key(), 47 | ed25519.Signature(b"\x00" * 64), 48 | ) 49 | ) 50 | signed_transaction = SignedTransaction(transaction, authenticator) 51 | params = { 52 | 'estimate_gas_unit_price': "true", 53 | 'estimate_max_gas_amount': "true" 54 | } 55 | headers = { 56 | "Content-Type": "application/x.aptos.signed_transaction+bcs" 57 | } 58 | response = self.client.client.post( 59 | f"{self.client.base_url}/transactions/simulate", 60 | headers=headers, 61 | data=signed_transaction.bytes(), 62 | params=params 63 | ) 64 | if response.status_code >= 400: 65 | raise ApiError(response.text, response.status_code) 66 | 67 | return response.json() 68 | -------------------------------------------------------------------------------- /src/sdk/base_sdk.py: -------------------------------------------------------------------------------- 1 | from abc import ABC 2 | 3 | from aptos_sdk.transactions import EntryFunction 4 | 5 | 6 | class BaseSdk(ABC): 7 | def __int__(self, private_key: str | None = None): ... 8 | 9 | def send_and_submit_transaction(self, payload: EntryFunction) -> str: ... 10 | -------------------------------------------------------------------------------- /src/uln/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3engineering/LayerZero-python-aptos/a0dc0bd94d7a1d5615dcb6994da7f9ed32543455/src/uln/__init__.py -------------------------------------------------------------------------------- /src/uln/uln_config.py: -------------------------------------------------------------------------------- 1 | from aptos_sdk.client import RestClient 2 | from src.uln.uln_signer import UlnSigner 3 | 4 | 5 | class UlnConfig: 6 | executor_address = '0x1d8727df513fa2a8785d0834e40b34223daff1affc079574082baadb74b66ee4' 7 | oracle_address = '0x12e12de0af996d9611b0b78928cd9f4cbf50d94d972043cdd829baa77a78929b' 8 | layerzero_address = '0x54ad3d30af77b60d939ae356e6606de9a4da67583f02b962d2d3f2e481484e90' 9 | bridge_address = '0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa' 10 | module = f'{layerzero_address}::uln_config' 11 | module_name = 'layerzero::uln_config' 12 | 13 | def __init__(self, sdk: RestClient): 14 | self.sdk = sdk 15 | self.uln_signer = UlnSigner(sdk) 16 | 17 | def get_default_app_config(self, dst_chain_id: int): 18 | resource = self.sdk.account_resource( 19 | self.layerzero_address, 20 | f"{self.module}::DefaultUlnConfig" 21 | ) 22 | 23 | return self.sdk.get_table_item( 24 | resource['data']['config']['handle'], 25 | key_type='u64', 26 | value_type=f'{self.module}::UlnConfig', 27 | key=str(dst_chain_id), 28 | ) 29 | 30 | def get_app_config(self, ua_address: str, dst_chain_id: int): 31 | # TODO: RESOLVE IT FOR GET_TABLE_ITEM 32 | # aptos_sdk.client.ApiError: {"message":"Table Item not found by Table handle(0xf576de3aafdcd17b912476f145c1c839ee34edc71a5fa7633d8267df0b2501c4), Table key({\"ua_address\":\"0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa\",\"chain_id\":\"110\"}) and Ledger version(169788690)","error_code":"table_item_not_found","vm_error_code":null} 33 | # default_config = self.get_default_app_config(dst_chain_id) # Do we need to merge it? 34 | resource = self.sdk.account_resource( 35 | self.layerzero_address, 36 | f"{self.module}::UaUlnConfig" 37 | ) 38 | 39 | config = self.sdk.get_table_item( 40 | resource['data']['config']['handle'], 41 | key_type=f"{self.module}::UaConfigKey", 42 | value_type=f"{self.module}::UlnConfig", 43 | key={ 44 | "ua_address": ua_address, 45 | "chain_id": str(dst_chain_id) 46 | } 47 | ) 48 | 49 | # TODO: No merged config 50 | 51 | return config 52 | 53 | def quote_fee(self, ua_address: str, dst_chain_id: int, payload_size: int) -> int: 54 | config = self.get_default_app_config(dst_chain_id) 55 | 56 | oracle_fee = self.uln_signer.get_fee(config['oracle'], dst_chain_id) 57 | relayer_fee = self.uln_signer.get_fee(config['relayer'], dst_chain_id) 58 | treasury_config_resource = self.sdk.account_resource( 59 | self.layerzero_address, 60 | f"{self.layerzero_address}::msglib_v1_0::GlobalStore" 61 | ) 62 | 63 | treasury_fee_bps = int(treasury_config_resource['data']['treasury_fee_bps']) 64 | total_fee = int(relayer_fee['base_fee']) + int(relayer_fee['fee_per_byte']) * payload_size 65 | total_fee += int(oracle_fee['base_fee']) + int(oracle_fee['fee_per_byte']) * payload_size 66 | total_fee += (treasury_fee_bps * total_fee) / 10000 67 | return total_fee 68 | -------------------------------------------------------------------------------- /src/uln/uln_signer.py: -------------------------------------------------------------------------------- 1 | from aptos_sdk.client import RestClient 2 | 3 | 4 | class UlnSigner: 5 | executor_address = '0x1d8727df513fa2a8785d0834e40b34223daff1affc079574082baadb74b66ee4' 6 | oracle_address = '0x12e12de0af996d9611b0b78928cd9f4cbf50d94d972043cdd829baa77a78929b' 7 | layerzero_address = '0x54ad3d30af77b60d939ae356e6606de9a4da67583f02b962d2d3f2e481484e90' 8 | bridge_address = '0xf22bede237a07e121b56d91a491eb7bcdfd1f5907926a9e58338f964a01b17fa' 9 | module = f'{layerzero_address}::uln_signer' 10 | module_name = 'layerzero::uln_signer' 11 | 12 | def __init__(self, sdk: RestClient): 13 | self.sdk = sdk 14 | 15 | def get_fee(self, address: str, dst_chain_id: int): 16 | resource = self.sdk.account_resource( 17 | address, 18 | f"{self.module}::Config" 19 | ) 20 | 21 | response = self.sdk.get_table_item( 22 | resource['data']['fees']['handle'], 23 | key_type='u64', 24 | value_type=f'{self.module}::Fee', 25 | key=str(dst_chain_id), 26 | ) 27 | 28 | return { 29 | "base_fee": response['base_fee'], 30 | "fee_per_byte": response['fee_per_byte'] 31 | } 32 | -------------------------------------------------------------------------------- /src/utils.py: -------------------------------------------------------------------------------- 1 | def get_raw_address(address: str) -> str: 2 | return address.replace("0x", "") 3 | 4 | 5 | def get_u64_raw_address(address: str) -> str: 6 | return get_raw_address(address).rjust(64, "0") 7 | 8 | 9 | def full_address(address: str) -> bytes: 10 | raw_value = address.replace("0x", "") 11 | hexadecimal = raw_value.zfill(64).encode() 12 | return hexadecimal 13 | 14 | 15 | ZERO_ADDRESS_HEX = full_address("0x0").decode() 16 | 17 | 18 | def is_same_address(address1, address2): 19 | return full_address(address1).decode() == full_address(address2).decode() 20 | 21 | 22 | def is_zero_address(address): 23 | return is_same_address(address, ZERO_ADDRESS_HEX) 24 | 25 | 26 | def merge_config(config, default_config): 27 | merged_config = default_config.copy() 28 | if not is_zero_address(config["oracle"]): 29 | merged_config["oracle"] = config["oracle"] 30 | if not is_zero_address(config["relayer"]): 31 | merged_config["relayer"] = config["relayer"] 32 | if config["inbound_confirmations"] > 0: 33 | merged_config["inbound_confirmations"] = config["inbound_confirmations"] 34 | if config["outbound_confirmations"] > 0: 35 | merged_config["outbound_confirmations"] = config["outbound_confirmations"] 36 | return merged_config 37 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3engineering/LayerZero-python-aptos/a0dc0bd94d7a1d5615dcb6994da7f9ed32543455/tests/__init__.py -------------------------------------------------------------------------------- /tests/unit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/web3engineering/LayerZero-python-aptos/a0dc0bd94d7a1d5615dcb6994da7f9ed32543455/tests/unit/__init__.py -------------------------------------------------------------------------------- /tests/unit/test_utils.py: -------------------------------------------------------------------------------- 1 | from src.utils import ( 2 | get_raw_address, 3 | get_u64_raw_address, 4 | full_address, 5 | is_same_address, 6 | is_zero_address, 7 | merge_config 8 | ) 9 | 10 | 11 | def test_get_raw_address(): 12 | assert get_raw_address('0xaabbcc') == 'aabbcc' 13 | 14 | 15 | def test_get_u64_raw_address(): 16 | assert get_u64_raw_address('0xaabbccc') == "000000000000000000000000000000000000000000000000000000000aabbccc" 17 | 18 | 19 | def test_full_address(): 20 | assert isinstance(full_address('0xaabbcc'), bytes) 21 | assert full_address('0xaa') == b'00000000000000000000000000000000000000000000000000000000000000aa' 22 | 23 | 24 | def test_is_same_address(): 25 | assert is_same_address('0x0', '0x0') 26 | assert not is_same_address('0x0', '0x1') 27 | 28 | 29 | def test_is_zero_address(): 30 | assert is_zero_address('0x0') 31 | assert not is_zero_address('0x1') 32 | 33 | 34 | def test_merge_config(): 35 | config = { 36 | 'oracle': '0x0', 37 | 'relayer': '0x1', 38 | 'inbound_confirmations': 2, 39 | 'outbound_confirmations': 3, 40 | } 41 | default_config = { 42 | 'oracle': '0x0', 43 | 'relayer': '0x0', 44 | 'inbound_confirmations': 0, 45 | 'outbound_confirmations': 0, 46 | } 47 | expected_result = { 48 | 'oracle': '0x0', 49 | 'relayer': '0x1', 50 | 'inbound_confirmations': 2, 51 | 'outbound_confirmations': 3, 52 | } 53 | assert merge_config(config, default_config) == expected_result 54 | --------------------------------------------------------------------------------