Skip to content

Commit

Permalink
use enum and static class methods for config
Browse files Browse the repository at this point in the history
this addresses review comments
- uses an enum instead of a string for better checking of network values
- move initialization of configs into individual classes: use from_network and from_env to initialize classes
  • Loading branch information
fhenneke committed Nov 7, 2024
1 parent 2d5d631 commit 5b7a8cc
Showing 1 changed file with 163 additions and 99 deletions.
262 changes: 163 additions & 99 deletions src/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
"""Config for solver accounting."""

from __future__ import annotations

import os
from dataclasses import dataclass
from enum import Enum
from fractions import Fraction
from pathlib import Path

Expand All @@ -14,6 +17,13 @@
load_dotenv()


class Network(Enum):
MAINNET = "mainnet"
GNOSIS = "gnosis"
ARBITRUM_ONE = "arbitrum"
BASE = "base"


@dataclass(frozen=True)
class RewardConfig:
"""Configuration for reward mechanism."""
Expand All @@ -26,6 +36,26 @@ class RewardConfig:
quote_reward_cap_native: int
service_fee_factor: Fraction

@staticmethod
def from_network(network: Network) -> RewardConfig:
match network:
case Network.MAINNET:
return RewardConfig(
reward_token_address=Address(
"0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB"
),
batch_reward_cap_upper=12 * 10**15,
batch_reward_cap_lower=10 * 10**15,
quote_reward_cow=6 * 10**18,
quote_reward_cap_native=6 * 10**14,
service_fee_factor=Fraction(15, 100),
cow_bonding_pool=Address(
"0x5d4020b9261f01b6f8a45db929704b0ad6f5e9e6"
),
)
case _:
raise ValueError(f"No reward config set up for network {network}.")


@dataclass(frozen=True)
class ProtocolFeeConfig:
Expand All @@ -36,13 +66,40 @@ class ProtocolFeeConfig:
partner_fee_reduced_cut: float
reduced_cut_address: str

@staticmethod
def from_network(network: Network) -> ProtocolFeeConfig:
match network:
case Network.MAINNET:
return ProtocolFeeConfig(
protocol_fee_safe=Address(
"0xB64963f95215FDe6510657e719bd832BB8bb941B"
),
partner_fee_cut=0.15,
partner_fee_reduced_cut=0.10,
reduced_cut_address="0x63695Eee2c3141BDE314C5a6f89B98E62808d716",
)
case _:
raise ValueError(
f"No protocol fee config set up for network {network}."
)


@dataclass(frozen=True)
class BufferAccountingConfig:
"""Configuration for buffer accounting."""

include_slippage: bool

@staticmethod
def from_network(network: Network) -> BufferAccountingConfig:
match network:
case Network.MAINNET:
return BufferAccountingConfig(include_slippage=True)
case _:
raise ValueError(
f"No buffer accounting config set up for network {network}."
)


@dataclass(frozen=True)
class OrderbookConfig:
Expand All @@ -51,6 +108,13 @@ class OrderbookConfig:
prod_db_url: str
barn_db_url: str

@staticmethod
def from_env() -> OrderbookConfig:
prod_db_url = os.environ.get("PROD_DB_URL", "")
barn_db_url = os.environ.get("BARN_DB_URL", "")

return OrderbookConfig(prod_db_url=prod_db_url, barn_db_url=barn_db_url)


@dataclass(frozen=True)
class DuneConfig:
Expand All @@ -59,13 +123,30 @@ class DuneConfig:
dune_api_key: str
dune_blockchain: str

@staticmethod
def from_network(network: Network) -> DuneConfig:
dune_api_key = os.environ.get("DUNE_API_KEY", "")
match network:
case Network.MAINNET:
return DuneConfig(dune_api_key=dune_api_key, dune_blockchain="ethereum")
case _:
raise ValueError(f"No dune config set up for network {network}.")


@dataclass(frozen=True)
class NodeConfig:
"""Configuration for web3 node."""

node_url: str

