Skip to content

Commit

Permalink
Merge pull request #790 from tellor-io/fix-uniswap
Browse files Browse the repository at this point in the history
Fixed Subgraph Sources that went Decentralized
  • Loading branch information
0xSpuddy authored Jul 30, 2024
2 parents d707469 + b2ab433 commit 498c20e
Show file tree
Hide file tree
Showing 14 changed files with 90 additions and 23 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,4 @@ package.json

# ignore stray test files
reported_pools.pickle
tenv
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ install_requires =
pyrsistent==0.19.2
python-dateutil==2.8.1
python-dotenv==0.21.0
pytz==2024.1
PyYAML==6.0
requests==2.28.1
rlp==2.0.1
Expand Down
2 changes: 2 additions & 0 deletions src/telliot_feeds/feeds/dai_usd_feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from telliot_feeds.sources.price.spot.coinbase import CoinbaseSpotPriceSource
from telliot_feeds.sources.price.spot.coingecko import CoinGeckoSpotPriceSource
from telliot_feeds.sources.price.spot.gemini import GeminiSpotPriceSource
from telliot_feeds.sources.price.spot.uniswapV3 import UniswapV3PriceSource
from telliot_feeds.sources.price_aggregator import PriceAggregator

dai_usd_median_feed = DataFeed(
Expand All @@ -17,6 +18,7 @@
CoinbaseSpotPriceSource(asset="dai", currency="usd"),
BinanceSpotPriceSource(asset="dai", currency="usdt"),
GeminiSpotPriceSource(asset="dai", currency="usd"),
UniswapV3PriceSource(asset="dai", currency="usd"),
],
),
)
2 changes: 2 additions & 0 deletions src/telliot_feeds/feeds/mnt_usd_feed.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from telliot_feeds.datafeed import DataFeed
from telliot_feeds.queries.price.spot_price import SpotPrice
from telliot_feeds.sources.price.spot.coingecko import CoinGeckoSpotPriceSource
from telliot_feeds.sources.price.spot.coinpaprika import CoinpaprikaSpotPriceSource
from telliot_feeds.sources.price.spot.uniswapV3 import UniswapV3PriceSource
from telliot_feeds.sources.price_aggregator import PriceAggregator

Expand All @@ -14,6 +15,7 @@
sources=[
CoinGeckoSpotPriceSource(asset="mnt", currency="usd"),
UniswapV3PriceSource(asset="mnt", currency="usd"),
CoinpaprikaSpotPriceSource(asset="mnt-mantle", currency="usd"),
],
),
)
4 changes: 2 additions & 2 deletions src/telliot_feeds/feeds/oeth_eth_feed.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from telliot_feeds.datafeed import DataFeed
from telliot_feeds.queries.price.spot_price import SpotPrice
from telliot_feeds.sources.price.spot.coingecko import CoinGeckoSpotPriceSource
from telliot_feeds.sources.price.spot.maverickV2 import MaverickV2PriceSource
from telliot_feeds.sources.price.spot.coinpaprika import CoinpaprikaSpotPriceSource
from telliot_feeds.sources.price.spot.uniswapV3Pool import UniswapV3PoolPriceSource
from telliot_feeds.sources.price_aggregator import PriceAggregator

Expand All @@ -15,7 +15,7 @@
sources=[
CoinGeckoSpotPriceSource(asset="oeth", currency="eth"),
UniswapV3PoolPriceSource(asset="oeth", currency="eth"),
MaverickV2PriceSource(asset="oeth", currency="eth"),
CoinpaprikaSpotPriceSource(asset="oeth-origin-ether", currency="eth"),
],
),
)
2 changes: 2 additions & 0 deletions src/telliot_feeds/feeds/oeth_usd_feed.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from telliot_feeds.datafeed import DataFeed
from telliot_feeds.queries.price.spot_price import SpotPrice
from telliot_feeds.sources.price.spot.coingecko import CoinGeckoSpotPriceSource
from telliot_feeds.sources.price.spot.coinpaprika import CoinpaprikaSpotPriceSource
from telliot_feeds.sources.price.spot.uniswapV3 import UniswapV3PriceSource
from telliot_feeds.sources.price_aggregator import PriceAggregator

Expand All @@ -14,6 +15,7 @@
sources=[
CoinGeckoSpotPriceSource(asset="oeth", currency="usd"),
UniswapV3PriceSource(asset="eth", currency="oeth"),
CoinpaprikaSpotPriceSource(asset="oeth-origin-ether", currency="usd"),
],
),
)
7 changes: 4 additions & 3 deletions src/telliot_feeds/feeds/ousd_usd_feed.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from telliot_feeds.datafeed import DataFeed
from telliot_feeds.queries.price.spot_price import SpotPrice
from telliot_feeds.sources.price.spot.coingecko import CoinGeckoSpotPriceSource
from telliot_feeds.sources.price.spot.uniswapV3 import UniswapV3PriceSource
from telliot_feeds.sources.price.spot.coinpaprika import CoinpaprikaSpotPriceSource
from telliot_feeds.sources.price.spot.curvefiprice import CurveFiUSDPriceSource
from telliot_feeds.sources.price_aggregator import PriceAggregator

