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

New bob feeds #818

Merged
merged 6 commits into from
Oct 21, 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
6 changes: 6 additions & 0 deletions src/telliot_feeds/feeds/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@
from telliot_feeds.feeds.shib_usd_feed import shib_usd_median_feed
from telliot_feeds.feeds.snapshot_feed import snapshot_feed_example
from telliot_feeds.feeds.snapshot_feed import snapshot_manual_feed
from telliot_feeds.feeds.solvbtc_usd_feed import solvbtc_usd_median_feed
from telliot_feeds.feeds.solvbtcbbn_usd_feed import solvbtcbbn_usd_median_feed
from telliot_feeds.feeds.spot_price_manual_feed import spot_price_manual_feed
from telliot_feeds.feeds.steth_btc_feed import steth_btc_median_feed
from telliot_feeds.feeds.steth_usd_feed import steth_usd_median_feed
Expand All @@ -109,6 +111,7 @@
from telliot_feeds.feeds.twap_manual_feed import twap_30d_example_manual_feed
from telliot_feeds.feeds.twap_manual_feed import twap_manual_feed
from telliot_feeds.feeds.uni_usd_feed import uni_usd_median_feed
from telliot_feeds.feeds.unibtc_usd_feed import unibtc_usd_median_feed
from telliot_feeds.feeds.usdc_usd_feed import usdc_usd_median_feed
from telliot_feeds.feeds.usdm_usd_feed import usdm_usd_median_feed
from telliot_feeds.feeds.usdt_usd_feed import usdt_usd_median_feed
Expand Down Expand Up @@ -234,6 +237,9 @@
"stone-usd-spot": stone_usd_median_feed,
"superoethb-eth-spot": superoethb_eth_median_feed,
"lsk-usd-spot": lsk_usd_median_feed,
"unibtc-usd-spot": unibtc_usd_median_feed,
"solvbtc-usd-spot": solvbtc_usd_median_feed,
"solvbtcbbn-usd-spot": solvbtcbbn_usd_median_feed,
}

DATAFEED_BUILDER_MAPPING: Dict[str, DataFeed[Any]] = {
Expand Down
2 changes: 2 additions & 0 deletions src/telliot_feeds/feeds/op_usd_feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from telliot_feeds.sources.price.spot.coingecko import CoinGeckoSpotPriceSource
from telliot_feeds.sources.price.spot.coinpaprika import CoinpaprikaSpotPriceSource
from telliot_feeds.sources.price.spot.okx import OKXSpotPriceSource
from telliot_feeds.sources.price.spot.uniV3Optimism import UniV3OptimismPriceSource
from telliot_feeds.sources.price_aggregator import PriceAggregator

op_usd_median_feed = DataFeed(
Expand All @@ -15,6 +16,7 @@
CoinGeckoSpotPriceSource(asset="op", currency="usd"),
CoinpaprikaSpotPriceSource(asset="op-optimism", currency="usd"),
OKXSpotPriceSource(asset="op", currency="usdt"),
UniV3OptimismPriceSource(asset="op", currency="usdt"),
],
),
)
22 changes: 22 additions & 0 deletions src/telliot_feeds/feeds/solvbtc_usd_feed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from telliot_feeds.datafeed import DataFeed
from telliot_feeds.queries.price.spot_price import SpotPrice
from telliot_feeds.sources.lfj_source import LFJPriceSource
from telliot_feeds.sources.price.spot.coingecko import CoinGeckoSpotPriceSource
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

solvbtc_usd_median_feed = DataFeed(
query=SpotPrice(asset="SOLVBTC", currency="USD"),
source=PriceAggregator(
asset="solvbtc",
currency="usd",
algorithm="median",
sources=[
CoinGeckoSpotPriceSource(asset="solvbtc", currency="usd"),
CoinpaprikaSpotPriceSource(asset="solvbtc-solv-protocol-solvbtc", currency="usd"),
CurveFiUSDPriceSource(asset="solvbtc", currency="usd"),
LFJPriceSource(asset="solvbtc", currency="usd"),
],
),
)
20 changes: 20 additions & 0 deletions src/telliot_feeds/feeds/solvbtcbbn_usd_feed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from telliot_feeds.datafeed import DataFeed
from telliot_feeds.queries.price.spot_price import SpotPrice
from telliot_feeds.sources.lfj_source import LFJPriceSource
from telliot_feeds.sources.price.spot.coingecko import CoinGeckoSpotPriceSource
from telliot_feeds.sources.price_aggregator import PriceAggregator
from telliot_feeds.sources.solvbtcbbn_source import pancakePoolPriceSource