@staticmethod
def from_network(network: Network) -> NodeConfig:
# Found this exposed infura key on https://rpc.info/
infura_key = os.environ.get("INFURA_KEY", "9aa3d95b3bc440fa88ea12eaa4456161")
node_url = f"https://{network}.infura.io/v3/{infura_key}"

return NodeConfig(node_url=node_url)


@dataclass(frozen=True)
class PaymentConfig:
Expand All @@ -82,6 +163,53 @@ class PaymentConfig:
verification_docs_url: str
weth_address: ChecksumAddress

@staticmethod
def from_network(network: Network) -> PaymentConfig:
signing_key = os.getenv("PROPOSER_PK")
if signing_key == "":
signing_key = None

docs_url = "https://www.notion.so/cownation/Solver-Payouts-3dfee64eb3d449ed8157a652cc817a8c"

network_short_name = {
Network.MAINNET: "eth",
Network.GNOSIS: "gno",
}

match network:
case Network.MAINNET:
payment_safe_address = Web3.to_checksum_address(
os.environ.get(
"SAFE_ADDRESS", "0xA03be496e67Ec29bC62F01a428683D7F9c204930"
)
)
short_name = network_short_name[network]
csv_app_hash = "Qme49gESuwpSvwANmEqo34yfCkzyQehooJ5yL7aHmKJnpZ"
safe_url = (
f"https://app.safe.global/{short_name}:{payment_safe_address}"
)
airdrop_url = f"{safe_url}/apps?appUrl=https://cloudflare-ipfs.com/ipfs/{csv_app_hash}/"
safe_queue_url = f"{safe_url}/transactions/queue"

return PaymentConfig(
network=EthereumNetwork.MAINNET,
cow_token_address=Address(
"0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB"
),
payment_safe_address=Web3.to_checksum_address(
"0xA03be496e67Ec29bC62F01a428683D7F9c204930"
),
signing_key=signing_key,
safe_queue_url=safe_queue_url,
csv_airdrop_url=airdrop_url,
verification_docs_url=docs_url,
weth_address=Web3.to_checksum_address(
"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
),
)
case _:
raise ValueError(f"No payment config set up for network {network}.")


@dataclass(frozen=True)
class IOConfig:
Expand All @@ -95,6 +223,27 @@ class IOConfig:
slack_channel: str | None
slack_token: str | None

@staticmethod
def from_env():
slack_channel = os.getenv("SLACK_CHANNEL", None)
slack_token = os.getenv("SLACK_TOKEN", None)

project_root_dir = Path(__file__).parent.parent
file_out_dir = project_root_dir / Path("out")
log_config_file = project_root_dir / Path("logging.conf")
query_dir = project_root_dir / Path("queries")
dashboard_dir = project_root_dir / Path("dashboards/solver-rewards-accounting")

return IOConfig(
project_root_dir=project_root_dir,
log_config_file=log_config_file,
query_dir=query_dir,
csv_output_dir=file_out_dir,
dashboard_dir=dashboard_dir,
slack_channel=slack_channel,
slack_token=slack_token,
)


@dataclass(frozen=True)
class AccountingConfig:
Expand All @@ -111,107 +260,22 @@ class AccountingConfig:
buffer_accounting_config: BufferAccountingConfig
io_config: IOConfig

@staticmethod
def from_network(network: Network) -> AccountingConfig:
"""Get config for specified network."""

def get_accounting_config(network: str) -> AccountingConfig:
"""Get config for specified network."""

# pylint: disable=too-many-locals

project_root_dir = Path(__file__).parent.parent
file_out_dir = project_root_dir / Path("out")
log_config_file = project_root_dir / Path("logging.conf")
query_dir = project_root_dir / Path("queries")
dashboard_dir = project_root_dir / Path("dashboards/solver-rewards-accounting")

docs_url = "https://www.notion.so/cownation/Solver-Payouts-3dfee64eb3d449ed8157a652cc817a8c"

# Secrets

# Found this exposed infura key on https://rpc.info/
infura_key = os.environ.get("INFURA_KEY", "9aa3d95b3bc440fa88ea12eaa4456161")

