├── .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 |
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 |
--------------------------------------------------------------------------------