Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Price api #5

Open
wants to merge 36 commits into
base: backend_v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7b47db2
feat: create price fetcher
Aerilym Jan 27, 2025
8e2e201
feat: create new config system for prices and base flask
Aerilym Jan 27, 2025
b269162
chore: create token conversion methods and tests
Aerilym Jan 28, 2025
2c739dd
chore: move non route methods to app class in price api
Aerilym Jan 28, 2025
a1d9431
fix: abi manager default add to cache
Aerilym Jan 28, 2025
663f42d
fix: change all inner module imports to relative imports
Aerilym Jan 28, 2025
b2acb63
fix: abi manager default and coingecko defaults
Aerilym Jan 29, 2025
118f383
fix: add root level package init
Aerilym Jan 29, 2025
ad3fdc6
chore: move python code into src folder so it can be used as a packag…
Aerilym Jan 29, 2025
02fb28e
chore: move configs
Aerilym Jan 29, 2025
8587905
fix: make db readers read only
Aerilym Jan 30, 2025
ae65c66
fix: use relative imports for src
Aerilym Jan 30, 2025
97361cb
fix: change packages to use relative imports to themselves
Aerilym Jan 30, 2025
022a210
fix: only require uwsgi for price fetcher if timer is active
Aerilym Jan 30, 2025
57bebdd
fix: leading slash on db file names
Aerilym Jan 30, 2025
6f2b566
fix: add disable db file rewrite option
Aerilym Jan 30, 2025
8a13b8d
fix: update most recent price fetcher
Aerilym Jan 30, 2025
b2d3018
fix: cache getters on no item
Aerilym Jan 30, 2025
20410e9
fix: cache ttl and invalidation defaults
Aerilym Jan 30, 2025
53ad6f0
fix: db read uri
Aerilym Jan 31, 2025
06d7d87
fix: change server timestamp to int
Aerilym Jan 31, 2025
a7b0e76
fix: raw transaction old version support
Aerilym Feb 3, 2025
0d9ffd0
feat: create cache tests
Aerilym Feb 3, 2025
19653f1
fix: staking api config
Aerilym Feb 4, 2025
fe6fd00
fix: abi manager cache
Aerilym Feb 4, 2025
71a225a
fix: fetcher runner
Aerilym Feb 4, 2025
109b98f
fix: show reserved slots for non-contributed contracts
Aerilym Feb 4, 2025
bee4a2b
fix: module resolution for registration and snapshot apps
Aerilym Feb 6, 2025
df6361f
fix: make default immutable block height 0
Aerilym Feb 6, 2025
b52cfb2
fix: make immutable block height 0 if None
Aerilym Feb 6, 2025
419a637
fix: mutate immutable block height 0 if None
Aerilym Feb 6, 2025
afcf941
fix: use get for immutable block height 0 if None
Aerilym Feb 6, 2025
d6d3f7b
fix: recreate network class on immutable 0
Aerilym Feb 6, 2025
6b767cf
fix: add defaults to oxen rpc network info
Aerilym Feb 6, 2025
167713a
fix: default config db schemas
Aerilym Feb 6, 2025
f3d0540
fix: add defaults for all net info fields
Aerilym Feb 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*.db
/config.py
/src/config.py
/__pycache__
/oxend/*.sock
*/__pycache__
6 changes: 0 additions & 6 deletions app_registration.py

This file was deleted.

6 changes: 0 additions & 6 deletions app_snapshot.py

This file was deleted.

6 changes: 0 additions & 6 deletions app_staking.py

This file was deleted.

2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
python_files = *_tests.py
2 changes: 2 additions & 0 deletions run_fetcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env python3
import src.app_fetcher
File renamed without changes.
6 changes: 6 additions & 0 deletions src/app_fetcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env python3
from src import config
from src.staking.fetcher import App

app = App(config.backend.fetcher_name if config.backend.fetcher_name else __name__)
app.run()
21 changes: 21 additions & 0 deletions src/app_price.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env python3

from src import config
from src.price.app import create_app, PriceAppConfig

price_config = PriceAppConfig(
name="price_api",
log_level=config.backend.log_level,
enable_perf=config.backend.performance_logging,
sqlite_db=config.backend.prices_sqlite_db,
sqlite_schema=config.backend.prices_sqlite_schema,
coingecko_api_key=config.backend.coingecko_api_key,
coingecko_api_url=config.backend.coingecko_api_url,
coingecko_api_token_ids=config.backend.coingecko_api_token_ids,
coingecko_api_currencies=config.backend.coingecko_api_currencies,
coingecko_api_rate_poll_rate_seconds=config.backend.prices_api_refetch_interval_seconds,
default_token=config.backend.prices_api_default_token,
default_currency=config.backend.prices_api_default_currency,
)