dune_api_key = os.environ.get("DUNE_API_KEY", "")

prod_db_url = os.environ.get("PROD_DB_URL", "")
barn_db_url = os.environ.get("BARN_DB_URL", "")

signing_key = os.getenv("PROPOSER_PK")
if signing_key == "":
signing_key = None

slack_channel = os.getenv("SLACK_CHANNEL", None)
slack_token = os.getenv("SLACK_TOKEN", None)

node_url = f"https://{network}.infura.io/v3/{infura_key}"

#
payment_safe_address = Web3.to_checksum_address(
os.environ.get("SAFE_ADDRESS", "0xA03be496e67Ec29bC62F01a428683D7F9c204930")
)
short_name = {
"mainnet": "eth",
"rinkeby": "rin",
"gnosis": "gno",
"goerli": "gor",
}[network]
csv_app_hash = "Qme49gESuwpSvwANmEqo34yfCkzyQehooJ5yL7aHmKJnpZ"
safe_url = f"https://app.safe.global/{short_name}:{payment_safe_address}"
airdrop_url = (
f"{safe_url}/apps?appUrl=https://cloudflare-ipfs.com/ipfs/{csv_app_hash}/"
)
safe_queue_url = f"{safe_url}/transactions/queue"

result = AccountingConfig(
payment_config=PaymentConfig(
network=EthereumNetwork.MAINNET,
cow_token_address=Address("0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB"),
payment_safe_address=Web3.to_checksum_address(
"0xA03be496e67Ec29bC62F01a428683D7F9c204930"
),
signing_key=signing_key,
safe_queue_url=safe_queue_url,
csv_airdrop_url=airdrop_url,
verification_docs_url=docs_url,
weth_address=Web3.to_checksum_address(
"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
),
),
orderbook_config=OrderbookConfig(
prod_db_url=prod_db_url,
barn_db_url=barn_db_url,
),
dune_config=DuneConfig(dune_api_key=dune_api_key, dune_blockchain="ethereum"),
node_config=NodeConfig(node_url=node_url),
reward_config=RewardConfig(
reward_token_address=Address("0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB"),
batch_reward_cap_upper=12 * 10**15,
batch_reward_cap_lower=10 * 10**15,
quote_reward_cow=6 * 10**18,
quote_reward_cap_native=6 * 10**14,
service_fee_factor=Fraction(15, 100),
cow_bonding_pool=Address("0x5d4020b9261f01b6f8a45db929704b0ad6f5e9e6"),
),
protocol_fee_config=ProtocolFeeConfig(
protocol_fee_safe=Address("0xB64963f95215FDe6510657e719bd832BB8bb941B"),
partner_fee_cut=0.15,
partner_fee_reduced_cut=0.10,
reduced_cut_address="0x63695Eee2c3141BDE314C5a6f89B98E62808d716",
),
buffer_accounting_config=BufferAccountingConfig(include_slippage=True),
io_config=IOConfig(
project_root_dir=project_root_dir,
log_config_file=log_config_file,
query_dir=query_dir,
csv_output_dir=file_out_dir,
dashboard_dir=dashboard_dir,
slack_channel=slack_channel,
slack_token=slack_token,
),
)

return result
return AccountingConfig(
payment_config=PaymentConfig.from_network(network),
orderbook_config=OrderbookConfig.from_env(),
dune_config=DuneConfig.from_network(network),
node_config=NodeConfig.from_network(network),
reward_config=RewardConfig.from_network(network),
protocol_fee_config=ProtocolFeeConfig.from_network(network),
buffer_accounting_config=BufferAccountingConfig.from_network(network),
io_config=IOConfig.from_env(),
)


config = get_accounting_config(os.environ.get("NETWORK", "mainnet"))
config = AccountingConfig.from_network(Network(os.environ.get("NETWORK", "mainnet")))

web3 = Web3(Web3.HTTPProvider(config.node_config.node_url))

0 comments on commit 5b7a8cc

Please sign in to comment.