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

Refactor update_price.py #3

Merged
merged 5 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 8 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
# Fill values

# Common settings
EXECUTION_ENDPOINT=https://execution
NETWORK=holesky
HOT_WALLET_PRIVATE_KEY=0x2......

# Settings for update_price.py
# TARGET_RPC_URL=https://example.com
# TARGET_CHAIN=23
# TARGET_ADDRESS=0xbd335c16c94be8c4dd073ae376ddf78bec1858df
# PRICE_FEED=0xba74737a078c05500dd98c970909e4a3b90c35c6
# PRICE_FEED_SENDER=0xf7d4e7273e5015c96728a6b02f31c505ee184603
# NETWORK is used as sender network
# Target network is determined automatically based on sender network
# Supported sender networks: Sepolia (id 11155111), Mainnet (id 1)
# Target networks: Arbitrum Sepolia (id 421614), Arbitrum (id 42161)
# SENDER_EXECUTION_ENDPOINT=https://example.com
# TARGET_EXECUTION_ENDPOINT=https://example.com

# Settings for update_ltv.py
# NETWORK=holesky
# EXECUTION_ENDPOINT=https://execution
# GRAPH_API_URL=https://graph
# VAULT=0x...
705 changes: 345 additions & 360 deletions poetry.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package-mode = false

[tool.poetry.dependencies]
python = "^3.10"
python-dotenv = "==1.0.1"
gql = {extras = ["requests"], version = "==3.5.0"}
sw-utils = {git = "https://github.com/stakewise/sw-utils.git", rev = "v0.6.25"}
python-decouple = "==3.8"
Expand Down Expand Up @@ -80,3 +79,6 @@ exclude = '''
| dist
)/
'''

[tool.vulture]
exclude = ["networks.py"]
Empty file added src/common/__init__.py
Empty file.
22 changes: 22 additions & 0 deletions src/common/clients.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import logging

from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3 import Web3
from web3.middleware import construct_sign_and_send_raw_middleware

from src.common.settings import HOT_WALLET_PRIVATE_KEY

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


def get_execution_client(endpoint: str, account: LocalAccount | None = None) -> Web3:
client = Web3(Web3.HTTPProvider(endpoint))
if account:
client.middleware_onion.add(construct_sign_and_send_raw_middleware(account))
return client


hot_wallet_account = Account().from_key(HOT_WALLET_PRIVATE_KEY)
logger.info('Wallet address: %s', hot_wallet_account.address)
26 changes: 26 additions & 0 deletions src/common/contracts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import json
import logging

from eth_typing import ChecksumAddress
from web3 import Web3
from web3.contract.contract import ContractEvents, ContractFunctions

logger = logging.getLogger(__name__)


class ContractWrapper:
def __init__(self, abi_path: str, address: ChecksumAddress, client: Web3):
self.address = address
self.contract = client.eth.contract(address=address, abi=self._load_abi(abi_path))

def _load_abi(self, abi_path: str) -> dict:
with open(abi_path, encoding='utf-8') as f:
return json.load(f)

@property
def functions(self) -> ContractFunctions:
return self.contract.functions

@property
def events(self) -> ContractEvents:
return self.contract.events
100 changes: 100 additions & 0 deletions src/common/networks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
from dataclasses import dataclass
from enum import Enum

from eth_typing import ChecksumAddress, HexAddress, HexStr
from web3 import Web3

EMPTY_ADDR_HEX = HexAddress(HexStr('0x' + '00' * 20))
ZERO_CHECKSUM_ADDRESS = Web3.to_checksum_address(EMPTY_ADDR_HEX) # noqa


class Network(Enum):
MAINNET = 'mainnet'
HOLESKY = 'holesky'
GNOSIS = 'gnosis'
CHIADO = 'chiado'
SEPOLIA = 'sepolia'


