Skip to content

Commit

Permalink
improved sources
Browse files Browse the repository at this point in the history
  • Loading branch information
0xSpuddy committed Oct 21, 2024
1 parent c7c8f23 commit f03d0df
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/telliot_feeds/feeds/solvbtc_usd_feed.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
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
Expand All @@ -15,6 +16,7 @@
CoinGeckoSpotPriceSource(asset="solvbtc", currency="usd"),
CoinpaprikaSpotPriceSource(asset="solvbtc-solv-protocol-solvbtc", currency="usd"),
CurveFiUSDPriceSource(asset="solvbtc", currency="usd"),
LFJPriceSource(asset="solvbtc", currency="usd"),
],
),
)
4 changes: 3 additions & 1 deletion src/telliot_feeds/feeds/solvbtcbbn_usd_feed.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
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.solvbtcbbn_source import pancakePoolPriceSource
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"),
Expand All @@ -13,6 +14,7 @@
sources=[
CoinGeckoSpotPriceSource(asset="solvbtcbbn", currency="usd"),
pancakePoolPriceSource(asset="solvbtcbbn", currency="usd"),
LFJPriceSource(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())
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 @@ -25,6 +25,7 @@
"rseth": "0xa1290d69c65a6fe4df752f95823fae25cb99e5a7",
"ousd": "0x2a8e1e676ec238d8a992307b495b45b3feaa5e86",
"pufeth": "0xd9a442856c234a39a81a089c06451ebaa4306a72",
"solvbtc": "0x7a56e1c57c7475ccf742a1832b028f0456652f97",
}


Expand Down
2 changes: 1 addition & 1 deletion tests/feeds/test_solvbtc_usd_feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async def test_solvbtc_usd_median_feed(caplog):

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

# Get list of data sources from sources dict
Expand Down
2 changes: 1 addition & 1 deletion tests/feeds/test_solvbtcbbn_usd_feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async def test_solvbtcbbn_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"solvbtcbbn/usd Price: {v}")

# Get list of data sources from sources dict
Expand Down

0 comments on commit f03d0df

Please sign in to comment.