-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5772c8b
commit 12bcd51
Showing
9 changed files
with
167 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,4 +11,5 @@ pytest==7.4.0 | |
setuptools | ||
pandas-stubs | ||
types-psycopg2 | ||
types-requests | ||
types-requests | ||
moralis |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
from typing import Optional | ||
import dotenv, os | ||
from dune_client.types import QueryParameter | ||
from dune_client.client import DuneClient | ||
from dune_client.query import QueryBase | ||
from src.config import get_web3_instance, get_logger | ||
from src.constants import FETCH_PRICE_QUERY_ID, QUERY_BUFFER_TIME | ||
|
||
dotenv.load_dotenv() | ||
dune_api_key = os.getenv("DUNE_API_KEY") | ||
dune = DuneClient.from_env() | ||
|
||
|
||
class DunePriceProvider: | ||
""" | ||
Purpose of this class is to fetch historical token prices from Dune. | ||
""" | ||
|
||
def __init__(self) -> None: | ||
self.web3 = get_web3_instance() | ||
self.logger = get_logger() | ||
|
||
def get_price(self, block_number: int, token_address: str) -> Optional[float]: | ||
""" | ||
Function returns Dune price for a token address, | ||
closest to and at least as large as the block timestamp for a given tx hash. | ||
""" | ||
try: | ||
start_timestamp = self.web3.eth.get_block(block_number)["timestamp"] | ||
end_timestamp = start_timestamp + QUERY_BUFFER_TIME | ||
query = QueryBase( | ||
name="ERC20 Prices", | ||
query_id=FETCH_PRICE_QUERY_ID, | ||
params=[ | ||
QueryParameter.text_type(name="token_address", value=token_address), | ||
QueryParameter.number_type( | ||
name="start_timestamp", value=start_timestamp | ||
), | ||
QueryParameter.number_type( | ||
name="end_timestamp", value=end_timestamp | ||
), | ||
], | ||
) | ||
result = dune.run_query(query=query) | ||
if result.result.rows: | ||
row = result.result.rows[0] | ||
price = row.get("price") | ||
if price is not None: | ||
return price | ||
# No valid price found | ||
return None | ||
except KeyError as e: | ||
self.logger.error(f"Key error occurred: {e}") | ||
except Exception as e: | ||
self.logger.error(f"Unknown error occurred: {e}") | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
from typing import Optional | ||
from moralis import evm_api | ||
from src.config import get_logger | ||
import os, dotenv | ||
|
||
dotenv.load_dotenv() | ||
|
||
|
||
class MoralisPriceProvider: | ||
""" | ||
Purpose of this class is to fetch historical token prices using the Moralis API. | ||
""" | ||
|
||
def __init__(self) -> None: | ||
self.logger = get_logger() | ||
|
||
@staticmethod | ||
def wei_to_eth(price: str) -> Optional[float]: | ||
"""Function to convert string price to float price in ETH.""" | ||
float_price = float(price) if isinstance(price, str) else None | ||
if isinstance(float_price, float): | ||
return float_price / 10**18 | ||
return None | ||
|
||
def get_price(self, block_number: int, token_address: str) -> Optional[float]: | ||
""" | ||
Function returns Moralis price given a block number and token_address. | ||
Price returned is closest to and at least as large as block timestamp. | ||
""" | ||
try: | ||
params = { | ||
"chain": "eth", | ||
"address": token_address, | ||
"to_block": block_number, | ||
} | ||
result = evm_api.token.get_token_price( | ||
api_key=os.getenv("MORALIS_KEY"), | ||
params=params, | ||
) | ||
if "nativePrice" in result and "value" in result["nativePrice"]: | ||
# return price in ETH | ||
return self.wei_to_eth(result["nativePrice"]["value"]) | ||
else: | ||
raise KeyError(" 'nativePrice' or 'value' not found in the result.") | ||
except KeyError as e: | ||
self.logger.warning(f"Error: {e}") | ||
except Exception as e: | ||
self.logger.warning( | ||
f"Error: Likely the token: {token_address} was not found." | ||
) | ||
return None |