Skip to content

Commit

Permalink
add rsn_xag oracle option
Browse files Browse the repository at this point in the history
- add ergodex as datasource
  • Loading branch information
Alesfatalis committed Dec 16, 2024
1 parent 1c3cb36 commit ff6f384
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 15 deletions.
4 changes: 3 additions & 1 deletion core/src/datapoint_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ mod coingecko;
mod custom_ext_script;
mod erg_btc;
mod erg_usd;
mod erg_xag;
mod erg_xau;
mod ergodex;
mod predef;
mod erg_xag;
mod rsn_xag;

use crate::oracle_types::Rate;
use crate::pool_config::PredefinedDataPointSource;
Expand Down
6 changes: 3 additions & 3 deletions core/src/datapoint_source/bitpanda.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::assets_exchange_rate::AssetsExchangeRate;
use super::assets_exchange_rate::Btc;
use super::assets_exchange_rate::Usd;
use super::erg_xau::KgAu;
use super::erg_xag::KgAg;
use super::erg_xau::KgAu;
use super::DataPointSourceError;

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -139,13 +139,13 @@ mod tests {
let pair: AssetsExchangeRate<KgAu, Usd> = tokio_test::block_on(get_kgau_usd()).unwrap();
assert!(pair.rate > 0.0);
}

#[test]
fn test_kgag_usd_price() {
let pair: AssetsExchangeRate<KgAg, Usd> = tokio_test::block_on(get_kgag_usd()).unwrap();
assert!(pair.rate > 0.0);
}

