From d907c5ae71214fa5d9c71c6639e0aa0f61780ead Mon Sep 17 00:00:00 2001 From: Dzmitry Lahoda Date: Mon, 10 Jan 2022 12:26:08 +0200 Subject: [PATCH] oracle api clarification Signed-off-by: Dzmitry Lahoda --- frame/composable-traits/src/oracle.rs | 53 ++++++++++++++++++++------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/frame/composable-traits/src/oracle.rs b/frame/composable-traits/src/oracle.rs index e75197b8839..237bbb41f7b 100644 --- a/frame/composable-traits/src/oracle.rs +++ b/frame/composable-traits/src/oracle.rs @@ -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 { @@ -16,17 +16,30 @@ pub trait Oracle { type Balance: From; 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 @@ -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, 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 { Self::get_price(asset, asset.unit()).map(|_| true) @@ -53,4 +66,16 @@ pub trait Oracle { of: Self::AssetId, weighting: Vec, ) -> Result; + + /// 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) -> Result; }