@dataclass
class PriceNetworkConfig:
# TARGET_CHAIN is not what eth_chainId returns.
# It is internal id used in PriceFeedSender contract.
TARGET_CHAIN: int
# PriceFeedReceiver contract address on target network
TARGET_ADDRESS: ChecksumAddress
# PriceFeed contract address on target network
TARGET_PRICE_FEED_CONTRACT_ADDRESS: ChecksumAddress
# PriceFeedSender contract address on sender network
PRICE_FEED_SENDER_CONTRACT_ADDRESS: ChecksumAddress


@dataclass
class NetworkConfig:
VAULT_USER_LTV_TRACKER_CONTRACT_ADDRESS: ChecksumAddress
PRICE_NETWORK_CONFIG: PriceNetworkConfig | None = None


NETWORKS: dict[Network, NetworkConfig] = {
Network.MAINNET: NetworkConfig(
VAULT_USER_LTV_TRACKER_CONTRACT_ADDRESS=Web3.to_checksum_address(
'0xe0Ae8B04922d6e3fA06c2496A94EF2875EFcC7BB'
),
PRICE_NETWORK_CONFIG=(
PriceNetworkConfig(
# TARGET_CHAIN is not what eth_chainId returns.
# It is internal id used in PriceFeedSender contract.
TARGET_CHAIN=23,
# PriceFeedReceiver contract address on Arbitrum
TARGET_ADDRESS=Web3.to_checksum_address(
'0xbd335c16c94be8c4dd073ae376ddf78bec1858df'
),
# PriceFeed contract address on Arbitrum
TARGET_PRICE_FEED_CONTRACT_ADDRESS=Web3.to_checksum_address(
'0xba74737a078c05500dd98c970909e4a3b90c35c6'
),
# PriceFeedSender contract address on Mainnet
PRICE_FEED_SENDER_CONTRACT_ADDRESS=Web3.to_checksum_address(
'0xf7d4e7273e5015c96728a6b02f31c505ee184603'
),
)
),
),
Network.HOLESKY: NetworkConfig(
VAULT_USER_LTV_TRACKER_CONTRACT_ADDRESS=Web3.to_checksum_address(
'0x8f48130b9b96B58035b4A9389eCDaBC00d59d0c8'
),
),
Network.GNOSIS: NetworkConfig(
VAULT_USER_LTV_TRACKER_CONTRACT_ADDRESS=Web3.to_checksum_address(
'0xdEa72c54f63470349CE2dC12f8232FE00241abE6'
),
),
Network.CHIADO: NetworkConfig(
VAULT_USER_LTV_TRACKER_CONTRACT_ADDRESS=Web3.to_checksum_address(
'0xe0Ae8B04922d6e3fA06c2496A94EF2875EFcC7BB'
),
),
Network.SEPOLIA: NetworkConfig(
VAULT_USER_LTV_TRACKER_CONTRACT_ADDRESS=ZERO_CHECKSUM_ADDRESS,
PRICE_NETWORK_CONFIG=(
PriceNetworkConfig(
# TARGET_CHAIN is not what eth_chainId returns.
# It is internal id used in PriceFeedSender contract.
TARGET_CHAIN=10003,
# PriceFeedReceiver contract address on Arbitrum Sepolia
TARGET_ADDRESS=Web3.to_checksum_address(
'0x744836a91f5151c6ef730eb7e07c232997debaaa'
),
# PriceFeed contract address on Arbitrum Sepolia
TARGET_PRICE_FEED_CONTRACT_ADDRESS=Web3.to_checksum_address(
'0x4026affabd9032bcc87fa05c02f088905f3dc09b'
),
# PriceFeedSender contract address on Sepolia
PRICE_FEED_SENDER_CONTRACT_ADDRESS=Web3.to_checksum_address(
'0xe572a8631a49ec4c334812bb692beecf934ac4e9'
),
)
),
),
}
9 changes: 9 additions & 0 deletions src/common/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from decouple import config

from src.common.networks import NETWORKS, Network

EXECUTION_ENDPOINT: str = config('EXECUTION_ENDPOINT', default='')
HOT_WALLET_PRIVATE_KEY: str = config('HOT_WALLET_PRIVATE_KEY')