#[test]
fn test_btc_usd_price() {
let pair: AssetsExchangeRate<Btc, Usd> = tokio_test::block_on(get_btc_usd()).unwrap();
Expand Down
66 changes: 59 additions & 7 deletions core/src/datapoint_source/coingecko.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::datapoint_source::assets_exchange_rate::AssetsExchangeRate;
use crate::datapoint_source::assets_exchange_rate::NanoErg;
use crate::datapoint_source::DataPointSourceError;

use super::ada_usd::Lovelace;
use super::assets_exchange_rate::Btc;
use super::assets_exchange_rate::Usd;
use super::erg_xau::KgAu;
use super::erg_xag::KgAg;
use super::erg_xau::KgAu;
use crate::datapoint_source::assets_exchange_rate::AssetsExchangeRate;
use crate::datapoint_source::assets_exchange_rate::NanoErg;
use crate::datapoint_source::rsn_xag::Rsn;
use crate::datapoint_source::DataPointSourceError;

#[cfg(not(test))]
pub async fn get_kgau_nanoerg() -> Result<AssetsExchangeRate<KgAu, NanoErg>, DataPointSourceError> {
Expand Down Expand Up @@ -180,6 +180,46 @@ pub async fn get_btc_nanoerg() -> Result<AssetsExchangeRate<Btc, NanoErg>, DataP
Ok(rate)
}

pub async fn get_kgag_rsn() -> Result<AssetsExchangeRate<KgAg, Rsn>, DataPointSourceError> {
let url = "https://api.coingecko.com/api/v3/simple/price?ids=rosen-bridge&vs_currencies=XAG";
let resp = reqwest::get(url).await?;
let price_json = json::parse(&resp.text().await?)?;
if let Some(p) = price_json["rosen-bridge"]["xag"].as_f64() {
// Convert from price RSN/XAG
let rsn_per_ag = KgAg::from_troy_ounce(1.0 / p);
let rate = AssetsExchangeRate {
per1: KgAg {},
get: Rsn {},
rate: rsn_per_ag,
};
Ok(rate)
} else {
Err(DataPointSourceError::JsonMissingField {
field: "rsn.xag as f64".to_string(),
json: price_json.dump(),
})
}
}

pub async fn get_rsn_usd() -> Result<AssetsExchangeRate<Usd, Rsn>, DataPointSourceError> {
let url = "https://api.coingecko.com/api/v3/simple/price?ids=rosen-bridge&vs_currencies=USD";
let resp = reqwest::get(url).await?;
let price_json = json::parse(&resp.text().await?)?;
if let Some(p) = price_json["rosen-bridge"]["usd"].as_f64() {
let rate = AssetsExchangeRate {
per1: Usd {},
get: Rsn {},
rate: 1.0 / p,
};
Ok(rate)
} else {
Err(DataPointSourceError::JsonMissingField {
field: "rsn.usd as f64".to_string(),
json: price_json.dump(),
})
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -190,10 +230,10 @@ mod tests {
tokio_test::block_on(get_kgau_nanoerg()).unwrap();
assert!(pair.rate > 0.0);
}

#[test]
fn test_erg_xag_price() {
let pair: AssetsExchangeRate<KgAg, NanoErg> =
let pair: AssetsExchangeRate<KgAg, NanoErg> =
tokio_test::block_on(get_kgag_nanoerg()).unwrap();
assert!(pair.rate > 0.0);
}
Expand All @@ -217,4 +257,16 @@ mod tests {
tokio_test::block_on(get_btc_nanoerg()).unwrap();
assert!(pair.rate > 0.0);
}

#[test]
fn test_rsn_xag_price() {
let pair: AssetsExchangeRate<KgAg, Rsn> = tokio_test::block_on(get_kgag_rsn()).unwrap();
assert!(pair.rate > 0.0);
}

#[test]
fn test_rsn_usd_price() {
let pair: AssetsExchangeRate<Usd, Rsn> = tokio_test::block_on(get_rsn_usd()).unwrap();
assert!(pair.rate > 0.0);
}
}
10 changes: 6 additions & 4 deletions core/src/datapoint_source/erg_xag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ use std::pin::Pin;

use futures::Future;

use crate::datapoint_source::assets_exchange_rate::{convert_rate, Asset, AssetsExchangeRate, NanoErg};
use crate::datapoint_source::{bitpanda, coingecko, DataPointSourceError};
use crate::datapoint_source::aggregator::fetch_aggregated;
use crate::datapoint_source::assets_exchange_rate::{
convert_rate, Asset, AssetsExchangeRate, NanoErg,
};
use crate::datapoint_source::erg_usd::nanoerg_usd_sources;
use crate::datapoint_source::{bitpanda, coingecko, DataPointSourceError};

#[derive(Debug, Clone, Copy)]
pub struct KgAg {}
Expand All @@ -25,15 +27,15 @@ impl KgAg {
// troy ounces per kg
oz * 32.150746568627
}

pub fn from_gram(g: f64) -> f64 {
g * 1000.0
}
}

#[allow(clippy::type_complexity)]
pub fn nanoerg_kgag_sources() -> Vec<
Pin<Box<dyn Future<Output = Result<AssetsExchangeRate<KgAg, NanoErg>, DataPointSourceError>>>>,
Pin<Box<dyn Future<Output = Result<AssetsExchangeRate<KgAg, NanoErg>, DataPointSourceError>>>>,
> {
vec![
Box::pin(coingecko::get_kgag_nanoerg()),
Expand Down
41 changes: 41 additions & 0 deletions core/src/datapoint_source/ergodex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::datapoint_source::assets_exchange_rate::{AssetsExchangeRate, NanoErg};
use crate::datapoint_source::rsn_xag::Rsn;
use crate::datapoint_source::DataPointSourceError;

pub async fn get_rsn_nanoerg() -> Result<AssetsExchangeRate<NanoErg, Rsn>, DataPointSourceError> {
let url = "https://api.spectrum.fi/v1/amm/pool/1b694b15467c62f0cd4525e368dbdea2329c713aa200b73df4a622e950551b40/stats";
let resp = reqwest::get(url).await?;
let pool_json = json::parse(&resp.text().await?)?;
let locked_erg = pool_json["lockedX"]["amount"].as_f64().ok_or_else(|| {
DataPointSourceError::JsonMissingField {
field: "lockedX.amount as f64".to_string(),
json: pool_json.dump(),
}
})?;

let locked_rsn = pool_json["lockedY"]["amount"].as_f64().ok_or_else(|| {
DataPointSourceError::JsonMissingField {
field: "lockedY.amount as f64".to_string(),
json: pool_json.dump(),
}
})?;
let price = Rsn::from_rsn(Rsn::from_rsn(locked_rsn) / NanoErg::from_erg(locked_erg));
let rate = AssetsExchangeRate {
per1: NanoErg {},
get: Rsn {},
rate: price,
};
Ok(rate)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_rsn_nanoerg_price() {
let pair: AssetsExchangeRate<NanoErg, Rsn> =
tokio_test::block_on(get_rsn_nanoerg()).unwrap();
assert!(pair.rate > 0.0);
}
}
2 changes: 2 additions & 0 deletions core/src/datapoint_source/predef.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::datapoint_source::rsn_xag::rsn_kgag_sources;
use crate::oracle_types::Rate;

use super::ada_usd::usd_lovelace_sources;
Expand Down Expand Up @@ -35,6 +36,7 @@ async fn fetch_predef_source_aggregated(
PredefinedDataPointSource::NanoErgBTC => {
fetch_aggregated(nanoerg_btc_sources()).await?.rate
}
PredefinedDataPointSource::RsnXag => fetch_aggregated(rsn_kgag_sources()).await?.rate,
};
Ok((rate_float as i64).into())
}
72 changes: 72 additions & 0 deletions core/src/datapoint_source/rsn_xag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use futures::Future;
use std::pin::Pin;

use crate::datapoint_source::assets_exchange_rate::{convert_rate, Asset, AssetsExchangeRate};
use crate::datapoint_source::erg_xag::KgAg;
use crate::datapoint_source::{bitpanda, coingecko, ergodex, DataPointSourceError};

#[derive(Debug, Clone, Copy)]
pub struct Rsn {}

impl Asset for Rsn {}

impl Rsn {
pub fn from_rsn(rsn: f64) -> f64 {
rsn * 1_000.0
}
}

#[allow(clippy::type_complexity)]
pub fn rsn_kgag_sources(
) -> Vec<Pin<Box<dyn Future<Output = Result<AssetsExchangeRate<KgAg, Rsn>, DataPointSourceError>>>>>
{
vec![
Box::pin(coingecko::get_kgag_rsn()),
Box::pin(get_rsn_kgag_erg()),
Box::pin(get_rsn_kgag_usd()),
]
}

// Calculate RSN/KGAG through RSN/USD and KGAG/USD
async fn get_rsn_kgag_usd() -> Result<AssetsExchangeRate<KgAg, Rsn>, DataPointSourceError> {
Ok(convert_rate(
coingecko::get_rsn_usd().await?,
bitpanda::get_kgag_usd().await?,
))
}

// Calculate KGAG/RSN through KGAG/ERG and ERG/RSN
async fn get_rsn_kgag_erg() -> Result<AssetsExchangeRate<KgAg, Rsn>, DataPointSourceError> {
Ok(convert_rate(
ergodex::get_rsn_nanoerg().await?,
coingecko::get_kgag_nanoerg().await?,
))
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_kgag_rsn_combined() {
let combined = tokio_test::block_on(get_rsn_kgag_usd()).unwrap();
let coingecko = tokio_test::block_on(coingecko::get_kgag_rsn()).unwrap();
let ergodex = tokio_test::block_on(get_rsn_kgag_erg()).unwrap();
let deviation_from_coingecko = (combined.rate - coingecko.rate).abs() / coingecko.rate;
assert!(
deviation_from_coingecko < 0.05,
"up to 5% deviation is allowed"
);
let ergodex_deviation_from_coingecko =
(ergodex.rate - coingecko.rate).abs() / coingecko.rate;
assert!(
ergodex_deviation_from_coingecko < 0.05,
"up to 5% deviation is allowed"
);
let deviation_from_ergodex = (ergodex.rate - combined.rate).abs() / combined.rate;
assert!(
deviation_from_ergodex < 0.05,
"up to 5% deviation is allowed"
);
}
}
1 change: 1 addition & 0 deletions core/src/pool_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pub enum PredefinedDataPointSource {
NanoErgXag,
NanoAdaUsd,
NanoErgBTC,
RsnXag,
}

/// Holds the token ids of every important token used by the oracle pool.
Expand Down

0 comments on commit ff6f384

Please sign in to comment.