Skip to content

Commit

Permalink
temp
Browse files Browse the repository at this point in the history
  • Loading branch information
KirilMihaylov committed Aug 7, 2024
1 parent a305c09 commit 6385f3e
Show file tree
Hide file tree
Showing 3 changed files with 264 additions and 90 deletions.
23 changes: 17 additions & 6 deletions market-data-feeder/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,33 @@ pub(crate) trait Provider: Send + Sized {
}

#[must_use]
#[derive(Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct DecimalAmount {
amount: String,
decimal_places: u8,
}

impl DecimalAmount {
#[inline]
pub const fn new(amount: String, decimal_places: u8) -> Self {
Self {
amount,
decimal_places,
}
}

#[inline]
pub fn amount(&self) -> &str {
&self.amount
}

#[inline]
pub fn into_amount(self) -> String {
self.amount
}

pub const fn decimal_places(&self) -> u8 {
#[inline]
pub const fn decimal_digits(&self) -> u8 {
self.decimal_places
}
}
Expand All @@ -51,7 +59,7 @@ macro_rules! define_amount_newtype {
($($type:ident),+ $(,)?) => {
$(
#[must_use]
#[derive(Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct $type($crate::provider::DecimalAmount);

impl $type {
Expand All @@ -61,10 +69,13 @@ macro_rules! define_amount_newtype {
}

#[inline]
pub fn into_inner(self) -> DecimalAmount {
let Self(value) = self;
pub fn as_inner(&self) -> &DecimalAmount {
&self.0
}

value
#[inline]
pub fn into_inner(self) -> DecimalAmount {
self.0
}
}
)+
Expand Down
213 changes: 158 additions & 55 deletions market-data-feeder/src/providers/osmosis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use std::{collections::BTreeMap, future::Future};
use anyhow::{Context as _, Result};
use prost::Message;
use tonic::codegen::http::uri::PathAndQuery;
#[cfg(debug_assertions)]
use tracing::debug;

use chain_ops::node;

Expand All @@ -26,74 +28,82 @@ impl Osmosis {
}
}

fn normalized_price(spot_price: &str) -> Result<(BaseAmount, QuoteAmount)> {
let mut decimal_places = 36;

fn normalized_price(
spot_price: &str,
base_decimal_digits: u8,
quote_decimal_digits: u8,
) -> Result<(BaseAmount, QuoteAmount)> {
let mut trimmed_spot_price = spot_price.trim_end_matches('0');

decimal_places -=
u8::try_from(spot_price.len() - trimmed_spot_price.len())?;
let (base_decimal_digits, quote_decimal_digits) = {
let mut decimal_places = 36;

decimal_places -=
u8::try_from(spot_price.len() - trimmed_spot_price.len())?;

(
decimal_places.saturating_sub(
quote_decimal_digits.saturating_sub(base_decimal_digits),
),
decimal_places.saturating_sub(
base_decimal_digits.saturating_sub(quote_decimal_digits),
),
)
};

trimmed_spot_price = trimmed_spot_price.trim_start_matches('0');

10_u128
.checked_pow(decimal_places.into())
.checked_pow(base_decimal_digits.into())
.context(
"Failed to calculate price base amount due to an overflow \
during exponentiation!",
)
.map(|base_amount| {
BaseAmount::new(DecimalAmount::new(
base_amount.to_string(),
decimal_places,
))
})
.map(|base_amount| {
(
base_amount,
BaseAmount::new(DecimalAmount::new(
base_amount.to_string(),
base_decimal_digits,
)),
QuoteAmount::new(DecimalAmount::new(
trimmed_spot_price.into(),
decimal_places,
quote_decimal_digits,
)),
)
})
}
}

impl Provider for Osmosis {
type PriceQueryMessage = SpotPriceRequest;
type PriceQueryMessage = QueryMessage;

const PROVIDER_NAME: &'static str = "Osmosis";

fn price_query_messages(
&self,
oracle: &Oracle,
) -> Result<BTreeMap<CurrencyPair, Self::PriceQueryMessage>> {
let get_currency_dex_denom = {
let currencies = oracle.currencies();

move |currency| {
currencies
.get(currency)
.map(|currency| currency.dex_symbol.clone())
}
};
let currencies = oracle.currencies();

oracle
.currency_pairs()
.iter()
.map(|((base, quote), &pool_id)| {
get_currency_dex_denom(base).and_then(|base_asset_denom| {
get_currency_dex_denom(quote).map(|quote_asset_denom| {
.map(|((base_ticker, quote_ticker), &pool_id)| {
currencies.get(base_ticker).and_then(|base| {
currencies.get(quote_ticker).map(|quote| {
(
CurrencyPair {
base: base.clone().into(),
quote: quote.clone().into(),
base: base_ticker.clone().into(),
quote: quote_ticker.clone().into(),
},
SpotPriceRequest {
pool_id,
base_asset_denom,
quote_asset_denom,
QueryMessage {
request: SpotPriceRequest {
pool_id,
base_asset_denom: base.dex_symbol.clone(),
quote_asset_denom: quote.dex_symbol.clone(),
},
base_decimal_digits: base.decimal_digits,
quote_decimal_digits: quote.decimal_digits,
},
)
})
Expand All @@ -110,29 +120,55 @@ impl Provider for Osmosis {
{
let mut query_raw = dex_node_client.clone().query_raw();

let query_message = query_message.clone();
let &Self::PriceQueryMessage {
ref request,
base_decimal_digits,
quote_decimal_digits,
} = query_message;

#[cfg(debug_assertions)]
let (base, quote) = (
request.base_asset_denom.clone(),
request.quote_asset_denom.clone(),
);

let request = request.clone();

let path_and_query = self.path_and_query.clone();

async move {
let spot_price = query_raw
.raw::<_, SpotPriceResponse>(request, path_and_query)
.await
.context(
"Failed to query spot price from pool manager module!",
)?
.spot_price;

#[cfg(debug_assertions)]
debug!(base, quote, "Unprocessed price: {spot_price}");

Self::normalized_price(
&query_raw
.raw::<_, SpotPriceResponse>(query_message, path_and_query)
.await
.context(
"Failed to query spot price from pool manager module!",
)?
.spot_price,
&spot_price,
base_decimal_digits,
quote_decimal_digits,
)
.context(
"Failed to normalize price returned from pool manager module!",
"Failed to normalize price returned from pool manager \
module!",
)
}
}
}

pub(crate) struct QueryMessage {
request: SpotPriceRequest,
base_decimal_digits: u8,
quote_decimal_digits: u8,
}

#[derive(Clone, Message)]
pub(crate) struct SpotPriceRequest {
struct SpotPriceRequest {
#[prost(uint64, tag = "1")]
pool_id: u64,
#[prost(string, tag = "2")]
Expand All @@ -150,34 +186,101 @@ struct SpotPriceResponse {
#[test]
fn normalized_price() {
let (base, quote) =
Osmosis::normalized_price("1941974700000000000000000000000000")
Osmosis::normalized_price("1941974700000000000000000000000000", 6, 6)
.unwrap();

let base = base.into_inner();
assert_eq!(base.amount(), "10000000000");
assert_eq!(base.decimal_digits(), 10);

let query = quote.into_inner();
assert_eq!(query.amount(), "19419747");
assert_eq!(query.decimal_digits(), 10);

let (base, quote) =
Osmosis::normalized_price("001941974700000000000000000000000000", 6, 6)
.unwrap();

let base = base.into_inner();
assert_eq!(base.amount(), "10000000000");
assert_eq!(base.decimal_digits(), 10);

let quote = quote.into_inner();
assert_eq!(quote.amount(), "19419747");
assert_eq!(quote.decimal_digits(), 10);

let (base, quote) =
Osmosis::normalized_price("194197470000000000000000000000000000", 6, 6)
.unwrap();

let base = base.into_inner();
assert_eq!(base.amount(), "100000000");
assert_eq!(base.decimal_digits(), 8);

let quote = quote.into_inner();
assert_eq!(quote.amount(), "19419747");
assert_eq!(quote.decimal_digits(), 8);

let (base, quote) = Osmosis::normalized_price(
"24602951060000000000000000000000000000",
6,
6,
)
.unwrap();

let base = base.into_inner();
assert_eq!(base.amount(), "100000000");
assert_eq!(base.decimal_digits(), 8);

let quote = quote.into_inner();
assert_eq!(quote.amount(), "2460295106");
assert_eq!(quote.decimal_digits(), 8);

let (base, quote) =
Osmosis::normalized_price("74167359355013376000000000000000000", 6, 6)
.unwrap();

assert_eq!(base.into_inner().into_amount(), "10000000000");
let base = base.into_inner();
assert_eq!(base.amount(), "1000000000000000000");
assert_eq!(base.decimal_digits(), 18);

assert_eq!(quote.into_inner().into_amount(), "19419747");
let quote = quote.into_inner();
assert_eq!(quote.amount(), "74167359355013376");
assert_eq!(quote.decimal_digits(), 18);

let (base, quote) =
Osmosis::normalized_price("001941974700000000000000000000000000")
Osmosis::normalized_price("6724762410000000000000000000", 18, 6)
.unwrap();

assert_eq!(base.into_inner().into_amount(), "10000000000");
let base = base.into_inner();
assert_eq!(base.amount(), "100000000000000000");
assert_eq!(base.decimal_digits(), 17);

assert_eq!(quote.into_inner().into_amount(), "19419747");
let query = quote.into_inner();
assert_eq!(query.amount(), "672476241");
assert_eq!(query.decimal_digits(), 5);

let (base, quote) =
Osmosis::normalized_price("194197470000000000000000000000000000")
Osmosis::normalized_price("6724762415000000000000000000", 18, 6)
.unwrap();

assert_eq!(base.into_inner().into_amount(), "100000000");
let base = base.into_inner();
assert_eq!(base.amount(), "1000000000000000000");
assert_eq!(base.decimal_digits(), 18);

assert_eq!(quote.into_inner().into_amount(), "19419747");
let query = quote.into_inner();
assert_eq!(query.amount(), "6724762415");
assert_eq!(query.decimal_digits(), 6);

let (base, quote) =
Osmosis::normalized_price("24602951060000000000000000000000000000")
Osmosis::normalized_price("6724762415300000000000000000", 18, 6)
.unwrap();

assert_eq!(base.into_inner().into_amount(), "100000000");
let base = base.into_inner();
assert_eq!(base.amount(), "10000000000000000000");
assert_eq!(base.decimal_digits(), 19);

assert_eq!(quote.into_inner().into_amount(), "2460295106");
let query = quote.into_inner();
assert_eq!(query.amount(), "67247624153");
assert_eq!(query.decimal_digits(), 7);
}
Loading

0 comments on commit 6385f3e

Please sign in to comment.