# PyXatu
<img src="https://github.com/nerolation/pyxatu/blob/main/logo/pyxatu.png?raw=true" width="400">
Pyxatu is a Python package for querying data from the [Xatu](https://ethpandaops.io/data/xatu/schema/) database and was developed to make access to Ethereum data as easy as possible without sacrificing on a rich set of features.
---
**Pyxatu comes out of the box with:**
* High level access to Xatu (Ethereum EL + CL)
* Mevboost Data API Interface
* Validator label mapping
## Install
```console
pip install pyxatu
xatu setup
```
`xatu setup` copies the default configuration file to your HOME directory as `.pyxatu_config.json`. Update this file with your actual Xatu credentials. Alternatively, you can use environment variables.
If you don't have credentials yet, please get in contact with someone from [EthPandaOps](https://ethpandaops.io/).
## Example Usage
As a first step, we always want to initialize PyXatu.
```python
import pyxatu
xatu = pyxatu.PyXatu()
```
We use `xatu` to execute our first query: We want to get the *block number* and the *gas used* of a block in a certain slot:
```python
df = xatu.get_slots(
slot = [9000000, 9000010],
columns="slot, execution_payload_block_number, execution_payload_gas_used",
orderby="slot"
)
print(df)
```
| slot | execution_payload_block_number | execution_payload_gas_used |
|--------:|---------------------------------:|-----------------------------:|
| 9000000 | 19796604 | 18026681 |
| 9000001 | 19796605 | 13920219 |
| 9000002 | 19796606 | 12498513 |
| 9000003 | 19796607 | 2914192 |
| 9000004 | 19796608 | 29996743 |
| ... | ... | ... |
Second, let's say we want to know which validator attested correctly in a certain epoch:
```python
df = xatu.get_elaborated_attestations(slot = 9000000)
print(df.head().to_markdown(index=False))
```
| slot | validator | status | vote_type |
|--------:|------------:|:---------|:------------|
| 9000000 | 7 | correct | source |
| 9000000 | 1179655 | correct | source |
| 9000000 | 524305 | correct | source |
| 9000000 | 17 | correct | source |
| 9000000 | 1179681 | correct | source |
| ... | ... | ... | ... |
Next, we want to get all bids accross all mevboost relays for a specific slot:
```python
df = xatu.mevboost.get_bids(slot = 9096969)
print(df.groupby("relay")["value"].median().reset_index().to_markdown(index=False))
```
| relay | value |
|:-----------------------|------------:|
| aestus | 3.92872e+16 |
| bloxroute (max profit) | 3.89533e+16 |
| bloxroute (regulated) | 3.89042e+16 |
| eden | 3.07634e+16 |
| flashbots | 3.89779e+16 |
and the delivered mevboost payloads:
```python
df = xatu.mevboost.get_payloads(slot = 9814162)
print(df.groupby("relay")["value"].median().reset_index().to_markdown(index=False))
```
| relay | value |
|:-----------------------|------------:|
| bloxroute (max profit) | 1.39261e+16 |
| ultra sound | 1.39261e+16 |
What if we need a mappling from validator ids to labels:
```python
xatu.validators.mapping[["validator_id", "deposit_address", "label", "lido_node_operator"]]
```
| validator_id | deposit_address | label | lido_node_operator |
|---------------:|:-------------------------------------------|:--------|:---------------------|
| 1545106 | 0xfddf38947afb03c621c71b06c9c70bce73f12999 | lido | Develp GmbH |
| 1545105 | 0xfddf38947afb03c621c71b06c9c70bce73f12999 | lido | Develp GmbH |
| 1546068 | 0xd523794c879d9ec028960a231f866758e405be34 | everstake | |
| 1546067 | 0xe3cbd06d7dadb3f4e6557bab7edd924cd1489e8f | mantle | |
| 1546066 | 0xd4039ecc40aeda0582036437cf3ec02845da4c13 | kraken | |
| 1546065 | 0xd4039ecc40aeda0582036437cf3ec02845da4c13 | kraken | |
| 1545103 | 0xfddf38947afb03c621c71b06c9c70bce73f12999 | lido | Launchnodes |
| 1545102 | 0xfddf38947afb03c621c71b06c9c70bce73f12999 | lido | Launchnodes |
## Contribution Guidelines
Please follow these steps to contribute:
1. **Fork the Repository**: Start by forking the repository to your GitHub account.
2. **Create a New Branch**: Create a new branch for your feature or bugfix.
```
git checkout -b feature/new-feature
```
3. **Write Tests**: Ensure your code is well-tested and follows the project's coding standards.
4. **Submit a Pull Request**: Once you're ready, submit a pull request for review.
New contributions that help improve PyXatu are more than welcome!
---
For any additional questions or support, feel free to open an issue on the [GitHub repository](https://github.com/nerolation/pyxatu).
Raw data
{
"_id": null,
"home_page": "https://github.com/nerolation/pyxatu",
"name": "pyxatu",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": null,
"author": "Toni Wahrst\u00e4tter",
"author_email": "toni@ethereum.org",
"download_url": "https://files.pythonhosted.org/packages/f0/30/b6f402677fe09573e1fed0e1a8b87d0708e2cb23ed99ea95849307da93b9/pyxatu-1.8.tar.gz",
"platform": null,
"description": "# PyXatu\n\n<img src=\"https://github.com/nerolation/pyxatu/blob/main/logo/pyxatu.png?raw=true\" width=\"400\">\n\n\n\nPyxatu is a Python package for querying data from the [Xatu](https://ethpandaops.io/data/xatu/schema/) database and was developed to make access to Ethereum data as easy as possible without sacrificing on a rich set of features.\n\n---\n\n**Pyxatu comes out of the box with:**\n* High level access to Xatu (Ethereum EL + CL)\n* Mevboost Data API Interface\n* Validator label mapping\n\n ## Install\n\n ```console\n pip install pyxatu\n xatu setup\n ```\n\n\n`xatu setup` copies the default configuration file to your HOME directory as `.pyxatu_config.json`. Update this file with your actual Xatu credentials. Alternatively, you can use environment variables.\nIf you don't have credentials yet, please get in contact with someone from [EthPandaOps](https://ethpandaops.io/).\n\n## Example Usage\n\n\nAs a first step, we always want to initialize PyXatu. \n ```python\n import pyxatu\n\n xatu = pyxatu.PyXatu()\n ```\n\nWe use `xatu` to execute our first query: We want to get the *block number* and the *gas used* of a block in a certain slot:\n\n ```python\n df = xatu.get_slots(\n slot = [9000000, 9000010],\n columns=\"slot, execution_payload_block_number, execution_payload_gas_used\",\n orderby=\"slot\"\n )\n\n print(df)\n ```\n\n| slot | execution_payload_block_number | execution_payload_gas_used |\n|--------:|---------------------------------:|-----------------------------:|\n| 9000000 | 19796604 | 18026681 |\n| 9000001 | 19796605 | 13920219 |\n| 9000002 | 19796606 | 12498513 |\n| 9000003 | 19796607 | 2914192 |\n| 9000004 | 19796608 | 29996743 |\n| ... | ... | ... |\n\n\n\nSecond, let's say we want to know which validator attested correctly in a certain epoch:\n\n ```python\n df = xatu.get_elaborated_attestations(slot = 9000000)\n\n print(df.head().to_markdown(index=False))\n ```\n\n\n| slot | validator | status | vote_type |\n|--------:|------------:|:---------|:------------|\n| 9000000 | 7 | correct | source |\n| 9000000 | 1179655 | correct | source |\n| 9000000 | 524305 | correct | source |\n| 9000000 | 17 | correct | source |\n| 9000000 | 1179681 | correct | source |\n| ... | ... | ... | ... |\n\n\nNext, we want to get all bids accross all mevboost relays for a specific slot:\n\n\n```python\ndf = xatu.mevboost.get_bids(slot = 9096969)\n\nprint(df.groupby(\"relay\")[\"value\"].median().reset_index().to_markdown(index=False))\n```\n\n\n| relay | value |\n|:-----------------------|------------:|\n| aestus | 3.92872e+16 |\n| bloxroute (max profit) | 3.89533e+16 |\n| bloxroute (regulated) | 3.89042e+16 |\n| eden | 3.07634e+16 |\n| flashbots | 3.89779e+16 |\n\n\nand the delivered mevboost payloads:\n\n```python\ndf = xatu.mevboost.get_payloads(slot = 9814162)\n\nprint(df.groupby(\"relay\")[\"value\"].median().reset_index().to_markdown(index=False))\n```\n\n| relay | value |\n|:-----------------------|------------:|\n| bloxroute (max profit) | 1.39261e+16 |\n| ultra sound | 1.39261e+16 |\n\n\nWhat if we need a mappling from validator ids to labels:\n\n```python\nxatu.validators.mapping[[\"validator_id\", \"deposit_address\", \"label\", \"lido_node_operator\"]]\n```\n\n| validator_id | deposit_address | label | lido_node_operator |\n|---------------:|:-------------------------------------------|:--------|:---------------------|\n| 1545106 | 0xfddf38947afb03c621c71b06c9c70bce73f12999 | lido | Develp GmbH |\n| 1545105 | 0xfddf38947afb03c621c71b06c9c70bce73f12999 | lido | Develp GmbH |\n| 1546068 | 0xd523794c879d9ec028960a231f866758e405be34 | everstake | |\n| 1546067 | 0xe3cbd06d7dadb3f4e6557bab7edd924cd1489e8f | mantle | |\n| 1546066 | 0xd4039ecc40aeda0582036437cf3ec02845da4c13 | kraken | |\n| 1546065 | 0xd4039ecc40aeda0582036437cf3ec02845da4c13 | kraken | |\n| 1545103 | 0xfddf38947afb03c621c71b06c9c70bce73f12999 | lido | Launchnodes |\n| 1545102 | 0xfddf38947afb03c621c71b06c9c70bce73f12999 | lido | Launchnodes |\n\n\n## Contribution Guidelines\n\nPlease follow these steps to contribute:\n\n1. **Fork the Repository**: Start by forking the repository to your GitHub account.\n2. **Create a New Branch**: Create a new branch for your feature or bugfix.\n ```\n git checkout -b feature/new-feature\n ```\n3. **Write Tests**: Ensure your code is well-tested and follows the project's coding standards.\n4. **Submit a Pull Request**: Once you're ready, submit a pull request for review.\n\n\nNew contributions that help improve PyXatu are more than welcome!\n\n---\n\nFor any additional questions or support, feel free to open an issue on the [GitHub repository](https://github.com/nerolation/pyxatu).\n",
"bugtrack_url": null,
"license": null,
"summary": "A Python interface for the Xatu API",
"version": "1.8",
"project_urls": {
"Homepage": "https://github.com/nerolation/pyxatu"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "2a5f57ead2b50b4399da8719c8601ffc65aacba63d9d6d2805b8b37ab0517b8e",
"md5": "689805a1069cff71fb3c346edea30df3",
"sha256": "f66549f431d7a7a741aacb15674d31fa6d392531abc37c72d3de24197a637f37"
},
"downloads": -1,
"filename": "pyxatu-1.8-py3-none-any.whl",
"has_sig": false,
"md5_digest": "689805a1069cff71fb3c346edea30df3",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 26712,
"upload_time": "2024-10-28T12:06:08",
"upload_time_iso_8601": "2024-10-28T12:06:08.336191Z",
"url": "https://files.pythonhosted.org/packages/2a/5f/57ead2b50b4399da8719c8601ffc65aacba63d9d6d2805b8b37ab0517b8e/pyxatu-1.8-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f030b6f402677fe09573e1fed0e1a8b87d0708e2cb23ed99ea95849307da93b9",
"md5": "ed51fa4ec8218991b969503a861768b1",
"sha256": "4adbe97610e7c523a60309697fe4949c0d6bce4c3b3708b237fb83aedd378e7c"
},
"downloads": -1,
"filename": "pyxatu-1.8.tar.gz",
"has_sig": false,
"md5_digest": "ed51fa4ec8218991b969503a861768b1",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 35593,
"upload_time": "2024-10-28T12:06:10",
"upload_time_iso_8601": "2024-10-28T12:06:10.187441Z",
"url": "https://files.pythonhosted.org/packages/f0/30/b6f402677fe09573e1fed0e1a8b87d0708e2cb23ed99ea95849307da93b9/pyxatu-1.8.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-28 12:06:10",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "nerolation",
"github_project": "pyxatu",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "beautifulsoup4",
"specs": [
[
"==",
"4.12.3"
]
]
},
{
"name": "bs4",
"specs": [
[
"==",
"0.0.2"
]
]
},
{
"name": "certifi",
"specs": [
[
"==",
"2024.7.4"
]
]
},
{
"name": "charset-normalizer",
"specs": [
[
"==",
"3.3.2"
]
]
},
{
"name": "cramjam",
"specs": [
[
"==",
"2.8.3"
]
]
},
{
"name": "fastparquet",
"specs": [
[
"==",
"2024.5.0"
]
]
},
{
"name": "fsspec",
"specs": [
[
"==",
"2024.6.1"
]
]
},
{
"name": "idna",
"specs": [
[
"==",
"3.7"
]
]
},
{
"name": "numpy",
"specs": [
[
"==",
"2.1.0"
]
]
},
{
"name": "packaging",
"specs": [
[
"==",
"24.1"
]
]
},
{
"name": "pandas",
"specs": [
[
"==",
"2.2.2"
]
]
},
{
"name": "python-dateutil",
"specs": [
[
"==",
"2.9.0.post0"
]
]
},
{
"name": "pytz",
"specs": [
[
"==",
"2024.1"
]
]
},
{
"name": "pyxatu",
"specs": []
},
{
"name": "requests",
"specs": [
[
"==",
"2.32.3"
]
]
},
{
"name": "six",
"specs": [
[
"==",
"1.16.0"
]
]
},
{
"name": "soupsieve",
"specs": [
[
"==",
"2.6"
]
]
},
{
"name": "termcolor",
"specs": [
[
"==",
"2.4.0"
]
]
},
{
"name": "tqdm",
"specs": [
[
"==",
"4.66.5"
]
]
},
{
"name": "tzdata",
"specs": [
[
"==",
"2024.1"
]
]
},
{
"name": "urllib3",
"specs": [
[
"==",
"2.2.2"
]
]
}
],
"lcname": "pyxatu"
}