app = create_app(price_config)
16 changes: 16 additions & 0 deletions src/app_registration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env python3

from src import config
from src.registration.app import create_app, RegistrationAppConfig

registration_config = RegistrationAppConfig(
name="registration_api",
log_level=config.backend.log_level,
enable_perf=config.backend.performance_logging,
sqlite_db=config.backend.registration_sqlite_db,
sqlite_schema=config.backend.registration_sqlite_schema,
api_rate_limit=config.backend.registration_api_rate_limit,
api_rate_limit_period=config.backend.registration_api_rate_limit_period,
)

app = create_app(registration_config)
6 changes: 6 additions & 0 deletions src/app_snapshot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env python3

from src import config
from src.snapshot.app import create_app

app = create_app(config)
25 changes: 25 additions & 0 deletions src/app_staking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env python3
from src import config
from src.staking.app import create_app, StakingAppConfig

staking_app_config = StakingAppConfig(
name="staking_api",
log_level=config.backend.log_level,
enable_perf=config.backend.performance_logging,
sqlite_db=config.backend.sqlite_db,
sqlite_schema=config.backend.sqlite_schema,
sqlite_db_registrations=config.backend.registration_sqlite_db,
sqlite_schema_registrations=config.backend.registration_sqlite_schema,
rpc_api=config.backend.rpc_api,
rpc_api_cache=config.backend.rpc_api_cache,
rpc_shared=config.backend.rpc_shared,
rpc_shared_cache=config.backend.rpc_shared_cache,
rpc_api_usage_logging=config.backend.rpc_api_usage_logging,
log_level_generic=config.backend.log_level_generic,
cache_stale_time_seconds=config.backend.stale_time_seconds,
disable_db_file_rewrite=config.backend.disable_db_file_rewrite,
stale_time_seconds_contract_abis=config.backend.stale_time_seconds_contract_abis,
rpc_api_usage_logging_interval=config.backend.rpc_api_usage_logging_interval,
)

app = create_app(staking_app_config)
5 changes: 4 additions & 1 deletion config.py → src/config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from config_defaults import *
from .config_defaults import *

# Local settings. Changes to this file are meant for a local installation (and should not be
# committed to git).
Expand All @@ -12,3 +12,6 @@

# backend = stagenet_backend
# backend.provider_url = 'tcp://127.0.0.1:6786'

# backend.log_level = CUSTOM_LOG_LEVELS["SILLY"]
# backend.log_level = logging.INFO
29 changes: 25 additions & 4 deletions config_defaults.py → src/config_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ class Backend:
log_level_generic = None # Logs from other packages will use log_level if this is not set
oxen_wallet_regex: str = ""
sqlite_db: str = "ssb.db"
sqlite_schema: str = "db/schema.sql"
sqlite_schema: str = "src/staking/schema.sql"
rpc_shared: list[str] = ""
rpc_shared_cache: int = 2
disable_db_file_rewrite: bool = False


