Skip to content

Commit

Permalink
refactor: filter by token name, dia is quoted in usd
Browse files Browse the repository at this point in the history
Signed-off-by: Gregory Hill <[email protected]>
  • Loading branch information
gregdhill committed Aug 30, 2023
1 parent 8f21f88 commit 02edc4e
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 48 deletions.
29 changes: 25 additions & 4 deletions oracle/examples/kintsugi-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@
],
"dia": [
[
"USD",
"BTC=Bitcoin/0x0000000000000000000000000000000000000000"
"BTC=Bitcoin/0x0000000000000000000000000000000000000000",
"USD"
],
[
"USD",
"KSM=Kusama/0x0000000000000000000000000000000000000000"
"KSM=Kusama/0x0000000000000000000000000000000000000000",
"USD"
]
]
}
Expand All @@ -113,6 +113,27 @@
]
]
}
},
{
"pair": [
"BTC",
"VKSM"
],
"feeds": {
"dia_fair_price": [
[
{
"symbol": "BTC",
"alias": "KBTC"
},
"USD"
],
[
"VKSM",
"USD"
]
]
}
}
]
}
28 changes: 11 additions & 17 deletions oracle/src/currency.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -21,16 +21,10 @@ pub trait CurrencyInfo<Currency> {
}

#[derive(Deserialize, Debug, Clone)]
pub struct Extension {
pub(crate) alias: Option<String>,
pub(crate) index: Option<usize>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Extended {
pub struct Extended<Ext> {
symbol: String,
#[serde(flatten)]
pub(crate) ext: Option<Extension>,
pub(crate) ext: Option<Ext>,
}

#[derive(Deserialize, Debug, Clone)]
Expand All @@ -40,7 +34,7 @@ pub enum Currency {
Symbol(String),
#[serde(deserialize_with = "deserialize_as_tuple")]
Path(String, String),
Extended(Extended),
DiaFairPrice(Extended<DiaFairPriceExt>),
}

fn deserialize_as_string<'de, D>(deserializer: D) -> Result<String, D::Error>
Expand Down Expand Up @@ -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<Extension> {
pub fn path(&self) -> Option<String> {
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<String> {
pub fn dia_fair_price_ext(&self) -> Option<DiaFairPriceExt> {
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(),
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions oracle/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion oracle/src/feeds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down
11 changes: 4 additions & 7 deletions oracle/src/feeds/dia.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ impl Default for DiaApi {
}

fn extract_response(value: Value) -> Option<f64> {
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) {
Expand All @@ -52,10 +49,10 @@ impl DiaApi {
currency_pair: CurrencyPair<Currency>,
_currency_store: &CurrencyStore<String>,
) -> Result<CurrencyPairAndPrice<Currency>, 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();
Expand Down Expand Up @@ -115,7 +112,7 @@ mod tests {
"Time": "2022-10-21T07:35:24Z",
"Source": "diadata.org"
})),
Some(1.0 / 5.842649511778436)
Some(5.842649511778436)
)
}
}
36 changes: 19 additions & 17 deletions oracle/src/feeds/dia_fair_price.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,
}

#[derive(Parser, Debug, Clone)]
pub struct DiaFairPriceCli {
/// Fetch the exchange rate from Dia xLSD feed
Expand All @@ -25,18 +31,13 @@ impl Default for DiaFairPriceApi {
}
}

fn extract_response(value: Value, alias: &str, index: usize) -> Option<f64> {
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<f64> {
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 {
Expand All @@ -53,20 +54,22 @@ impl DiaFairPriceApi {
currency_pair: CurrencyPair<Currency>,
_currency_store: &CurrencyStore<String>,
) -> Result<CurrencyPairAndPrice<Currency>, 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,
Expand Down Expand Up @@ -112,9 +115,8 @@ mod tests {
}
]),
"KBTC",
0
),
Some(1.0 / 27418.406434486784)
Some(27418.406434486784)
)
}
}

0 comments on commit 02edc4e

Please sign in to comment.