solvbtcbbn_usd_median_feed = DataFeed(
query=SpotPrice(asset="SOLVBTCBBN", currency="USD"),
source=PriceAggregator(
asset="solvbtcbbn",
currency="usd",
algorithm="median",
sources=[
CoinGeckoSpotPriceSource(asset="solvbtcbbn", currency="usd"),
pancakePoolPriceSource(asset="solvbtcbbn", currency="usd"),
LFJPriceSource(asset="solvbtcbbn", currency="usd"),
],
),
)
18 changes: 18 additions & 0 deletions src/telliot_feeds/feeds/unibtc_usd_feed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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_aggregator import PriceAggregator

unibtc_usd_median_feed = DataFeed(
query=SpotPrice(asset="UNIBTC", currency="USD"),
source=PriceAggregator(
asset="unibtc",
currency="usd",
algorithm="median",
sources=[
CoinGeckoSpotPriceSource(asset="unibtc", currency="usd"),
CoinpaprikaSpotPriceSource(asset="unibtc-universal-btc", currency="usd"),
],
),
)
3 changes: 3 additions & 0 deletions src/telliot_feeds/queries/price/spot_price.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@
"STONE/USD",
"SUPEROETHB/ETH",
"LSK/USD",
"UNIBTC/USD",
"SOLVBTC/USD",
"SOLVBTCBBN/USD",
]


Expand Down
18 changes: 18 additions & 0 deletions src/telliot_feeds/queries/query_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,3 +668,21 @@
title="LSK/USD spot price",
q=SpotPrice(asset="lsk", currency="usd"),
)

query_catalog.add_entry(
tag="unibtc-usd-spot",
title="UNIBTC/USD spot price",
q=SpotPrice(asset="unibtc", currency="usd"),
)

query_catalog.add_entry(
tag="solvbtc-usd-spot",
title="SOLVBTC/USD spot price",
q=SpotPrice(asset="solvbtc", currency="usd"),
)

query_catalog.add_entry(
tag="solvbtcbbn-usd-spot",
title="SOLVBTCBBN/USD spot price",
q=SpotPrice(asset="solvbtcbbn", currency="usd"),
)
150 changes: 150 additions & 0 deletions src/telliot_feeds/sources/lfj_source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
from dataclasses import dataclass
from dataclasses import field
from typing import Any
from typing import List
from typing import Optional

from telliot_core.apps.telliot_config import TelliotConfig

from telliot_feeds.dtypes.datapoint import datetime_now_utc
from telliot_feeds.dtypes.datapoint import OptionalDataPoint
from telliot_feeds.pricing.price_service import WebPriceService
from telliot_feeds.pricing.price_source import PriceSource
from telliot_feeds.utils.log import get_logger

logger = get_logger(__name__)

LFJ_QUOTER_CONTRACT = "0x9A550a522BBaDFB69019b0432800Ed17855A51C3"
CONTRACT_ABI = [
{
"inputs": [
{"internalType": "address[]", "name": "route", "type": "address[]"},
{"internalType": "uint128", "name": "amountIn", "type": "uint128"},
],
"name": "findBestPathFromAmountIn",
"outputs": [
{
"components": [
{"internalType": "address[]", "name": "route", "type": "address[]"},
{"internalType": "address[]", "name": "pairs", "type": "address[]"},
{"internalType": "uint256[]", "name": "binSteps", "type": "uint256[]"},
{"internalType": "uint8[]", "name": "versions", "type": "uint8[]"}, # Enum is uint8
{"internalType": "uint128[]", "name": "amounts", "type": "uint128[]"},
{"internalType": "uint128[]", "name": "virtualAmountsWithoutSlippage", "type": "uint128[]"},
{"internalType": "uint128[]", "name": "fees", "type": "uint128[]"},
],
"internalType": "tuple", # Struct is tuple in ABI
"name": "quote",
"type": "tuple",
}
],
"stateMutability": "view",
"type": "function",
}
]
SOLVBTC_ROUTE = [
"0xbc78D84Ba0c46dFe32cf2895a19939c86b81a777", # solvBTC
"0x152b9d0FdC40C096757F570A51E494bd4b943E50", # BTC.b
"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", # AVAX
"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", # USDC
]

SOLVBTCBBN_ROUTE = [
"0xCC0966D8418d412c599A6421b760a847eB169A8c", # solvBTC.bbn
"0xbc78D84Ba0c46dFe32cf2895a19939c86b81a777", # solvBTC
"0x152b9d0FdC40C096757F570A51E494bd4b943E50", # BTC.b
"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", # USDC
]


