Skip to content

Commit

Permalink
oracle api clarification
Browse files Browse the repository at this point in the history
Signed-off-by: Dzmitry Lahoda <dzmitry@lahoda.pro>
  • Loading branch information
dzmitry-lahoda committed Jan 10, 2022
1 parent a532ead commit d907c5a
Showing 1 changed file with 39 additions and 14 deletions.
53 changes: 39 additions & 14 deletions frame/composable-traits/src/oracle.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use frame_support::{dispatch::DispatchError, pallet_prelude::*};
use sp_std::vec::Vec;

use crate::currency::PriceableAsset;
use sp_runtime::FixedU128;
use crate::{currency::PriceableAsset, defi::CurrencyPair};

#[derive(Encode, Decode, Default, Debug, PartialEq)]
pub struct Price<PriceValue, BlockNumber> {
Expand All @@ -16,17 +16,30 @@ pub trait Oracle {
type Balance: From<u64>;
type Timestamp;

/// Quote the `amount` of `asset` in USDT cent.
/// Error is returned if `asset` not supported or price information not available.

/// Assuming we have a price `p` for an unit (not smallest) of `asset` in USDT cents.
/// Let `k` be the number of decimals for `asset`.
/// The price of an amount `a` of the smallest possible unit of `asset` is:
/// p * a / 10^k
/// e.g. for BTC, the price is expressed for 1 BTC, but the amount is in sats:
/// Quote the `amount` of `asset_id` in normalized currency unit cent. Default is USDT Cent. Which is 0.01 of USDT.
/// `Result::Err` is returned if `asset_id` not supported or price information not available.
///
/// Assuming we have a price `price` for an unit (not smallest) of `asset_id` in USDT cents.
/// Let `decimals` be the number of decimals for `asset_id` as given by `PriceableAsset::decimals`
/// The price of an amount `amount` of the smallest possible unit of `asset_id` is:
/// `price * amount / 10^decimals`
///
/// # Example
/// E.g. for BTC, the price is expressed for 1 BTC, but the amount is in sats:
/// 1 BTC = 10^8 sats
/// get_price(BTC, 1_00000000) = price(1BTC) * 1_00000000 / 10^8 = $50000

/// So that:
/// `get_price(BTC, 1_00000000) = price(1BTC) * 1_00000000 / 10^8 = $50_000 = 5_000_000 USDT cents`
///
/// # Normal assets
/// ```rust
/// let btc_amount = 1;
/// let satoshi_in_btc = 100_000_000;
///
/// let price_in_normalized =
/// ```
///
/// # Diluted assets
///
/// Implementation ensure that a LP token price can be resolved as long as the base asset price
/// is resolvable.
///```haskell
Expand All @@ -39,11 +52,11 @@ pub trait Oracle {
/// price (Vaulted base stock_dilution_rate) = price base * stock_dilution_rate
/// ```
fn get_price(
asset: Self::AssetId,
asset_id: Self::AssetId,
amount: Self::Balance,
) -> Result<Price<Self::Balance, Self::Timestamp>, DispatchError>;

/// Check whether the provided `asset` is supported (a.k.a. a price can be computed) by the
/// Check whether the provided `asset_id` is supported (a.k.a. a price can be computed) by the
/// oracle.
fn is_supported(asset: Self::AssetId) -> Result<bool, DispatchError> {
Self::get_price(asset, asset.unit()).map(|_| true)
Expand All @@ -53,4 +66,16 @@ pub trait Oracle {
of: Self::AssetId,
weighting: Vec<Self::Balance>,
) -> Result<Self::Balance, DispatchError>;

/// Up to oracle how it decides ratio.
/// If there is no direct trading pair, can estimate via common pair (to which all currencies are normalized).
/// General formula
/// ```rust
/// let base_in_common = 1000.0;
/// let quote_in_common = 100.0;
/// let ratio = base_in_common / quote_in_common; // 10.0
/// let base_amount = 3.0;
/// let needed_base_for_quote = base_amount * ratio; // 300.0
/// ```
fn get_ratio(pair: CurrencyPair<Self::AssetId>) -> Result<FixedU128, DispatchError>;
}

0 comments on commit d907c5a

Please sign in to comment.