summaryrefslogtreecommitdiff
path: root/python-lido-sdk.spec
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-05-05 13:50:59 +0000
committerCoprDistGit <infra@openeuler.org>2023-05-05 13:50:59 +0000
commit14d913fd699da2e211de06745d3980f7786f24cd (patch)
treeb0b5a09220a4f6e90fe962aeb1c2cc60f8a445fc /python-lido-sdk.spec
parentdf6f1bbd30e11b9ef3fd45897449c6f772d83ec5 (diff)
automatic import of python-lido-sdkopeneuler20.03
Diffstat (limited to 'python-lido-sdk.spec')
-rw-r--r--python-lido-sdk.spec830
1 files changed, 830 insertions, 0 deletions
diff --git a/python-lido-sdk.spec b/python-lido-sdk.spec
new file mode 100644
index 0000000..3f64687
--- /dev/null
+++ b/python-lido-sdk.spec
@@ -0,0 +1,830 @@
+%global _empty_manifest_terminate_build 0
+Name: python-lido-sdk
+Version: 4.0.0
+Release: 1
+Summary: This library consolidates various functions to efficiently load network data for Lido, validate node operator keys and find key duplicates.
+License: MIT
+URL: https://github.com/lidofinance/lido-python-sdk
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/46/b7/b293f1fc58cc33f2250644bb5b4a6a27dd94dad1cfe6015ac99dc71b93cb/lido-sdk-4.0.0.tar.gz
+
+
+%description
+
+# <img src="https://docs.lido.fi/img/logo.svg" alt="Lido" width="46"/> Lido Python SDK
+
+[![codecov](https://codecov.io/gh/lidofinance/lido-python-sdk/branch/master/graph/badge.svg)](https://codecov.io/gh/lidofinance/lido-python-sdk)
+[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
+[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
+
+A library with which you can get all Lido validator's signatures and check their validity.
+
+## Installation
+This library is available on PyPi:
+
+```bash
+pip install lido-sdk
+```
+
+## Fast start
+
+1. Create Web3 provider. One of fast options to start is INFURA.
+```python
+from web3 import Web3
+
+w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/{INFURA_PROJECT_ID}'))
+```
+
+2. Create Lido instance and provide web3 provider
+```python
+from lido_sdk import Lido
+
+lido = Lido(w3)
+```
+
+3. Call one
+```python
+response = lido.fetch_all_keys_and_validate()
+
+if response['invalid_keys'] or response['duplicated_keys']:
+ # This is not cool
+ print('There is invalid or duplicated keys\n')
+ print(response)
+else:
+ print('Everything is good!')
+```
+
+## Params for Lido
+| Param name | Default value | Description |
+|---------------------------------|---------------|----------------------------------------------------------------------|
+| w3 | required | Web3 provider |
+| MULTICALL_MAX_BUNCH | 275 | Count of calls in one multicall (not recommended to increase) |
+| MULTICALL_MAX_WORKERS | 6 | Count of requests in parallel (not recommended to have more than 12) |
+| MULTICALL_MAX_RETRIES | 5 | Count of retries before exception will be raised |
+| MULTICALL_POOL_EXECUTOR_TIMEOUT | 30 | Thread pool timeout for multicall (seconds) |
+| VALIDATE_POOL_EXECUTOR_TIMEOUT | 10 | Process pool timeout for keys validation (seconds) |
+
+Settings example if timeout exception was raised:
+```python
+Lido(w3=w3, MULTICALL_MAX_BUNCH=100, MULTICALL_MAX_WORKERS=3)
+```
+
+## Base methods
+Everything you need is in Lido class.
+
+- `Lido.get_operators_indexes(self) -> List[int]`
+Returns: Node operators indexes in contract.
+```
+>>> lido.get_operators_indexes()
+
+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
+```
+
+- `Lido.get_operators_data(self, operators_indexes: Optional[List[int]] = None) -> List[Operator]`
+Receives: List of operators indexes. If nothing provided will take previous return from `get_operators_indexes` method.
+Returns: List of operators details.
+```
+>>> lido.get_operators_data([1])
+
+[{'active': True, 'name': 'Certus One', 'rewardAddress': '0x8d689476eb446a1fb0065bffac32398ed7f89165', 'stakingLimit': 1000, 'stoppedValidators': 0, 'totalSigningKeys': 1000, 'usedSigningKeys': 1000, 'index': 1}]```
+```
+
+- `Lido.get_operators_keys(self, operators: Optional[List[Operator]] = None) -> List[OperatorKey]`
+Receives: List of operators details. If nothing provided will take previous return from `get_operators_data` method.
+Returns: List of keys in contract.
+```
+>>> lido.get_operators_keys(operators_data)
+
+[{'key': b'...', 'depositSignature': b'...', 'used': False, 'index': 6921, 'operator_index': 8}, ...]
+```
+
+- `Lido.update_keys(self) -> List[OperatorKey]`
+Returns actual keys list. Works only in `get_operators_keys` was called before. Should be used to periodically update keys.
+Faster because not all keys are updated from the contract.
+```
+>>> lido.update_keys()
+
+[{'key': b'...', 'depositSignature': b'...', 'used': False, 'index': 6521, 'operator_index': 5}]
+```
+
+- `Lido.validate_keys(self, keys: Optional[List[OperatorKey]] = None) -> List[OperatorKey]`
+Receives: List of keys to validate. If nothing provided will take previous return from `get_operators_keys` method.
+Returns: List of invalid keys.
+```
+>>> lido.validate_keys()
+
+[{'key': b'...', 'depositSignature': b'...', 'used': False, 'index': 6521, 'operator_index': 5}]
+```
+
+- `Lido.find_duplicated_keys(self, keys: Optional[List[OperatorKey]] = None) -> List[Tuple[OperatorKey, OperatorKey]]`
+Receives: List of keys to compare. If nothing provided will take previous return from `get_operators_keys` method.
+Returns: List of same pairs keys.
+```
+>>> lido.find_duplicated_keys()
+
+[
+ (
+ {'key': b'abc...', 'index': 222, 'operator_index': 5, ...},
+ {'key': b'abc...', 'index': 111, 'operator_index': 5, ...}
+ )
+]
+```
+
+- `Lido.get_status(self) -> dict`
+Returns dict with Lido current state.
+```
+>>> lido.get_status()
+
+{
+ 'isStopped': False,
+ 'totalPooledEther': 1045230979275869331637351,
+ 'withdrawalCredentials': b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb9\xd7\x93Hx\xb4\xfb\x96\x10\xb3\xfe\x8a^D\x1e\x8f\xad~)?',
+ 'bufferedEther': 76467538672788331637351,
+ 'feeBasisPoints': 1000,
+ 'treasuryFeeBasisPoints': 0,
+ 'insuranceFeeBasisPoints': 5000,
+ 'operatorsFeeBasisPoints': 5000,
+ 'depositedValidators': 29800,
+ 'beaconValidators': 29800,
+ 'beaconBalance': 968763440603081000000000,
+ 'last_block': 13110151,
+ 'last_blocktime': 1630103538,
+}
+```
+
+- `Lido.fetch_all_keys_and_validate(self) -> Dict[str, list]`
+Makes all steps below except `get_status`.
+Returns all invalid and duplicated keys.
+```
+>>> lido.fetch_all_keys_and_validate()
+
+{
+ 'invalid_keys': [...],
+ 'duplicated_keys': [...],
+}
+```
+
+## Issues
+
+There is issues with using blst lib on macos ARM cpu.
+But everything works on linux ARM cpu.
+
+## Main Features
+
+### Multicall Function Calls
+
+- Instead of making network requests one-by-one, this library combines many requests into one RPC call. It uses [banteg/multicall.py](https://github.com/banteg/multicall.py), a Python wrapper for [makerdao/multicall](https://github.com/makerdao/multicall).
+- Fast validation system powered by [blst](https://github.com/supranational/blst)
+
+### Automatic Testnet / Mainnet Switching
+
+Depending on which network is configured in web3 object, a set of contracts will be used.
+Available networks:
+- Mainnet
+- Görli
+- Ropsten
+- Rinkeby
+
+## Development
+
+Clone project:
+```bash
+git clone --recurse-submodules https://github.com/lidofinance/lido-python-sdk.git
+cd lido-python-sdk
+```
+Create virtual env:
+```bash
+virtualenv .env --python=python3
+source .env/bin/activate
+```
+Install all dependencies:
+```bash
+ poetry install
+```
+Activate virtual env
+```bash
+ poetry shell
+```
+Build blst locally (linux):
+```bash
+ cd blst/
+ ./build.sh
+ cd ..
+ mkdir -p ./blst-lib/linux/
+ cp ./blst/libblst.a ./blst-lib/linux/
+ cp ./blst/bindings/blst.h ./blst-lib/
+ cp ./blst/bindings/blst.hpp ./blst-lib/
+ cp ./blst/bindings/blst_aux.h ./blst-lib/
+ python setup.py build_ext --inplace
+```
+Build blst locally (osx):
+```bash
+ cd blst/
+ ./build.sh
+ cd ..
+ mkdir -p ./blst-lib/darwin/
+ cp ./blst/libblst.a ./blst-lib/darwin/
+ cp ./blst/bindings/blst.h ./blst-lib/
+ cp ./blst/bindings/blst.hpp ./blst-lib/
+ cp ./blst/bindings/blst_aux.h ./blst-lib/
+ python setup.py build_ext --inplace
+```
+Build blst locally (osx arm):
+```bash
+ cd blst/
+ ./build.sh
+ cd ..
+ mkdir -p ./blst-lib/darwin-arm64/
+ cp ./blst/libblst.a ./blst-lib/darwin-arm64/
+ cp ./blst/bindings/blst.h ./blst-lib/
+ cp ./blst/bindings/blst.hpp ./blst-lib/
+ cp ./blst/bindings/blst_aux.h ./blst-lib/
+ python setup.py build_ext --inplace
+```
+
+## How to test
+Simply run in project root directory:
+```bash
+poetry run pytest .
+```
+
+## Release new version
+```bash
+git tag v2.x.x master
+git push --tags
+```
+New version should be published after all pipelines passed.
+
+## Rebuild blst
+Goto actions "Build blst and create PR".
+Note that darwin-arm64 binaries are not rebuilt automatically due to GitHub Actions not supporting macOS runners on arm yet
+Review PR and merge.
+Do a release.
+
+
+
+
+%package -n python3-lido-sdk
+Summary: This library consolidates various functions to efficiently load network data for Lido, validate node operator keys and find key duplicates.
+Provides: python-lido-sdk
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+BuildRequires: python3-cffi
+BuildRequires: gcc
+BuildRequires: gdb
+%description -n python3-lido-sdk
+
+# <img src="https://docs.lido.fi/img/logo.svg" alt="Lido" width="46"/> Lido Python SDK
+
+[![codecov](https://codecov.io/gh/lidofinance/lido-python-sdk/branch/master/graph/badge.svg)](https://codecov.io/gh/lidofinance/lido-python-sdk)
+[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
+[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
+
+A library with which you can get all Lido validator's signatures and check their validity.
+
+## Installation
+This library is available on PyPi:
+
+```bash
+pip install lido-sdk
+```
+
+## Fast start
+
+1. Create Web3 provider. One of fast options to start is INFURA.
+```python
+from web3 import Web3
+
+w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/{INFURA_PROJECT_ID}'))
+```
+
+2. Create Lido instance and provide web3 provider
+```python
+from lido_sdk import Lido
+
+lido = Lido(w3)
+```
+
+3. Call one
+```python
+response = lido.fetch_all_keys_and_validate()
+
+if response['invalid_keys'] or response['duplicated_keys']:
+ # This is not cool
+ print('There is invalid or duplicated keys\n')
+ print(response)
+else:
+ print('Everything is good!')
+```
+
+## Params for Lido
+| Param name | Default value | Description |
+|---------------------------------|---------------|----------------------------------------------------------------------|
+| w3 | required | Web3 provider |
+| MULTICALL_MAX_BUNCH | 275 | Count of calls in one multicall (not recommended to increase) |
+| MULTICALL_MAX_WORKERS | 6 | Count of requests in parallel (not recommended to have more than 12) |
+| MULTICALL_MAX_RETRIES | 5 | Count of retries before exception will be raised |
+| MULTICALL_POOL_EXECUTOR_TIMEOUT | 30 | Thread pool timeout for multicall (seconds) |
+| VALIDATE_POOL_EXECUTOR_TIMEOUT | 10 | Process pool timeout for keys validation (seconds) |
+
+Settings example if timeout exception was raised:
+```python
+Lido(w3=w3, MULTICALL_MAX_BUNCH=100, MULTICALL_MAX_WORKERS=3)
+```
+
+## Base methods
+Everything you need is in Lido class.
+
+- `Lido.get_operators_indexes(self) -> List[int]`
+Returns: Node operators indexes in contract.
+```
+>>> lido.get_operators_indexes()
+
+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
+```
+
+- `Lido.get_operators_data(self, operators_indexes: Optional[List[int]] = None) -> List[Operator]`
+Receives: List of operators indexes. If nothing provided will take previous return from `get_operators_indexes` method.
+Returns: List of operators details.
+```
+>>> lido.get_operators_data([1])
+
+[{'active': True, 'name': 'Certus One', 'rewardAddress': '0x8d689476eb446a1fb0065bffac32398ed7f89165', 'stakingLimit': 1000, 'stoppedValidators': 0, 'totalSigningKeys': 1000, 'usedSigningKeys': 1000, 'index': 1}]```
+```
+
+- `Lido.get_operators_keys(self, operators: Optional[List[Operator]] = None) -> List[OperatorKey]`
+Receives: List of operators details. If nothing provided will take previous return from `get_operators_data` method.
+Returns: List of keys in contract.
+```
+>>> lido.get_operators_keys(operators_data)
+
+[{'key': b'...', 'depositSignature': b'...', 'used': False, 'index': 6921, 'operator_index': 8}, ...]
+```
+
+- `Lido.update_keys(self) -> List[OperatorKey]`
+Returns actual keys list. Works only in `get_operators_keys` was called before. Should be used to periodically update keys.
+Faster because not all keys are updated from the contract.
+```
+>>> lido.update_keys()
+
+[{'key': b'...', 'depositSignature': b'...', 'used': False, 'index': 6521, 'operator_index': 5}]
+```
+
+- `Lido.validate_keys(self, keys: Optional[List[OperatorKey]] = None) -> List[OperatorKey]`
+Receives: List of keys to validate. If nothing provided will take previous return from `get_operators_keys` method.
+Returns: List of invalid keys.
+```
+>>> lido.validate_keys()
+
+[{'key': b'...', 'depositSignature': b'...', 'used': False, 'index': 6521, 'operator_index': 5}]
+```
+
+- `Lido.find_duplicated_keys(self, keys: Optional[List[OperatorKey]] = None) -> List[Tuple[OperatorKey, OperatorKey]]`
+Receives: List of keys to compare. If nothing provided will take previous return from `get_operators_keys` method.
+Returns: List of same pairs keys.
+```
+>>> lido.find_duplicated_keys()
+
+[
+ (
+ {'key': b'abc...', 'index': 222, 'operator_index': 5, ...},
+ {'key': b'abc...', 'index': 111, 'operator_index': 5, ...}
+ )
+]
+```
+
+- `Lido.get_status(self) -> dict`
+Returns dict with Lido current state.
+```
+>>> lido.get_status()
+
+{
+ 'isStopped': False,
+ 'totalPooledEther': 1045230979275869331637351,
+ 'withdrawalCredentials': b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb9\xd7\x93Hx\xb4\xfb\x96\x10\xb3\xfe\x8a^D\x1e\x8f\xad~)?',
+ 'bufferedEther': 76467538672788331637351,
+ 'feeBasisPoints': 1000,
+ 'treasuryFeeBasisPoints': 0,
+ 'insuranceFeeBasisPoints': 5000,
+ 'operatorsFeeBasisPoints': 5000,
+ 'depositedValidators': 29800,
+ 'beaconValidators': 29800,
+ 'beaconBalance': 968763440603081000000000,
+ 'last_block': 13110151,
+ 'last_blocktime': 1630103538,
+}
+```
+
+- `Lido.fetch_all_keys_and_validate(self) -> Dict[str, list]`
+Makes all steps below except `get_status`.
+Returns all invalid and duplicated keys.
+```
+>>> lido.fetch_all_keys_and_validate()
+
+{
+ 'invalid_keys': [...],
+ 'duplicated_keys': [...],
+}
+```
+
+## Issues
+
+There is issues with using blst lib on macos ARM cpu.
+But everything works on linux ARM cpu.
+
+## Main Features
+
+### Multicall Function Calls
+
+- Instead of making network requests one-by-one, this library combines many requests into one RPC call. It uses [banteg/multicall.py](https://github.com/banteg/multicall.py), a Python wrapper for [makerdao/multicall](https://github.com/makerdao/multicall).
+- Fast validation system powered by [blst](https://github.com/supranational/blst)
+
+### Automatic Testnet / Mainnet Switching
+
+Depending on which network is configured in web3 object, a set of contracts will be used.
+Available networks:
+- Mainnet
+- Görli
+- Ropsten
+- Rinkeby
+
+## Development
+
+Clone project:
+```bash
+git clone --recurse-submodules https://github.com/lidofinance/lido-python-sdk.git
+cd lido-python-sdk
+```
+Create virtual env:
+```bash
+virtualenv .env --python=python3
+source .env/bin/activate
+```
+Install all dependencies:
+```bash
+ poetry install
+```
+Activate virtual env
+```bash
+ poetry shell
+```
+Build blst locally (linux):
+```bash
+ cd blst/
+ ./build.sh
+ cd ..
+ mkdir -p ./blst-lib/linux/
+ cp ./blst/libblst.a ./blst-lib/linux/
+ cp ./blst/bindings/blst.h ./blst-lib/
+ cp ./blst/bindings/blst.hpp ./blst-lib/
+ cp ./blst/bindings/blst_aux.h ./blst-lib/
+ python setup.py build_ext --inplace
+```
+Build blst locally (osx):
+```bash
+ cd blst/
+ ./build.sh
+ cd ..
+ mkdir -p ./blst-lib/darwin/
+ cp ./blst/libblst.a ./blst-lib/darwin/
+ cp ./blst/bindings/blst.h ./blst-lib/
+ cp ./blst/bindings/blst.hpp ./blst-lib/
+ cp ./blst/bindings/blst_aux.h ./blst-lib/
+ python setup.py build_ext --inplace
+```
+Build blst locally (osx arm):
+```bash
+ cd blst/
+ ./build.sh
+ cd ..
+ mkdir -p ./blst-lib/darwin-arm64/
+ cp ./blst/libblst.a ./blst-lib/darwin-arm64/
+ cp ./blst/bindings/blst.h ./blst-lib/
+ cp ./blst/bindings/blst.hpp ./blst-lib/
+ cp ./blst/bindings/blst_aux.h ./blst-lib/
+ python setup.py build_ext --inplace
+```
+
+## How to test
+Simply run in project root directory:
+```bash
+poetry run pytest .
+```
+
+## Release new version
+```bash
+git tag v2.x.x master
+git push --tags
+```
+New version should be published after all pipelines passed.
+
+## Rebuild blst
+Goto actions "Build blst and create PR".
+Note that darwin-arm64 binaries are not rebuilt automatically due to GitHub Actions not supporting macOS runners on arm yet
+Review PR and merge.
+Do a release.
+
+
+
+
+%package help
+Summary: Development documents and examples for lido-sdk
+Provides: python3-lido-sdk-doc
+%description help
+
+# <img src="https://docs.lido.fi/img/logo.svg" alt="Lido" width="46"/> Lido Python SDK
+
+[![codecov](https://codecov.io/gh/lidofinance/lido-python-sdk/branch/master/graph/badge.svg)](https://codecov.io/gh/lidofinance/lido-python-sdk)
+[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
+[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
+
+A library with which you can get all Lido validator's signatures and check their validity.
+
+## Installation
+This library is available on PyPi:
+
+```bash
+pip install lido-sdk
+```
+
+## Fast start
+
+1. Create Web3 provider. One of fast options to start is INFURA.
+```python
+from web3 import Web3
+
+w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/{INFURA_PROJECT_ID}'))
+```
+
+2. Create Lido instance and provide web3 provider
+```python
+from lido_sdk import Lido
+
+lido = Lido(w3)
+```
+
+3. Call one
+```python
+response = lido.fetch_all_keys_and_validate()
+
+if response['invalid_keys'] or response['duplicated_keys']:
+ # This is not cool
+ print('There is invalid or duplicated keys\n')
+ print(response)
+else:
+ print('Everything is good!')
+```
+
+## Params for Lido
+| Param name | Default value | Description |
+|---------------------------------|---------------|----------------------------------------------------------------------|
+| w3 | required | Web3 provider |
+| MULTICALL_MAX_BUNCH | 275 | Count of calls in one multicall (not recommended to increase) |
+| MULTICALL_MAX_WORKERS | 6 | Count of requests in parallel (not recommended to have more than 12) |
+| MULTICALL_MAX_RETRIES | 5 | Count of retries before exception will be raised |
+| MULTICALL_POOL_EXECUTOR_TIMEOUT | 30 | Thread pool timeout for multicall (seconds) |
+| VALIDATE_POOL_EXECUTOR_TIMEOUT | 10 | Process pool timeout for keys validation (seconds) |
+
+Settings example if timeout exception was raised:
+```python
+Lido(w3=w3, MULTICALL_MAX_BUNCH=100, MULTICALL_MAX_WORKERS=3)
+```
+
+## Base methods
+Everything you need is in Lido class.
+
+- `Lido.get_operators_indexes(self) -> List[int]`
+Returns: Node operators indexes in contract.
+```
+>>> lido.get_operators_indexes()
+
+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
+```
+
+- `Lido.get_operators_data(self, operators_indexes: Optional[List[int]] = None) -> List[Operator]`
+Receives: List of operators indexes. If nothing provided will take previous return from `get_operators_indexes` method.
+Returns: List of operators details.
+```
+>>> lido.get_operators_data([1])
+
+[{'active': True, 'name': 'Certus One', 'rewardAddress': '0x8d689476eb446a1fb0065bffac32398ed7f89165', 'stakingLimit': 1000, 'stoppedValidators': 0, 'totalSigningKeys': 1000, 'usedSigningKeys': 1000, 'index': 1}]```
+```
+
+- `Lido.get_operators_keys(self, operators: Optional[List[Operator]] = None) -> List[OperatorKey]`
+Receives: List of operators details. If nothing provided will take previous return from `get_operators_data` method.
+Returns: List of keys in contract.
+```
+>>> lido.get_operators_keys(operators_data)
+
+[{'key': b'...', 'depositSignature': b'...', 'used': False, 'index': 6921, 'operator_index': 8}, ...]
+```
+
+- `Lido.update_keys(self) -> List[OperatorKey]`
+Returns actual keys list. Works only in `get_operators_keys` was called before. Should be used to periodically update keys.
+Faster because not all keys are updated from the contract.
+```
+>>> lido.update_keys()
+
+[{'key': b'...', 'depositSignature': b'...', 'used': False, 'index': 6521, 'operator_index': 5}]
+```
+
+- `Lido.validate_keys(self, keys: Optional[List[OperatorKey]] = None) -> List[OperatorKey]`
+Receives: List of keys to validate. If nothing provided will take previous return from `get_operators_keys` method.
+Returns: List of invalid keys.
+```
+>>> lido.validate_keys()
+
+[{'key': b'...', 'depositSignature': b'...', 'used': False, 'index': 6521, 'operator_index': 5}]
+```
+
+- `Lido.find_duplicated_keys(self, keys: Optional[List[OperatorKey]] = None) -> List[Tuple[OperatorKey, OperatorKey]]`
+Receives: List of keys to compare. If nothing provided will take previous return from `get_operators_keys` method.
+Returns: List of same pairs keys.
+```
+>>> lido.find_duplicated_keys()
+
+[
+ (
+ {'key': b'abc...', 'index': 222, 'operator_index': 5, ...},
+ {'key': b'abc...', 'index': 111, 'operator_index': 5, ...}
+ )
+]
+```
+
+- `Lido.get_status(self) -> dict`
+Returns dict with Lido current state.
+```
+>>> lido.get_status()
+
+{
+ 'isStopped': False,
+ 'totalPooledEther': 1045230979275869331637351,
+ 'withdrawalCredentials': b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb9\xd7\x93Hx\xb4\xfb\x96\x10\xb3\xfe\x8a^D\x1e\x8f\xad~)?',
+ 'bufferedEther': 76467538672788331637351,
+ 'feeBasisPoints': 1000,
+ 'treasuryFeeBasisPoints': 0,
+ 'insuranceFeeBasisPoints': 5000,
+ 'operatorsFeeBasisPoints': 5000,
+ 'depositedValidators': 29800,
+ 'beaconValidators': 29800,
+ 'beaconBalance': 968763440603081000000000,
+ 'last_block': 13110151,
+ 'last_blocktime': 1630103538,
+}
+```
+
+- `Lido.fetch_all_keys_and_validate(self) -> Dict[str, list]`
+Makes all steps below except `get_status`.
+Returns all invalid and duplicated keys.
+```
+>>> lido.fetch_all_keys_and_validate()
+
+{
+ 'invalid_keys': [...],
+ 'duplicated_keys': [...],
+}
+```
+
+## Issues
+
+There is issues with using blst lib on macos ARM cpu.
+But everything works on linux ARM cpu.
+
+## Main Features
+
+### Multicall Function Calls
+
+- Instead of making network requests one-by-one, this library combines many requests into one RPC call. It uses [banteg/multicall.py](https://github.com/banteg/multicall.py), a Python wrapper for [makerdao/multicall](https://github.com/makerdao/multicall).
+- Fast validation system powered by [blst](https://github.com/supranational/blst)
+
+### Automatic Testnet / Mainnet Switching
+
+Depending on which network is configured in web3 object, a set of contracts will be used.
+Available networks:
+- Mainnet
+- Görli
+- Ropsten
+- Rinkeby
+
+## Development
+
+Clone project:
+```bash
+git clone --recurse-submodules https://github.com/lidofinance/lido-python-sdk.git
+cd lido-python-sdk
+```
+Create virtual env:
+```bash
+virtualenv .env --python=python3
+source .env/bin/activate
+```
+Install all dependencies:
+```bash
+ poetry install
+```
+Activate virtual env
+```bash
+ poetry shell
+```
+Build blst locally (linux):
+```bash
+ cd blst/
+ ./build.sh
+ cd ..
+ mkdir -p ./blst-lib/linux/
+ cp ./blst/libblst.a ./blst-lib/linux/
+ cp ./blst/bindings/blst.h ./blst-lib/
+ cp ./blst/bindings/blst.hpp ./blst-lib/
+ cp ./blst/bindings/blst_aux.h ./blst-lib/
+ python setup.py build_ext --inplace
+```
+Build blst locally (osx):
+```bash
+ cd blst/
+ ./build.sh
+ cd ..
+ mkdir -p ./blst-lib/darwin/
+ cp ./blst/libblst.a ./blst-lib/darwin/
+ cp ./blst/bindings/blst.h ./blst-lib/
+ cp ./blst/bindings/blst.hpp ./blst-lib/
+ cp ./blst/bindings/blst_aux.h ./blst-lib/
+ python setup.py build_ext --inplace
+```
+Build blst locally (osx arm):
+```bash
+ cd blst/
+ ./build.sh
+ cd ..
+ mkdir -p ./blst-lib/darwin-arm64/
+ cp ./blst/libblst.a ./blst-lib/darwin-arm64/
+ cp ./blst/bindings/blst.h ./blst-lib/
+ cp ./blst/bindings/blst.hpp ./blst-lib/
+ cp ./blst/bindings/blst_aux.h ./blst-lib/
+ python setup.py build_ext --inplace
+```
+
+## How to test
+Simply run in project root directory:
+```bash
+poetry run pytest .
+```
+
+## Release new version
+```bash
+git tag v2.x.x master
+git push --tags
+```
+New version should be published after all pipelines passed.
+
+## Rebuild blst
+Goto actions "Build blst and create PR".
+Note that darwin-arm64 binaries are not rebuilt automatically due to GitHub Actions not supporting macOS runners on arm yet
+Review PR and merge.
+Do a release.
+
+
+
+
+%prep
+%autosetup -n lido-sdk-4.0.0
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-lido-sdk -f filelist.lst
+%dir %{python3_sitearch}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Fri May 05 2023 Python_Bot <Python_Bot@openeuler.org> - 4.0.0-1
+- Package Spec generated