# from telliot_feeds.sources.price.spot.curvefi import CurveFinanceSpotPriceSource
Expand All @@ -14,8 +15,8 @@
algorithm="median",
sources=[
CoinGeckoSpotPriceSource(asset="ousd", currency="usd"),
UniswapV3PriceSource(asset="ousd", currency="usd"),
# CurveFinanceSpotPriceSource(asset="ousd", currency="usd"),
CoinpaprikaSpotPriceSource(asset="ousd-origin-dollar", currency="usd"),
CurveFiUSDPriceSource(asset="ousd", currency="usd"),
],
),
)
1 change: 1 addition & 0 deletions src/telliot_feeds/sources/price/spot/curvefiprice.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"ezeth": "0xbf5495efe5db9ce00f80364c8b423567e58d2110",
"weeth": "0xcd5fe23c85820f7b72d0926fc9b05b43e359b7ee",
"rseth": "0xa1290d69c65a6fe4df752f95823fae25cb99e5a7",
"ousd": "0x2a8e1e676ec238d8a992307b495b45b3feaa5e86",
}


Expand Down
28 changes: 17 additions & 11 deletions src/telliot_feeds/sources/price/spot/uniswapV3.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from typing import Any

import requests
from requests import Session
from telliot_core.apps.telliot_config import TelliotConfig

from telliot_feeds.dtypes.datapoint import datetime_now_utc
from telliot_feeds.dtypes.datapoint import OptionalDataPoint
Expand All @@ -21,7 +23,6 @@
"steth": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84",
"reth": "0xae78736cd615f374d3085123a210448e74fc6393",
"pls": "0xa882606494d86804b5514e07e6bd2d6a6ee6d68a",
"ousd": "0x2a8e1e676ec238d8a992307b495b45b3feaa5e86",
"sweth": "0xf951e335afb289353dc249e82926178eac7ded78",
"cbeth": "0xbe9895146f7af43049ca1c1ae358b0541ea49704",
"oeth": "0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3",
Expand All @@ -34,13 +35,15 @@
"rseth": "0xa1290d69c65a6fe4df752f95823fae25cb99e5a7",
}

API_KEY = TelliotConfig().api_keys.find(name="thegraph")[0].key


class UniswapV3PriceService(WebPriceService):
"""UniswapV3 Price Service in USD and ETH"""

def __init__(self, **kwargs: Any) -> None:
kwargs["name"] = "UniswapV3 Price Service"
kwargs["url"] = "https://api.thegraph.com"
kwargs["url"] = "https://gateway-arbitrum.network.thegraph.com"
kwargs["timeout"] = 10.0
super().__init__(**kwargs)

Expand All @@ -58,15 +61,18 @@ async def get_price(self, asset: str, currency: str) -> OptionalDataPoint[float]
if not token:
raise Exception("Asset not supported: {}".format(asset))

headers = {
"Content-Type": "application/json",
}

query = "{bundles{id ethPriceUSD}token" + f'(id: "{token}")' + "{ derivedETH } }"

json_data = {"query": query}

request_url = self.url + "/subgraphs/name/uniswap/uniswap-v3"
request_url = f"{self.url}/api/subgraphs/id/5zvR82QoaXYFyDEKLZ9t6v9adgnptxYpKpSbxtgVENFV"

session = Session()
if API_KEY != "":
headers = {"Accepts": "application/json", "Authorization": f"Bearer {API_KEY}"}
session.headers.update(headers)
if API_KEY == "":
logger.warning("No Graph API key found for Uniswap prices!")

with requests.Session() as s:
try:
Expand All @@ -75,11 +81,11 @@ async def get_price(self, asset: str, currency: str) -> OptionalDataPoint[float]
data = {"response": res}

except requests.exceptions.ConnectTimeout:
logger.warning("Timeout Error, No prices retrieved from Uniswap")
logger.warning("Timeout Error, No Uniswap prices retrieved (check thegraph api key)")
return None, None

except Exception:
logger.warning("No prices retrieved from Uniswap")
except Exception as e:
logger.warning(f"No prices retrieved from Uniswap: {e}")
return None, None

if "error" in data:
Expand Down Expand Up @@ -125,7 +131,7 @@ class UniswapV3PriceSource(PriceSource):
import asyncio

