From 02edc4e1d354a3d3047980d0f1180fac7d045fd3 Mon Sep 17 00:00:00 2001 From: Gregory Hill Date: Wed, 30 Aug 2023 12:07:21 +0100 Subject: [PATCH] refactor: filter by token name, dia is quoted in usd Signed-off-by: Gregory Hill --- oracle/examples/kintsugi-config.json | 29 ++++++++++++++++++---- oracle/src/currency.rs | 28 +++++++++------------- oracle/src/error.rs | 2 -- oracle/src/feeds.rs | 2 +- oracle/src/feeds/dia.rs | 11 ++++----- oracle/src/feeds/dia_fair_price.rs | 36 +++++++++++++++------------- 6 files changed, 60 insertions(+), 48 deletions(-) diff --git a/oracle/examples/kintsugi-config.json b/oracle/examples/kintsugi-config.json index bd9774904..bd4af5948 100644 --- a/oracle/examples/kintsugi-config.json +++ b/oracle/examples/kintsugi-config.json @@ -90,12 +90,12 @@ ], "dia": [ [ - "USD", - "BTC=Bitcoin/0x0000000000000000000000000000000000000000" + "BTC=Bitcoin/0x0000000000000000000000000000000000000000", + "USD" ], [ - "USD", - "KSM=Kusama/0x0000000000000000000000000000000000000000" + "KSM=Kusama/0x0000000000000000000000000000000000000000", + "USD" ] ] } @@ -113,6 +113,27 @@ ] ] } + }, + { + "pair": [ + "BTC", + "VKSM" + ], + "feeds": { + "dia_fair_price": [ + [ + { + "symbol": "BTC", + "alias": "KBTC" + }, + "USD" + ], + [ + "VKSM", + "USD" + ] + ] + } } ] } \ No newline at end of file diff --git a/oracle/src/currency.rs b/oracle/src/currency.rs index 83a17ac7e..3c239cbc3 100644 --- a/oracle/src/currency.rs +++ b/oracle/src/currency.rs @@ -1,6 +1,6 @@ #![allow(clippy::upper_case_acronyms)] -use crate::{CurrencyStore, Error}; +use crate::{feeds::DiaFairPriceExt, CurrencyStore, Error}; use runtime::{FixedPointNumber, FixedPointTraits::*, FixedU128}; use serde::Deserialize; use std::fmt::{self, Debug}; @@ -21,16 +21,10 @@ pub trait CurrencyInfo { } #[derive(Deserialize, Debug, Clone)] -pub struct Extension { - pub(crate) alias: Option, - pub(crate) index: Option, -} - -#[derive(Deserialize, Debug, Clone)] -pub struct Extended { +pub struct Extended { symbol: String, #[serde(flatten)] - pub(crate) ext: Option, + pub(crate) ext: Option, } #[derive(Deserialize, Debug, Clone)] @@ -40,7 +34,7 @@ pub enum Currency { Symbol(String), #[serde(deserialize_with = "deserialize_as_tuple")] Path(String, String), - Extended(Extended), + DiaFairPrice(Extended), } fn deserialize_as_string<'de, D>(deserializer: D) -> Result @@ -72,23 +66,23 @@ impl Currency { match self { Self::Symbol(symbol) => symbol.to_owned(), Self::Path(symbol, _) => symbol.to_owned(), - Self::Extended(extended) => extended.symbol.to_owned(), + Self::DiaFairPrice(extended) => extended.symbol.to_owned(), } } - pub fn ext(&self) -> Option { + pub fn path(&self) -> Option { match self { Self::Symbol(_) => None, - Self::Path(_, _) => None, - Self::Extended(extended) => extended.ext.to_owned(), + Self::Path(_, path) => Some(path.to_owned()), + Self::DiaFairPrice(_) => None, } } - pub fn path(&self) -> Option { + pub fn dia_fair_price_ext(&self) -> Option { match self { Self::Symbol(_) => None, - Self::Path(_, path) => Some(path.to_owned()), - Self::Extended(_) => None, + Self::Path(_, _) => None, + Self::DiaFairPrice(extended) => extended.ext.to_owned(), } } } diff --git a/oracle/src/error.rs b/oracle/src/error.rs index 8632f2064..03f8b4958 100644 --- a/oracle/src/error.rs +++ b/oracle/src/error.rs @@ -47,8 +47,6 @@ pub enum Error { NotConfigured(FeedName), #[error("Invalid dia symbol")] InvalidDiaSymbol, - #[error("Index required for fair price feed")] - NoFairPriceIndex, #[error("ReqwestError: {0}")] ReqwestError(#[from] ReqwestError), diff --git a/oracle/src/feeds.rs b/oracle/src/feeds.rs index 79cbb209d..b63203f3c 100644 --- a/oracle/src/feeds.rs +++ b/oracle/src/feeds.rs @@ -23,7 +23,7 @@ pub use blockcypher::{BlockCypherApi, BlockCypherCli}; pub use blockstream::{BlockstreamApi, BlockstreamCli}; pub use coingecko::{CoinGeckoApi, CoinGeckoCli}; pub use dia::{DiaApi, DiaCli}; -pub use dia_fair_price::{DiaFairPriceApi, DiaFairPriceCli}; +pub use dia_fair_price::{DiaFairPriceApi, DiaFairPriceCli, DiaFairPriceExt}; pub use gateio::{GateIoApi, GateIoCli}; pub use kraken::{KrakenApi, KrakenCli}; diff --git a/oracle/src/feeds/dia.rs b/oracle/src/feeds/dia.rs index 59c3b3ca3..edff50e09 100644 --- a/oracle/src/feeds/dia.rs +++ b/oracle/src/feeds/dia.rs @@ -26,10 +26,7 @@ impl Default for DiaApi { } fn extract_response(value: Value) -> Option { - value - .get("Price")? - .as_f64() - .and_then(|x| if x.is_normal() { Some(1.0 / x) } else { None }) + value.get("Price")?.as_f64() } fn set_token_path(base: &mut Url, token_path: &str) { @@ -52,10 +49,10 @@ impl DiaApi { currency_pair: CurrencyPair, _currency_store: &CurrencyStore, ) -> Result, Error> { - if currency_pair.base.symbol() != "USD" { + if currency_pair.quote.symbol() != "USD" { return Err(Error::InvalidDiaSymbol); } - let token_path = currency_pair.quote.path().ok_or(Error::InvalidDiaSymbol)?; + let token_path = currency_pair.base.path().ok_or(Error::InvalidDiaSymbol)?; // https://docs.diadata.org/documentation/api-1/api-endpoints#asset-quotation let mut url = self.url.clone(); @@ -115,7 +112,7 @@ mod tests { "Time": "2022-10-21T07:35:24Z", "Source": "diadata.org" })), - Some(1.0 / 5.842649511778436) + Some(5.842649511778436) ) } } diff --git a/oracle/src/feeds/dia_fair_price.rs b/oracle/src/feeds/dia_fair_price.rs index c2b50ae59..c2e70332b 100644 --- a/oracle/src/feeds/dia_fair_price.rs +++ b/oracle/src/feeds/dia_fair_price.rs @@ -4,8 +4,14 @@ use crate::{config::CurrencyStore, currency::*, Error}; use async_trait::async_trait; use clap::Parser; use reqwest::Url; +use serde::Deserialize; use serde_json::Value; +#[derive(Deserialize, Debug, Clone)] +pub struct DiaFairPriceExt { + alias: Option, +} + #[derive(Parser, Debug, Clone)] pub struct DiaFairPriceCli { /// Fetch the exchange rate from Dia xLSD feed @@ -25,18 +31,13 @@ impl Default for DiaFairPriceApi { } } -fn extract_response(value: Value, alias: &str, index: usize) -> Option { - let entry = value.get(index)?; - - if matches!(entry.get("Token")?.as_str(), Some(token) if token.to_uppercase() != alias) { - // expected index position does not match token - return None; - } - - entry +fn extract_response(value: Value, alias: &str) -> Option { + value + .as_array()? + .into_iter() + .find(|entry| matches!(entry.get("Token").and_then(|value| value.as_str()), Some(token) if token.to_uppercase() == alias))? .get("FairPrice")? .as_f64() - .and_then(|x| if x.is_normal() { Some(1.0 / x) } else { None }) } impl DiaFairPriceApi { @@ -53,20 +54,22 @@ impl DiaFairPriceApi { currency_pair: CurrencyPair, _currency_store: &CurrencyStore, ) -> Result, Error> { - if currency_pair.base.symbol() != "USD" { + if currency_pair.quote.symbol() != "USD" { return Err(Error::InvalidDiaSymbol); } - let extension = currency_pair.quote.ext().ok_or(Error::InvalidDiaSymbol)?; // this allows us to override the expected token name // which is helpful when using the xlsd feed of a wrapped token // but we want to submit the currency as the underlying (e.g. KBTC -> BTC) - let alias = extension.alias.unwrap_or(currency_pair.quote.symbol()); - let index = extension.index.ok_or(Error::NoFairPriceIndex)?; + let alias = currency_pair + .base + .dia_fair_price_ext() + .and_then(|ext| ext.alias) + .unwrap_or(currency_pair.base.symbol()); let url = self.url.clone(); let data = get_http(url).await?; - let price = extract_response(data, alias.as_str(), index).ok_or(Error::InvalidResponse)?; + let price = extract_response(data, alias.as_str()).ok_or(Error::InvalidResponse)?; Ok(CurrencyPairAndPrice { pair: currency_pair, @@ -112,9 +115,8 @@ mod tests { } ]), "KBTC", - 0 ), - Some(1.0 / 27418.406434486784) + Some(27418.406434486784) ) } }