NETWORK: Network = config('NETWORK', cast=Network)
network_config = NETWORKS[NETWORK]
18 changes: 5 additions & 13 deletions src/ltv/clients.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
import logging

import gql
from eth_account import Account
from gql.transport.requests import RequestsHTTPTransport
from web3 import Web3
from web3.middleware import construct_sign_and_send_raw_middleware

from .settings import (
EXECUTION_ENDPOINT,
GRAPH_API_TIMEOUT,
GRAPH_API_URL,
HOT_WALLET_PRIVATE_KEY,
)
from src.common.clients import get_execution_client, hot_wallet_account
from src.common.settings import EXECUTION_ENDPOINT

from .settings import GRAPH_API_TIMEOUT, GRAPH_API_URL

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

hot_wallet_account = Account().from_key(HOT_WALLET_PRIVATE_KEY)
execution_client = Web3(Web3.HTTPProvider(EXECUTION_ENDPOINT))
execution_client.middleware_onion.add(construct_sign_and_send_raw_middleware(hot_wallet_account))
logger.info('Wallet address: %s', hot_wallet_account.address)
execution_client = get_execution_client(EXECUTION_ENDPOINT, account=hot_wallet_account)


def get_graph_client() -> gql.Client:
Expand Down
32 changes: 8 additions & 24 deletions src/ltv/contracts.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,19 @@
import json
import logging
from pathlib import Path

from eth_typing import ChecksumAddress
from hexbytes import HexBytes
from web3 import Web3
from web3.contract.contract import ContractEvents, ContractFunctions

from .clients import execution_client, hot_wallet_account
from .settings import network_config
from src.common.clients import hot_wallet_account
from src.common.contracts import ContractWrapper
from src.common.settings import network_config

from .clients import execution_client
from .typings import HarvestParams

logger = logging.getLogger(__name__)


class ContractWrapper:
def __init__(self, abi_path: str, address: ChecksumAddress):
self.address = address
self.contract = execution_client.eth.contract(address=address, abi=self._load_abi(abi_path))

def _load_abi(self, abi_path: str) -> dict:
current_dir = Path(__file__).parent
with open(current_dir / abi_path, encoding='utf-8') as f:
return json.load(f)

@property
def functions(self) -> ContractFunctions:
return self.contract.functions

@property
def events(self) -> ContractEvents:
return self.contract.events
ABI_DIR = 'src/ltv/abi'


class VaultUserLTVTrackerContract(ContractWrapper):
Expand Down Expand Up @@ -65,6 +48,7 @@ def update_vault_max_ltv_user(


vault_user_ltv_tracker_contract = VaultUserLTVTrackerContract(
abi_path='abi/IVaultUserLtvTracker.json',
abi_path=f'{ABI_DIR}/IVaultUserLtvTracker.json',
address=network_config.VAULT_USER_LTV_TRACKER_CONTRACT_ADDRESS,
client=execution_client,
)
44 changes: 0 additions & 44 deletions src/ltv/networks.py

This file was deleted.

15 changes: 4 additions & 11 deletions src/ltv/settings.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
from decouple import config
from eth_typing import ChecksumAddress
from web3 import Web3

from .networks import NETWORKS, Network

NETWORK = config('NETWORK', cast=Network)
EXECUTION_ENDPOINT = config('EXECUTION_ENDPOINT')
HOT_WALLET_PRIVATE_KEY = config('HOT_WALLET_PRIVATE_KEY')

VAULT = config('VAULT', cast=Web3.to_checksum_address)
VAULT: ChecksumAddress = config('VAULT', cast=Web3.to_checksum_address)

# graph
GRAPH_API_URL = config('GRAPH_API_URL')
GRAPH_API_TIMEOUT = config('GRAPH_API_TIMEOUT', default='10', cast=int)

network_config = NETWORKS[NETWORK]
GRAPH_API_URL: str = config('GRAPH_API_URL')
GRAPH_API_TIMEOUT: int = config('GRAPH_API_TIMEOUT', default='10', cast=int)
Empty file added src/price/__init__.py
Empty file.
Loading
Loading