async def main() -> None:
price_source = UniswapV3PriceSource(asset="cbeth", currency="eth")
price_source = UniswapV3PriceSource(asset="reth", currency="eth")
price, timestamp = await price_source.fetch_new_datapoint()
print(price, timestamp)

Expand Down
17 changes: 12 additions & 5 deletions src/telliot_feeds/sources/price/spot/uniswapV3Pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from typing import Any

import requests
from requests import Session
from telliot_core.apps.telliot_config import TelliotConfig

from telliot_feeds.dtypes.datapoint import datetime_now_utc
from telliot_feeds.dtypes.datapoint import OptionalDataPoint
Expand All @@ -23,13 +25,15 @@
"ogv": "0xa0b30e46f6aeb8f5a849241d703254bb4a719d92",
}

API_KEY = TelliotConfig().api_keys.find(name="thegraph")[0].key


class UniswapV3PoolPriceService(WebPriceService):
"""UniswapV3 Price Service for Pool Ratios"""

def __init__(self, **kwargs: Any) -> None:
kwargs["name"] = "UniswapV3 Price Service"
kwargs["url"] = "https://api.thegraph.com"
kwargs["url"] = "https://gateway-arbitrum.network.thegraph.com"
kwargs["timeout"] = 10.0
super().__init__(**kwargs)

Expand All @@ -46,9 +50,7 @@ async def get_price(self, asset: str, currency: str) -> OptionalDataPoint[float]
if not pool0 and not pool1:
raise Exception("Asset not supported: {}".format(asset))

headers = {
"Content-Type": "application/json",
}
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {API_KEY}"}
if pool0:
query = "{pool" + f'(id: "{pool0}")' + "{ token0Price } }"
key = "token0Price"
Expand All @@ -59,7 +61,12 @@ async def get_price(self, asset: str, currency: str) -> OptionalDataPoint[float]

json_data = {"query": query}

request_url = self.url + "/subgraphs/name/uniswap/uniswap-v3"
request_url = f"{self.url}/api/subgraphs/id/5zvR82QoaXYFyDEKLZ9t6v9adgnptxYpKpSbxtgVENFV"

session = Session()
if API_KEY != "":
headers = {"Accepts": "application/json", "Authorization": f"Bearer {API_KEY}"}
session.headers.update(headers)

with requests.Session() as s:
try:
Expand Down
22 changes: 22 additions & 0 deletions tests/feeds/test_dai_usd_feed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import statistics

import pytest

from telliot_feeds.feeds.dai_usd_feed import dai_usd_median_feed


@pytest.mark.asyncio
async def test_dai_usd_median_feed(caplog):
"""Retrieve median DAI/USD price."""
v, _ = await dai_usd_median_feed.source.fetch_new_datapoint()

assert v is not None
assert v > 0
assert "sources used in aggregate: 4" in caplog.text.lower()
print(f"DAI/USD Price: {v}")

# Get list of data sources from sources dict
source_prices = [source.latest[0] for source in dai_usd_median_feed.source.sources if source.latest[0]]

# Make sure error is less than decimal tolerance
assert (v - statistics.median(source_prices)) < 10**-6
2 changes: 1 addition & 1 deletion tests/feeds/test_mnt_usd_feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async def test_mnt_usd_median_feed(caplog):

assert v is not None
assert v > 0
assert "sources used in aggregate: 2" in caplog.text.lower()
assert "sources used in aggregate: 3" in caplog.text.lower()
print(f"mnt/usd Price: {v}")

# Get list of data sources from sources dict
Expand Down
2 changes: 1 addition & 1 deletion tests/feeds/test_oeth_usd_feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async def test_oeth_usd_median_feed(caplog):

assert v is not None
assert v > 0
assert "sources used in aggregate: 2" in caplog.text.lower()
assert "sources used in aggregate: 3" in caplog.text.lower()
print(f"OETH/USD Price: {v}")

# Get list of data sources from sources dict
Expand Down
22 changes: 22 additions & 0 deletions tests/feeds/test_ousd_usd_feed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import statistics

import pytest

from telliot_feeds.feeds.ousd_usd_feed import ousd_usd_median_feed


@pytest.mark.asyncio
async def test_ousd_usd_median_feed(caplog):
"""Retrieve median ousd/USD price."""
v, _ = await ousd_usd_median_feed.source.fetch_new_datapoint()

assert v is not None
assert v > 0
assert "sources used in aggregate: 3" in caplog.text.lower()
print(f"ousd/USD Price: {v}")

# Get list of data sources from sources dict
source_prices = [source.latest[0] for source in ousd_usd_median_feed.source.sources if source.latest[0]]

# Make sure error is less than decimal tolerance
assert (v - statistics.median(source_prices)) < 10**-6

0 comments on commit 498c20e

Please sign in to comment.