eth-portfolio-temp 0.2.16__cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eth_portfolio/__init__.py +25 -0
- eth_portfolio/_argspec.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio/_argspec.py +42 -0
- eth_portfolio/_cache.py +121 -0
- eth_portfolio/_config.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio/_config.py +4 -0
- eth_portfolio/_db/__init__.py +0 -0
- eth_portfolio/_db/decorators.py +147 -0
- eth_portfolio/_db/entities.py +311 -0
- eth_portfolio/_db/utils.py +604 -0
- eth_portfolio/_decimal.py +156 -0
- eth_portfolio/_decorators.py +84 -0
- eth_portfolio/_exceptions.py +67 -0
- eth_portfolio/_ledgers/__init__.py +0 -0
- eth_portfolio/_ledgers/address.py +938 -0
- eth_portfolio/_ledgers/portfolio.py +327 -0
- eth_portfolio/_loaders/__init__.py +33 -0
- eth_portfolio/_loaders/_nonce.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio/_loaders/_nonce.py +196 -0
- eth_portfolio/_loaders/balances.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio/_loaders/balances.py +94 -0
- eth_portfolio/_loaders/token_transfer.py +217 -0
- eth_portfolio/_loaders/transaction.py +240 -0
- eth_portfolio/_loaders/utils.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio/_loaders/utils.py +68 -0
- eth_portfolio/_shitcoins.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio/_shitcoins.py +330 -0
- eth_portfolio/_stableish.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio/_stableish.py +42 -0
- eth_portfolio/_submodules.py +73 -0
- eth_portfolio/_utils.py +225 -0
- eth_portfolio/_ydb/__init__.py +0 -0
- eth_portfolio/_ydb/token_transfers.py +145 -0
- eth_portfolio/address.py +397 -0
- eth_portfolio/buckets.py +194 -0
- eth_portfolio/constants.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio/constants.py +82 -0
- eth_portfolio/portfolio.py +661 -0
- eth_portfolio/protocols/__init__.py +67 -0
- eth_portfolio/protocols/_base.py +108 -0
- eth_portfolio/protocols/convex.py +17 -0
- eth_portfolio/protocols/dsr.py +51 -0
- eth_portfolio/protocols/lending/README.md +6 -0
- eth_portfolio/protocols/lending/__init__.py +50 -0
- eth_portfolio/protocols/lending/_base.py +57 -0
- eth_portfolio/protocols/lending/compound.py +187 -0
- eth_portfolio/protocols/lending/liquity.py +110 -0
- eth_portfolio/protocols/lending/maker.py +104 -0
- eth_portfolio/protocols/lending/unit.py +46 -0
- eth_portfolio/protocols/liquity.py +16 -0
- eth_portfolio/py.typed +0 -0
- eth_portfolio/structs/__init__.py +43 -0
- eth_portfolio/structs/modified.py +69 -0
- eth_portfolio/structs/structs.py +637 -0
- eth_portfolio/typing/__init__.py +1447 -0
- eth_portfolio/typing/balance/single.py +176 -0
- eth_portfolio__mypyc.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio_scripts/__init__.py +20 -0
- eth_portfolio_scripts/_args.py +26 -0
- eth_portfolio_scripts/_logging.py +15 -0
- eth_portfolio_scripts/_portfolio.py +194 -0
- eth_portfolio_scripts/_utils.py +106 -0
- eth_portfolio_scripts/balances.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio_scripts/balances.py +52 -0
- eth_portfolio_scripts/docker/.grafana/dashboards/Portfolio/Balances.json +1962 -0
- eth_portfolio_scripts/docker/.grafana/dashboards/dashboards.yaml +10 -0
- eth_portfolio_scripts/docker/.grafana/datasources/datasources.yml +11 -0
- eth_portfolio_scripts/docker/__init__.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio_scripts/docker/__init__.py +16 -0
- eth_portfolio_scripts/docker/check.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio_scripts/docker/check.py +67 -0
- eth_portfolio_scripts/docker/docker-compose.yaml +61 -0
- eth_portfolio_scripts/docker/docker_compose.cpython-312-i386-linux-gnu.so +0 -0
- eth_portfolio_scripts/docker/docker_compose.py +96 -0
- eth_portfolio_scripts/main.py +119 -0
- eth_portfolio_scripts/py.typed +1 -0
- eth_portfolio_scripts/victoria/__init__.py +73 -0
- eth_portfolio_scripts/victoria/types.py +38 -0
- eth_portfolio_temp-0.2.16.dist-info/METADATA +26 -0
- eth_portfolio_temp-0.2.16.dist-info/RECORD +83 -0
- eth_portfolio_temp-0.2.16.dist-info/WHEEL +7 -0
- eth_portfolio_temp-0.2.16.dist-info/entry_points.txt +2 -0
- eth_portfolio_temp-0.2.16.dist-info/top_level.txt +3 -0
|
Binary file
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from eth_portfolio_scripts.docker.check import check_docker, check_docker_compose, check_system
|
|
2
|
+
from eth_portfolio_scripts.docker.docker_compose import build, down, ensure_containers, up, stop
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
# commands
|
|
6
|
+
"build",
|
|
7
|
+
"up",
|
|
8
|
+
"down",
|
|
9
|
+
"stop",
|
|
10
|
+
# decorators
|
|
11
|
+
"ensure_containers",
|
|
12
|
+
# checks
|
|
13
|
+
"check_docker",
|
|
14
|
+
"check_docker_compose",
|
|
15
|
+
"check_system",
|
|
16
|
+
]
|
|
Binary file
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from functools import lru_cache
|
|
2
|
+
from subprocess import CalledProcessError, check_output
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def check_docker() -> None:
|
|
7
|
+
"""
|
|
8
|
+
Check that docker is installed on the user's system.
|
|
9
|
+
|
|
10
|
+
Raises:
|
|
11
|
+
RuntimeError: If docker is not installed.
|
|
12
|
+
"""
|
|
13
|
+
print(" 🔍 checking your computer for docker")
|
|
14
|
+
try:
|
|
15
|
+
check_output(["docker", "--version"])
|
|
16
|
+
except (CalledProcessError, FileNotFoundError):
|
|
17
|
+
raise RuntimeError(
|
|
18
|
+
"Docker is not installed. You must install Docker before using dao-treasury."
|
|
19
|
+
) from None
|
|
20
|
+
else:
|
|
21
|
+
print(" ✔️ eth-portfolio found docker!")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def check_docker_compose() -> List[str]:
|
|
25
|
+
"""
|
|
26
|
+
Check that either `docker-compose` or `docker compose` is installed on the user's system.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
A valid compose command.
|
|
30
|
+
|
|
31
|
+
Raises:
|
|
32
|
+
RuntimeError: If docker-compose is not installed.
|
|
33
|
+
"""
|
|
34
|
+
for cmd in ["docker-compose", "docker compose"]:
|
|
35
|
+
print(f" 🔍 checking your computer for {cmd}")
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
check_output([*cmd.split(" "), "--version"])
|
|
39
|
+
except (CalledProcessError, FileNotFoundError):
|
|
40
|
+
print(f" ❌ {cmd} not found")
|
|
41
|
+
continue
|
|
42
|
+
else:
|
|
43
|
+
print(f" ✔️ eth-portfolio found {cmd}!")
|
|
44
|
+
return cmd.split(" ")
|
|
45
|
+
|
|
46
|
+
raise RuntimeError(
|
|
47
|
+
"Docker Compose is not installed. You must install Docker Compose before using dao-treasury."
|
|
48
|
+
) from None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@lru_cache(maxsize=None)
|
|
52
|
+
def check_system() -> List[str]:
|
|
53
|
+
"""
|
|
54
|
+
Check that docker and docker-compose is installed on the user's system.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
A valid compose command.
|
|
58
|
+
|
|
59
|
+
Raises:
|
|
60
|
+
RuntimeError: If docker-compose is not installed.
|
|
61
|
+
"""
|
|
62
|
+
print("eth-portfolio is checking for the required docker dependencies...")
|
|
63
|
+
check_docker()
|
|
64
|
+
return check_docker_compose()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
__all__ = ["check_docker", "check_docker_compose", "check_system"]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
networks:
|
|
2
|
+
eth_portfolio:
|
|
3
|
+
|
|
4
|
+
services:
|
|
5
|
+
grafana:
|
|
6
|
+
image: grafana/grafana:12.2.1
|
|
7
|
+
ports:
|
|
8
|
+
- 127.0.0.1:${GRAFANA_PORT:-3000}:3000
|
|
9
|
+
environment:
|
|
10
|
+
- GF_SECURITY_ADMIN_USER=${GF_SECURITY_ADMIN_USER:-admin}
|
|
11
|
+
- GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD:-admin}
|
|
12
|
+
- GF_AUTH_ANONYMOUS_ENABLED=true
|
|
13
|
+
- GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH=/etc/grafana/provisioning/dashboards/portfolio/Balances.json
|
|
14
|
+
- GF_SERVER_ROOT_URL
|
|
15
|
+
- GF_RENDERING_SERVER_URL=http://renderer:8091/render
|
|
16
|
+
- GF_RENDERING_CALLBACK_URL=http://grafana:3000/
|
|
17
|
+
- GF_LOG_FILTERS=rendering:debug
|
|
18
|
+
#- GF_INSTALL_PLUGINS=volkovlabs-variable-panel
|
|
19
|
+
#command: >
|
|
20
|
+
# sh -c "grafana-cli plugins install frser-sqlite-datasource && /run.sh"
|
|
21
|
+
volumes:
|
|
22
|
+
- ./.grafana/:/etc/grafana/provisioning/
|
|
23
|
+
networks:
|
|
24
|
+
- eth_portfolio
|
|
25
|
+
restart: always
|
|
26
|
+
|
|
27
|
+
renderer:
|
|
28
|
+
platform: linux/amd64
|
|
29
|
+
image: grafana/grafana-image-renderer:latest
|
|
30
|
+
ports:
|
|
31
|
+
- 127.0.0.1:${RENDERER_PORT:-8091}:8091
|
|
32
|
+
environment:
|
|
33
|
+
- ENABLE_METRICS=true
|
|
34
|
+
- HTTP_PORT=8091
|
|
35
|
+
networks:
|
|
36
|
+
- eth_portfolio
|
|
37
|
+
restart: always
|
|
38
|
+
|
|
39
|
+
vmagent:
|
|
40
|
+
image: victoriametrics/vmagent:heads-public-single-node-0-g52eb9c99e
|
|
41
|
+
command:
|
|
42
|
+
- "-remoteWrite.url=http://victoria-metrics:8428/api/v1/write"
|
|
43
|
+
depends_on:
|
|
44
|
+
- victoria-metrics
|
|
45
|
+
networks:
|
|
46
|
+
- eth_portfolio
|
|
47
|
+
restart: always
|
|
48
|
+
|
|
49
|
+
victoria-metrics:
|
|
50
|
+
image: victoriametrics/victoria-metrics:v1.129.1
|
|
51
|
+
volumes:
|
|
52
|
+
- ~/.eth-portfolio/data/victoria/:/victoria-metrics-data
|
|
53
|
+
command:
|
|
54
|
+
- '-memory.allowedBytes=3GB'
|
|
55
|
+
- "-retentionPeriod=10y"
|
|
56
|
+
- "-search.disableAutoCacheReset=true"
|
|
57
|
+
ports:
|
|
58
|
+
- 127.0.0.1:${VICTORIA_PORT:-8428}:8428
|
|
59
|
+
networks:
|
|
60
|
+
- eth_portfolio
|
|
61
|
+
restart: always
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from functools import wraps
|
|
3
|
+
from importlib import resources
|
|
4
|
+
from os import path
|
|
5
|
+
from subprocess import CalledProcessError, check_output
|
|
6
|
+
from typing import Callable, Final, Iterable, List, Literal, Tuple, TypeVar
|
|
7
|
+
|
|
8
|
+
from typing_extensions import ParamSpec
|
|
9
|
+
|
|
10
|
+
from eth_portfolio_scripts.docker.check import check_system
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
logger: Final = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
COMPOSE_FILE: Final = str(
|
|
16
|
+
resources.files("eth_portfolio_scripts").joinpath("docker/docker-compose.yaml")
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def up(*services: str) -> None:
|
|
21
|
+
"""Build and start the specified docker-compose services."""
|
|
22
|
+
build(*services)
|
|
23
|
+
_print_notice("starting", services)
|
|
24
|
+
_exec_command(["up", "-d", *services])
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def down() -> None:
|
|
28
|
+
"""Stop all of eth-portfolio's docker-compose services."""
|
|
29
|
+
_exec_command(["down"])
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def build(*services: str) -> None:
|
|
33
|
+
"""Build the specified docker-compose services."""
|
|
34
|
+
_print_notice("building", services)
|
|
35
|
+
_exec_command(["build", *services])
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def stop(*services: str) -> None:
|
|
39
|
+
"""Stop the specified docker-compose services, if running."""
|
|
40
|
+
_print_notice("stopping", services)
|
|
41
|
+
_exec_command(["stop", *services])
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
_P = ParamSpec("_P")
|
|
45
|
+
_T = TypeVar("_T")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def ensure_containers(fn: Callable[_P, _T]) -> Callable[_P, _T]:
|
|
49
|
+
@wraps(fn)
|
|
50
|
+
async def compose_wrap(*args: _P.args, **kwargs: _P.kwargs) -> _T:
|
|
51
|
+
# register shutdown sequence
|
|
52
|
+
# TODO: argument to leave them up
|
|
53
|
+
# NOTE: do we need both this and the finally?
|
|
54
|
+
# signal.signal(signal.SIGINT, down)
|
|
55
|
+
|
|
56
|
+
# start Grafana containers
|
|
57
|
+
up()
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
# attempt to run `fn`
|
|
61
|
+
return await fn(*args, **kwargs)
|
|
62
|
+
finally:
|
|
63
|
+
# stop and remove containers
|
|
64
|
+
# down()
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
return compose_wrap
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _print_notice(
|
|
71
|
+
doing: Literal["building", "starting", "stopping"],
|
|
72
|
+
services: Tuple[str, ...],
|
|
73
|
+
) -> None:
|
|
74
|
+
if len(services) == 1:
|
|
75
|
+
container = services[0]
|
|
76
|
+
print(f"{doing} the {container} container")
|
|
77
|
+
elif len(services) == 2:
|
|
78
|
+
first, second = services
|
|
79
|
+
print(f"{doing} the {first} and {second} containers")
|
|
80
|
+
else:
|
|
81
|
+
*all_but_last, last = services
|
|
82
|
+
print(f"{doing} the {', '.join(all_but_last)}, and {last} containers")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _exec_command(
|
|
86
|
+
command: List[str],
|
|
87
|
+
*,
|
|
88
|
+
compose_file: str = COMPOSE_FILE,
|
|
89
|
+
compose_options: Tuple[str, ...] = (),
|
|
90
|
+
) -> None:
|
|
91
|
+
compose = check_system()
|
|
92
|
+
full_command = [*compose, *compose_options, "-f", compose_file, *command]
|
|
93
|
+
try:
|
|
94
|
+
check_output(full_command)
|
|
95
|
+
except (CalledProcessError, FileNotFoundError) as e:
|
|
96
|
+
raise RuntimeError(f"Error occurred while running `{' '.join(full_command)}`: {e}") from e
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from argparse import ArgumentParser
|
|
3
|
+
from os import environ
|
|
4
|
+
|
|
5
|
+
import brownie
|
|
6
|
+
|
|
7
|
+
from eth_portfolio_scripts import docker, logger
|
|
8
|
+
from eth_portfolio_scripts._args import add_infra_port_args
|
|
9
|
+
from eth_portfolio_scripts.balances import export_balances
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
parser = ArgumentParser(description="eth-portfolio")
|
|
13
|
+
|
|
14
|
+
subparsers = parser.add_subparsers(title="Commands", dest="command", required=True)
|
|
15
|
+
|
|
16
|
+
export_parser = subparsers.add_parser("export", help="Export a specific dataset for your portfolio")
|
|
17
|
+
export_parser.add_argument("target", help="Choose an exporter to run")
|
|
18
|
+
add_infra_port_args(export_parser)
|
|
19
|
+
export_parser.set_defaults(func=export_balances)
|
|
20
|
+
|
|
21
|
+
infra_parser = subparsers.add_parser(
|
|
22
|
+
"infra", help="Start the docker containers required to run any eth-portfolio service"
|
|
23
|
+
)
|
|
24
|
+
infra_parser.add_argument("cmd", help="What do you want to do?")
|
|
25
|
+
add_infra_port_args(infra_parser)
|
|
26
|
+
infra_parser.add_argument(
|
|
27
|
+
"--start-renderer",
|
|
28
|
+
action="store_true",
|
|
29
|
+
help="If set, starts the renderer container in addition to the default containers. By default, only grafana, victoria-metrics, and vmagent are started.",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
export_parser.add_argument(
|
|
33
|
+
"--wallet",
|
|
34
|
+
type=str,
|
|
35
|
+
help="The address of a wallet to export. You can pass multiple, ie. `--wallet 0x123 0x234 0x345`",
|
|
36
|
+
required=True,
|
|
37
|
+
nargs="+",
|
|
38
|
+
)
|
|
39
|
+
export_parser.add_argument(
|
|
40
|
+
"--network",
|
|
41
|
+
type=str,
|
|
42
|
+
help="The brownie network identifier for the rpc you wish to use. default: mainnet",
|
|
43
|
+
default="mainnet",
|
|
44
|
+
)
|
|
45
|
+
export_parser.add_argument(
|
|
46
|
+
"--label",
|
|
47
|
+
type=str,
|
|
48
|
+
help='The label for this portfolio, if you want one. Defaults to "MyPortfolio".',
|
|
49
|
+
default="My Portfolio",
|
|
50
|
+
)
|
|
51
|
+
export_parser.add_argument(
|
|
52
|
+
"--interval",
|
|
53
|
+
type=str,
|
|
54
|
+
help="The time interval between datapoints. default: 6h",
|
|
55
|
+
default="6h",
|
|
56
|
+
)
|
|
57
|
+
export_parser.add_argument(
|
|
58
|
+
"--concurrency",
|
|
59
|
+
type=int,
|
|
60
|
+
help="The max number of historical blocks to export concurrently. default: 40",
|
|
61
|
+
default=40,
|
|
62
|
+
)
|
|
63
|
+
export_parser.add_argument(
|
|
64
|
+
"--first-tx-block",
|
|
65
|
+
type=int,
|
|
66
|
+
help=(
|
|
67
|
+
"The block of your portfolio's first transaction, if known. "
|
|
68
|
+
"This value, if provided, allows us to speed up processing of your data by limiting the block range we need to query. "
|
|
69
|
+
"If not provided, the whole blockchain will be scanned."
|
|
70
|
+
),
|
|
71
|
+
default=0,
|
|
72
|
+
)
|
|
73
|
+
export_parser.add_argument(
|
|
74
|
+
"--export-start-block",
|
|
75
|
+
type=int,
|
|
76
|
+
help="The first block in the range you wish to export.",
|
|
77
|
+
default=0,
|
|
78
|
+
)
|
|
79
|
+
export_parser.add_argument(
|
|
80
|
+
"--daemon",
|
|
81
|
+
action="store_true",
|
|
82
|
+
help="TODO: If True, starts a daemon process instead of running in your terminal. Not currently supported.",
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
args = parser.parse_args()
|
|
86
|
+
|
|
87
|
+
if hasattr(args, "network"):
|
|
88
|
+
environ["BROWNIE_NETWORK_ID"] = args.network
|
|
89
|
+
|
|
90
|
+
environ["GRAFANA_PORT"] = str(args.grafana_port)
|
|
91
|
+
environ["RENDERER_PORT"] = str(args.renderer_port)
|
|
92
|
+
environ["VICTORIA_PORT"] = str(args.victoria_port)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# TODO: run forever arg
|
|
96
|
+
def main():
|
|
97
|
+
command = args.command
|
|
98
|
+
if command == "infra":
|
|
99
|
+
if args.cmd == "start":
|
|
100
|
+
# Start the backend containers
|
|
101
|
+
if getattr(args, "start_renderer", False):
|
|
102
|
+
docker.up()
|
|
103
|
+
else:
|
|
104
|
+
docker.up("grafana", "victoria-metrics", "vmagent")
|
|
105
|
+
elif args.cmd == "stop":
|
|
106
|
+
docker.down()
|
|
107
|
+
else:
|
|
108
|
+
raise ValueError(f"{args.target} is not a valid command")
|
|
109
|
+
|
|
110
|
+
else:
|
|
111
|
+
# The user's command is `export`
|
|
112
|
+
if args.target == "balances":
|
|
113
|
+
asyncio.run(args.func(args))
|
|
114
|
+
else:
|
|
115
|
+
raise ValueError(f"{args.target} is not a valid command")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
if __name__ == "__main__":
|
|
119
|
+
brownie.project.run(__file__)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from gzip import compress
|
|
2
|
+
from logging import getLogger
|
|
3
|
+
from os import environ
|
|
4
|
+
from typing import Final, List
|
|
5
|
+
|
|
6
|
+
import a_sync
|
|
7
|
+
from aiohttp import ClientError, ClientSession, ServerDisconnectedError
|
|
8
|
+
from msgspec import json
|
|
9
|
+
|
|
10
|
+
from eth_portfolio_scripts.victoria import types
|
|
11
|
+
from eth_portfolio_scripts.victoria.types import Metric
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
BASE_URL: Final = environ.get("VM_URL", "http://127.0.0.1:8430")
|
|
15
|
+
|
|
16
|
+
# this will be populated later
|
|
17
|
+
session: ClientSession = None # type: ignore [assignment]
|
|
18
|
+
|
|
19
|
+
logger: Final = getLogger("eth_portfolio.victoria")
|
|
20
|
+
|
|
21
|
+
encode: Final = json.encode
|
|
22
|
+
decode: Final = json.decode
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class VictoriaMetricsError(ValueError): ...
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_session() -> ClientSession:
|
|
29
|
+
sesh = session
|
|
30
|
+
if sesh is None:
|
|
31
|
+
sesh = ClientSession(BASE_URL, raise_for_status=True)
|
|
32
|
+
__set_session(sesh)
|
|
33
|
+
return sesh
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
async def get(url: str) -> bytes:
|
|
37
|
+
session = get_session()
|
|
38
|
+
while True:
|
|
39
|
+
try:
|
|
40
|
+
async with session.get(url=url, headers={"Connection": "close"}) as response:
|
|
41
|
+
return await response.read()
|
|
42
|
+
except ServerDisconnectedError:
|
|
43
|
+
continue
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@a_sync.Semaphore(2)
|
|
47
|
+
async def post_data(metrics_to_export: List["Metric"]) -> None:
|
|
48
|
+
"""Post all metrics at once."""
|
|
49
|
+
data = compress(b"\n".join(encode(metric) for metric in metrics_to_export))
|
|
50
|
+
attempts = 0
|
|
51
|
+
session = get_session()
|
|
52
|
+
while True:
|
|
53
|
+
try:
|
|
54
|
+
async with session.post(
|
|
55
|
+
"/api/v1/import",
|
|
56
|
+
headers={"Connection": "close", "Content-Encoding": "gzip"},
|
|
57
|
+
data=data,
|
|
58
|
+
):
|
|
59
|
+
logger.debug(f"posted {len(data)} datas")
|
|
60
|
+
return
|
|
61
|
+
except ClientError as e:
|
|
62
|
+
attempts += 1
|
|
63
|
+
logger.debug("You had a ClientError: %s", e)
|
|
64
|
+
if attempts >= 10:
|
|
65
|
+
raise e
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def __set_session(sesh: ClientSession) -> None:
|
|
69
|
+
global session
|
|
70
|
+
session = sesh
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
__all__ = ["Metric", "get", "post_data"]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
These 2 helpers enable us to decode only the relevant data in the json response and discard the rest
|
|
3
|
+
They're in a separate file so mypyc doesn't try to compile them
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import List, Tuple, TypedDict, final
|
|
7
|
+
|
|
8
|
+
from eth_typing import ChecksumAddress
|
|
9
|
+
from msgspec import Raw, Struct
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@final
|
|
13
|
+
class Metric(TypedDict):
|
|
14
|
+
param: str
|
|
15
|
+
wallet: ChecksumAddress
|
|
16
|
+
token_address: ChecksumAddress
|
|
17
|
+
token: str
|
|
18
|
+
bucket: str
|
|
19
|
+
network: str
|
|
20
|
+
__name__: str
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@final
|
|
24
|
+
class PrometheusItem(TypedDict):
|
|
25
|
+
metric: Metric
|
|
26
|
+
values: List[float]
|
|
27
|
+
timestamps: List[float]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@final
|
|
31
|
+
class Data(Struct):
|
|
32
|
+
result: Tuple[Raw, ...]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@final
|
|
36
|
+
class Response(Struct):
|
|
37
|
+
status: str
|
|
38
|
+
data: Data
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: eth_portfolio_temp
|
|
3
|
+
Version: 0.2.16
|
|
4
|
+
Summary: eth-portfolio makes it easy to analyze your portfolio.
|
|
5
|
+
Home-page: https://github.com/BobTheBuidler/eth-portfolio
|
|
6
|
+
Author: BobTheBuidler
|
|
7
|
+
Author-email: bobthebuidlerdefi@gmail.com
|
|
8
|
+
Requires-Python: >=3.10,<3.14
|
|
9
|
+
Requires-Dist: checksum_dict>=2.1.7
|
|
10
|
+
Requires-Dist: dank_mids>=4.20.154
|
|
11
|
+
Requires-Dist: eth-brownie<1.23,>=1.22.0.dev0
|
|
12
|
+
Requires-Dist: eth_retry<1,>=0.3.4
|
|
13
|
+
Requires-Dist: evmspec>=0.4.1
|
|
14
|
+
Requires-Dist: ez-a-sync>=0.32.27
|
|
15
|
+
Requires-Dist: faster-async-lru==2.0.5
|
|
16
|
+
Requires-Dist: faster-eth-utils
|
|
17
|
+
Requires-Dist: numpy<3
|
|
18
|
+
Requires-Dist: pandas<3,>=1.4.3
|
|
19
|
+
Requires-Dist: typed-envs>=0.0.9
|
|
20
|
+
Requires-Dist: ypricemagic<5,>=4.10.0
|
|
21
|
+
Dynamic: author
|
|
22
|
+
Dynamic: author-email
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
eth_portfolio__mypyc.cpython-312-i386-linux-gnu.so,sha256=a6Fejb31982-bhygTtlefeowU_PTecEdNjs540VA0hg,938092
|
|
2
|
+
eth_portfolio/__init__.py,sha256=0sO4cSJaLYwJfnfVOJRFw7p5_Lzhsr95YuJ1aNQM83A,500
|
|
3
|
+
eth_portfolio/_argspec.cpython-312-i386-linux-gnu.so,sha256=y8-Nw9d9mJ2AwGyFVTDtfcyAUY8km9bNlwwpObTeVPY,16392
|
|
4
|
+
eth_portfolio/_argspec.py,sha256=VzUZkbDkmOSgNUZBGbGblqtxBfDcmBAB89dY2OX0j-U,1595
|
|
5
|
+
eth_portfolio/_cache.py,sha256=IOeMXvMgOlEEk01yHP0RARRZXyonuKXUNZbNLFM_KBU,4805
|
|
6
|
+
eth_portfolio/_config.cpython-312-i386-linux-gnu.so,sha256=qkZJya6uYbqdA5V9u3uBsxXJUzq2CzP_blnPo_6Vay0,16384
|
|
7
|
+
eth_portfolio/_config.py,sha256=mw-OA3M8rUA2hqy5wNt30AZRHkWFgR8K2sJg0o5Baxg,98
|
|
8
|
+
eth_portfolio/_decimal.py,sha256=tYS0miNoQYZguy0yd1bb3bf49l9F3YICyN8ov6r7VBs,4846
|
|
9
|
+
eth_portfolio/_decorators.py,sha256=_ZSurUFEIwZRiMFMhLcIXkD-Ey1CqfBqGaE24hLzOuA,2815
|
|
10
|
+
eth_portfolio/_exceptions.py,sha256=bw3IdXhqrWxeFqYLm7pJZqRHKZas_cCg8A5Ih1WQEqQ,2433
|
|
11
|
+
eth_portfolio/_shitcoins.cpython-312-i386-linux-gnu.so,sha256=ci_KbWBB_VlrlEro1VXW6N7qysADFM7sfF8c4iMci1o,16404
|
|
12
|
+
eth_portfolio/_shitcoins.py,sha256=5OsOC6dYXG6MA2V1hajdiHRfXAX4eG94Wzmh9Dh_5IM,17021
|
|
13
|
+
eth_portfolio/_stableish.cpython-312-i386-linux-gnu.so,sha256=jPFhdIYOQ2JTZcey8Lh1yKD7LQfFwUPRzuOzbEqDbe4,16404
|
|
14
|
+
eth_portfolio/_stableish.py,sha256=VTv69Q91AHxbNbbY0LB4PFwKEseHdkE4_6fLPKH1uW0,2021
|
|
15
|
+
eth_portfolio/_submodules.py,sha256=J8ht9bAAvblUXqwOGN7UIOXUPxrTiq7m1RWiB0-ObaE,2190
|
|
16
|
+
eth_portfolio/_utils.py,sha256=8403ioVA6VX4XaF56CDI9IA4ilTZUf_TrdlQ78chXbQ,7661
|
|
17
|
+
eth_portfolio/address.py,sha256=LvBh4Vp2DBC3gQ0WD-TZ6jfe9s6FZbET1krYG9_KMAA,14139
|
|
18
|
+
eth_portfolio/buckets.py,sha256=30Tv5Tq-IL6NsACKbxp7hge84Q-upWsiWGdDTKkXeqE,6702
|
|
19
|
+
eth_portfolio/constants.cpython-312-i386-linux-gnu.so,sha256=OXEUOHeT0fKPPu70sFUSAg39d_flBXyeDtI1pSHZQdk,16396
|
|
20
|
+
eth_portfolio/constants.py,sha256=LS9H2P_Qfcreb6z6NknErxvq6OAtIHbHykXy0spol9E,3659
|
|
21
|
+
eth_portfolio/portfolio.py,sha256=MP_0Y6fXw8TNoyoFCPiu-MUA44jnMm0L_33gec6MjKU,24248
|
|
22
|
+
eth_portfolio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
+
eth_portfolio/_db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
+
eth_portfolio/_db/decorators.py,sha256=GXL6kqnARl0W1roITfrSZkPKoIi9jxJHEvaj9WH86RQ,5161
|
|
25
|
+
eth_portfolio/_db/entities.py,sha256=wZcOa079gznsm7wl7CvRgPdiCBKBsfCeJgc-dH3PYJA,10034
|
|
26
|
+
eth_portfolio/_db/utils.py,sha256=Qc4oTv4Qte0ytrpskboJRkKbPNi1Ys-GYiy39EqLXiw,20982
|
|
27
|
+
eth_portfolio/_ledgers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
+
eth_portfolio/_ledgers/address.py,sha256=8FxDXApRenyjpedtU7nT8RLfqVbB2O5dBjDjB2dWkBM,32892
|
|
29
|
+
eth_portfolio/_ledgers/portfolio.py,sha256=4qk0tJsD9n6uDwSgF9JJnDuA-osjxeE5b7pTo7ovv6k,13100
|
|
30
|
+
eth_portfolio/_loaders/__init__.py,sha256=lb45_0ak32Z7N3-Nx1CAoRKiZ1_w-_YGbmSCNuunro8,1702
|
|
31
|
+
eth_portfolio/_loaders/_nonce.cpython-312-i386-linux-gnu.so,sha256=_oRgKUOCbFhcIVdqsJhoUeCmRVUzNtnTiEJPpw7xAXs,16400
|
|
32
|
+
eth_portfolio/_loaders/_nonce.py,sha256=cx0EjTAhVU2EudMKSO-7-t1jl3y4dYn6as4XiY6KyS8,6285
|
|
33
|
+
eth_portfolio/_loaders/balances.cpython-312-i386-linux-gnu.so,sha256=-Y5Gawz2qqGIbI7fa5rPeYEkkW-iiVVkoyE7PJGTzYQ,16412
|
|
34
|
+
eth_portfolio/_loaders/balances.py,sha256=BTWfkJIoSraUMe94Wuj8NPyg5EO0OByIjbXu7j6PZEo,3132
|
|
35
|
+
eth_portfolio/_loaders/token_transfer.py,sha256=JupdQRdTPPsnqFhyRv7vt7IhoC2oEtypjxhEfpzTy9E,8531
|
|
36
|
+
eth_portfolio/_loaders/transaction.py,sha256=XLIziLy3YnBPP0E639tQcZfT2Xy4I5VCz6jnfn_C4mE,9153
|
|
37
|
+
eth_portfolio/_loaders/utils.cpython-312-i386-linux-gnu.so,sha256=T4J95BjC0lcWtXqCoK6AQXMjgQng0JzFII96WBUXaNM,16392
|
|
38
|
+
eth_portfolio/_loaders/utils.py,sha256=aoGgWl9ra9F-qb0wA-sX3qelUNGI-fGvM90297L7xWM,2265
|
|
39
|
+
eth_portfolio/_ydb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
|
+
eth_portfolio/_ydb/token_transfers.py,sha256=aKaYSDnJehEcDb_c6YTmcKZxSfZ1jwHMXMOAmE8XH30,5152
|
|
41
|
+
eth_portfolio/protocols/__init__.py,sha256=2qpUnGdTbC4tLUbylFvy1AE32XbsCFuFNbvqz91s0W8,2556
|
|
42
|
+
eth_portfolio/protocols/_base.py,sha256=XS4wJZur6Fwl_8E_vFMXx7JSaCQmPn7QbN863TYFSZE,3685
|
|
43
|
+
eth_portfolio/protocols/convex.py,sha256=uNbXxEmhcpXulNkbxoqWl9eAJTZjPJlzXFtrBGvRXLo,518
|
|
44
|
+
eth_portfolio/protocols/dsr.py,sha256=eGL0DK4IpZkv10CdNr-3OmlAYjqXJAtQHWL34HUBgpY,1755
|
|
45
|
+
eth_portfolio/protocols/liquity.py,sha256=sTUoVtFYj-OWUamwCnJyqna-eAa5Ww7-qGA0St1OTMQ,640
|
|
46
|
+
eth_portfolio/protocols/lending/README.md,sha256=OhZfsW8e-aD-q02g0maG9QGgW0IietkDRZc7PBakBvc,493
|
|
47
|
+
eth_portfolio/protocols/lending/__init__.py,sha256=BZtCOglz6R12wqETlECbCEITdtIT9J6bYzy61iDencI,1643
|
|
48
|
+
eth_portfolio/protocols/lending/_base.py,sha256=UBdJ5eV2baewEvppjES72eOJzKTK2XHGYnySQNBcack,2254
|
|
49
|
+
eth_portfolio/protocols/lending/compound.py,sha256=bqnIevm7NWhk6nMfkMZUKlQuVWr-tXnuntX-4De1YZM,7252
|
|
50
|
+
eth_portfolio/protocols/lending/liquity.py,sha256=N45LTa2VTcj3UDygn76iwaG_l0AYXOWh-9n5YBqkQNM,4184
|
|
51
|
+
eth_portfolio/protocols/lending/maker.py,sha256=jebMGZ2mWsvk-2mjFADgHtcOKr08LSqoag2a2dQVTvs,3969
|
|
52
|
+
eth_portfolio/protocols/lending/unit.py,sha256=7oRvIkoKUm8IOnDv59pILSSJWFNNjwr4CR1gg2psW9M,1965
|
|
53
|
+
eth_portfolio/structs/__init__.py,sha256=3EmfKoJGszobO7fCkERLXSN50V6dX3nfhvbiKIvJUZI,1443
|
|
54
|
+
eth_portfolio/structs/modified.py,sha256=z75XDNXOfm3hDr7pj0PbmUvfPeQSFH9BJ9m0L2V_LFw,1784
|
|
55
|
+
eth_portfolio/structs/structs.py,sha256=Baf0rxYadp6Y0yGC4pYwBmLNkJ_LkNrQRuRy1LCN5PM,19853
|
|
56
|
+
eth_portfolio/typing/__init__.py,sha256=QtNAK0UHbZZ2ysANFBkb492F339O77m8u-fdIeE6KeA,57316
|
|
57
|
+
eth_portfolio/typing/balance/single.py,sha256=_HhJL21jOs4IPjRsYbjZVficsNWCS0fcpBryr3JFt7s,6325
|
|
58
|
+
eth_portfolio_scripts/__init__.py,sha256=TC5c4WZdzSHhTIBYuwzrAyzFuGzBmHiDX_g6ghO09jQ,261
|
|
59
|
+
eth_portfolio_scripts/_args.py,sha256=k6J6XkRe1VuN1DiyGuXLCR7NBSvzH5jnVChfzodKuB8,656
|
|
60
|
+
eth_portfolio_scripts/_logging.py,sha256=B_rQMYt_1PhpwCOLBRpkKK6M1ljcF0wAIgqfPIsFUGU,354
|
|
61
|
+
eth_portfolio_scripts/_portfolio.py,sha256=umA-70yv2PGdHgoQVycknkSKk6QurB86FOXlIqBVY38,7139
|
|
62
|
+
eth_portfolio_scripts/_utils.py,sha256=-JiZLpSa8P2_ZFXw1AfpVmTO6X65yPeVVdnrDpNFzNQ,3057
|
|
63
|
+
eth_portfolio_scripts/balances.cpython-312-i386-linux-gnu.so,sha256=XJvKXKe1QzddNt0ZWhf5ZuqaCo5HiFLA2DfjNkcO3mw,16408
|
|
64
|
+
eth_portfolio_scripts/balances.py,sha256=QvpOdXnH1V-tOuEmAOPxH3MrincDExlIP1eEJ2IG2Lk,1588
|
|
65
|
+
eth_portfolio_scripts/main.py,sha256=crhObJ5P0B45zTBE2QOIOPYCxtJ8zhsciarcSZN1HHE,3685
|
|
66
|
+
eth_portfolio_scripts/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
67
|
+
eth_portfolio_scripts/docker/__init__.cpython-312-i386-linux-gnu.so,sha256=0jIMZ8Csf0pspOUrRLuu2d-Un8-NOdLbWNihL88kfLw,16400
|
|
68
|
+
eth_portfolio_scripts/docker/__init__.py,sha256=ZXSIYcjp94c0O9o39BDGWju3YrCMLl4gtov7YChc9Ig,393
|
|
69
|
+
eth_portfolio_scripts/docker/check.cpython-312-i386-linux-gnu.so,sha256=oWgopp_rsP_0WU9omN7tgYV-L8B6t639wNl-unPZvLU,16404
|
|
70
|
+
eth_portfolio_scripts/docker/check.py,sha256=80fRi6WvxSQM1NxIhtM6vg6fLOjGuqq5F2mGCf4VSvc,1930
|
|
71
|
+
eth_portfolio_scripts/docker/docker-compose.yaml,sha256=ZZo_aOYw-Wm2XDpqJpXjUKbtyqbOE5BWa1gR3h-8fUw,1809
|
|
72
|
+
eth_portfolio_scripts/docker/docker_compose.cpython-312-i386-linux-gnu.so,sha256=SB6tx6k-d9dGTvP5oRMgrxLSWlYT_1xRdAR_Bam1f7s,16452
|
|
73
|
+
eth_portfolio_scripts/docker/docker_compose.py,sha256=kVsx2FlRBAsYm8xyax3jvrk-IHKgiZvDqPdpQR8yHKI,2727
|
|
74
|
+
eth_portfolio_scripts/docker/.grafana/dashboards/dashboards.yaml,sha256=MynNDOk69IihoYdd2bL7j8CnRb2Co4gdqW7T4m6AaEU,202
|
|
75
|
+
eth_portfolio_scripts/docker/.grafana/dashboards/Portfolio/Balances.json,sha256=dBmjogLJRuixCHWSs4ROE0_FXb-PUbqWBHEdLoP-1MU,68788
|
|
76
|
+
eth_portfolio_scripts/docker/.grafana/datasources/datasources.yml,sha256=pBE_0Nh_J7d9Fiy3Xu6vuac_HWCBcFsJJSV-ryjQR1Y,188
|
|
77
|
+
eth_portfolio_scripts/victoria/__init__.py,sha256=hHVexpiVFJdBrdztihYBKC5hCdYDopo6aSaErI0mmOo,1965
|
|
78
|
+
eth_portfolio_scripts/victoria/types.py,sha256=FJossvAvwNGkufmEk3JD_I10EEaCsOb-m6aeX_vGsUg,707
|
|
79
|
+
eth_portfolio_temp-0.2.16.dist-info/METADATA,sha256=X95Jf9P3LsjGll4sD_H9ibkF4HtBzr7OzBD0_-zoF1Q,814
|
|
80
|
+
eth_portfolio_temp-0.2.16.dist-info/WHEEL,sha256=DPeIgeHMjLq-U13051wtkSCVz8aJ1BEEPPv1I-p47B8,180
|
|
81
|
+
eth_portfolio_temp-0.2.16.dist-info/entry_points.txt,sha256=yqoC6X3LU1NA_-oJ6mloEYEPNmS-0hPS9OtEwgIeDGU,66
|
|
82
|
+
eth_portfolio_temp-0.2.16.dist-info/top_level.txt,sha256=4MlbY-Yj8oGBGL8piXiO4SOpk2gZFF9ZXVTObTZOzqM,57
|
|
83
|
+
eth_portfolio_temp-0.2.16.dist-info/RECORD,,
|