class LFJPriceService(WebPriceService):
"""Custom solvBTC Price Service"""

def __init__(self, **kwargs: Any) -> None:
kwargs["name"] = "Custom solvBTC Price Service"
kwargs["url"] = ""
super().__init__(**kwargs)
self.cfg = TelliotConfig()
self.contract_address: Optional[str] = None
self.contract_abi: Optional[Any] = None
self.src_len: Optional[int] = None
self.route: Optional[List[Any]] = None
self.asset: Optional[str] = None
self.currency: Optional[str] = None

def get_LFJ_quote(self, asset: str, currency: str) -> Optional[float]:
"""call the quote function from LFG exchange. Routes are defined based on the pools
that show up on the LFJ front end for 1(token) vs usdc"""
# get endpoint
endpoint = self.cfg.endpoints.find(chain_id=43114)
if not endpoint:
logger.error("check avalanche RPC endpoint. unable to get LFJ quotes")
return None
ep = endpoint[0]
if not ep.connect():
logger.error("Unable to connect to endpoint for LFJ source")
return None
w3 = ep._web3
if w3 is None:
logger.error("Unable to get web3 for avalanche to get LFJ quotes")
return None
if asset == "solvbtc":
self.route = SOLVBTC_ROUTE
elif asset == "solvbtcbbn":
self.route = SOLVBTCBBN_ROUTE
else:
logger.error("No route list for getting LFJ price (asset not supported)")
return None
if currency != "usd":
logger.error("LFJ source is for usd pairs only!")
return None
# get solvbtc/eth ratio
price_quote = None
try:
route = self.route
amount_in = 1000000000000000000
contract = w3.eth.contract(address=LFJ_QUOTER_CONTRACT, abi=CONTRACT_ABI)
contract_function = contract.functions.findBestPathFromAmountIn(route, amount_in)
data = contract_function.call()
response_int = data[5][3]
response_quote = w3.fromWei(response_int, "mwei")
price_quote = float(response_quote)

except Exception as e:
logger.error(f"Error querying LFJ: {e}")

return price_quote

async def get_price(self, asset: str, currency: str) -> OptionalDataPoint[float]:
"""This implementation gets the solvBTC/ETH ratio by checking the oracle
price from LFJ's price oracle contract
"""
asset = asset.lower()
currency = currency.lower()
lfj_quote = self.get_LFJ_quote(asset=asset, currency=currency)
logger.info(f"lfj quote for {asset}: {lfj_quote}")
if lfj_quote is None:
logger.error(f"lfj_quote is None for {asset} (check source)")
return None, None

return lfj_quote, datetime_now_utc()


@dataclass
class LFJPriceSource(PriceSource):
"""Gets data from LFJ contract"""

asset: str = ""
currency: str = ""
service: LFJPriceService = field(default_factory=LFJPriceService, init=False)


if __name__ == "__main__":
import asyncio

async def main() -> None:
source = LFJPriceSource(asset="solvbtcbbn", currency="usd")
v, _ = await source.fetch_new_datapoint()
print(v)

asyncio.run(main())
3 changes: 3 additions & 0 deletions src/telliot_feeds/sources/price/spot/coingecko.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@
"pufeth": "pufeth",
"stone": "stakestone-ether",
"superoethb": "super-oeth",
"unibtc": "universal-btc",
"solvbtc": "solv-btc",
"solvbtcbbn": "solv-protocol-solvbtc-bbn",
}

API_KEY = TelliotConfig().api_keys.find(name="coingecko")[0].key
Expand Down
3 changes: 2 additions & 1 deletion src/telliot_feeds/sources/price/spot/curvefiprice.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"rseth": "0xa1290d69c65a6fe4df752f95823fae25cb99e5a7",
"ousd": "0x2a8e1e676ec238d8a992307b495b45b3feaa5e86",
"pufeth": "0xd9a442856c234a39a81a089c06451ebaa4306a72",
"solvbtc": "0x7a56e1c57c7475ccf742a1832b028f0456652f97",
}


Expand Down Expand Up @@ -91,7 +92,7 @@ class CurveFiUSDPriceSource(PriceSource):
import asyncio

async def main() -> None:
source = CurveFiUSDPriceSource(asset="frxeth", currency="usd")
source = CurveFiUSDPriceSource(asset="solvbtcbbn", currency="usd")
v, _ = await source.fetch_new_datapoint()
print(v)

Expand Down
Loading
Loading