"""
API CONFIG
Expand All @@ -35,23 +37,24 @@ class Backend:
rpc_api: str = ""
rpc_api_cache: int = 2
rpc_api_usage_logging: bool = False
rpc_api_usage_logging_interval: int = 600
rpc_api_usage_logging_interval: int = 300

"""
REGISTRATION CONFIG
"""
registration_api_name: str = "registration_api"
# NOTE: This can be the same DB as the main API, but you must manually run the registrations/schema.sql script in
# the main db so it can be populated with the required tables.
registration_sqlite_db: str = "ssb-registrations.db"
registration_sqlite_schema: str = "registration/schema.sql"
registration_sqlite_schema: str = "src/registration/schema.sql"
# Creates a request per period limit by IP address (default is 100 requests per hour)
registration_api_rate_limit: int = 100
registration_api_rate_limit_period: int = 3600

"""
FETCHER CONFIG
"""
abi_dir = "web3client/abis"
abi_dir = "src/web3client/abis"
# Arbitrum runs at ~4 blocks per second, and the rpc node has a limit of 30m, so scan for 120 blocks
arbitrum_rescan_safety_blocks: int = 60
arbitrum_scan_start_chunk_size: int = 20
Expand Down Expand Up @@ -82,6 +85,24 @@ class Backend:
sqlite_snapshot_time_interval_seconds: int = 600
snapshot_on_startup: bool = False

"""
PRICE FETCHER CONFIG
"""
prices_api_name: str = "prices_api"
enable_price_fetcher: bool = False
coingecko_api_key: str = ""
coingecko_api_url: str = "https://api.coingecko.com/api"
coingecko_api_token_ids: list[str] = ["ethereum", "chainflip"]
coingecko_api_currencies: list[str] = ["usd", "aud"]

# Creates a request per period limit by IP address (default is 10 requests per 10 minutes)
prices_api_rate_limit: int = 10
prices_api_rate_limit_period: int = 600
prices_sqlite_db: str = "ssb-prices.db"
prices_sqlite_schema: str = "price/schema.sql"
prices_api_default_currency: str = "usd"
prices_api_default_token: str = "ethereum"
prices_api_refetch_interval_seconds:int = 300

# Session mainnet contracts
mainnet_backend = Backend()
Expand Down
12 changes: 6 additions & 6 deletions config_validate.py → src/config_validate.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import logging

import config
from log import Log
from oxen.omq import omq_connection
from oxen.rpc import OxenRPC
from util import is_not_empty_string, valid_address_assertion
from web3client.client import Web3Client
from . import config
from .log import Log
from .oxen.rpc import OxenRPC
from .util import is_not_empty_string, valid_address_assertion
from .web3client.abi_manager import ABIManager
from .web3client.client import Web3Client


def validate_config(conf: config):
Expand Down
File renamed without changes.
20 changes: 20 additions & 0 deletions src/db/read.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import sqlite3

from ..log import Log

class DBReader:
def __init__(self, db_path: str, log_level: int, perf: bool = False, disable_db_file_rewrite: bool = False):
self.log = Log("db_reader", log_level, enable_perf=perf).logger

if not disable_db_file_rewrite:
if not db_path.startswith("file:"):
db_path = "file:" + db_path

if not db_path.endswith("?mode=ro"):
db_path = db_path + "?mode=ro"

self.log.info(f"Connecting to db at {db_path}")
self.db_path = db_path

def connect(self):
return sqlite3.connect(self.db_path, uri=True)
File renamed without changes.
12 changes: 12 additions & 0 deletions src/db/write.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import sqlite3

from ..log import Log

class DBWriter:
def __init__(self, db_path: str, log_level: int, perf: bool = False):
self.db_path = db_path
self.log = Log("db_writer", log_level, enable_perf=perf).logger
self.log.info(f"Connecting to db at {db_path}")

def connect(self):
return sqlite3.connect(self.db_path)
4 changes: 2 additions & 2 deletions log/__init__.py → src/log/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging

from log.perf import PerformanceLogger
from log.util import add_logging_level
from .perf import PerformanceLogger
from .util import add_logging_level

CUSTOM_LOG_LEVELS = {"SILLY": 1, "PERFORMANCE": 69}
for label, lvl in CUSTOM_LOG_LEVELS.items():
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions log/time_keeper.py → src/log/time_keeper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import statistics
import time

from log import PerformanceLogger
from util import format_seconds, format_ms
from ..log import PerformanceLogger
from ..util import format_seconds, format_ms


class TimeKeeper:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
25 changes: 13 additions & 12 deletions oxen/rpc.py → src/oxen/rpc.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import logging
from typing import TypedDict
from oxen.omq import FutureJSON, omq_connection, RPCUsageTracker
from dataclasses import dataclass

from ..oxen.omq import FutureJSON, omq_connection, RPCUsageTracker


class ServiceNodeContributor(TypedDict):
address: str
Expand Down Expand Up @@ -164,15 +165,15 @@ def get_network_info_from_network(self):
self.log.silly("get_network_info_from_network info: {}".format(info))

return NetworkInfo(
block_hash=info.get("top_block_hash"),
block_height=info.get("height"),
hard_fork=info.get("hard_fork"),
immutable_block_hash=info.get("immutable_block_hash"),
immutable_block_height=info.get("immutable_height"),
max_stakers=info.get("max_contributors"),
min_operator_contribution=info.get("min_operator_contribution"),
nettype=info.get("nettype"),
pulse_target_timestamp=info.get("pulse_target_timestamp"),
staking_requirement=info.get("staking_requirement"),
version=info.get("version"),
block_hash=info.get("top_block_hash", "NA"),
block_height=info.get("height", 0),
hard_fork=info.get("hard_fork", "NA"),
immutable_block_hash=info.get("immutable_block_hash", "NA"),
immutable_block_height=info.get("immutable_height", 0),
max_stakers=info.get("max_contributors", 0),
min_operator_contribution=info.get("min_operator_contribution", 0),
nettype=info.get("nettype", "NA"),
pulse_target_timestamp=info.get("pulse_target_timestamp", 0),
staking_requirement=info.get("staking_requirement", 0),
version=info.get("version", "NA"),
)
File renamed without changes.
Loading