Skip to content

Commit

Permalink
Merge pull request #43 from mangata-finance/feature/calculate_with_id
Browse files Browse the repository at this point in the history
Feature/calculate with id
  • Loading branch information
gleb-urvanov authored Jun 2, 2021
2 parents 4e4bbfa + 1ef6fc8 commit 59cb0c9
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 6 deletions.
60 changes: 60 additions & 0 deletions pallets/xyk/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,24 @@ pub trait XykApi<BlockHash, Balance, TokenId, ResponseTypePrice, ResponseTypeAmo
at: Option<BlockHash>,
) -> Result<ResponseTypePrice>;

#[rpc(name = "xyk_calculate_sell_price_id")]
fn calculate_sell_price_id(
&self,
sold_token_id: TokenId,
bought_token_id: TokenId,
sell_amount: Balance,
at: Option<BlockHash>,
) -> Result<ResponseTypePrice>;

#[rpc(name = "xyk_calculate_buy_price_id")]
fn calculate_buy_price_id(
&self,
sold_token_id: TokenId,
bought_token_id: TokenId,
buy_amount: Balance,
at: Option<BlockHash>,
) -> Result<ResponseTypePrice>;

#[rpc(name = "xyk_get_burn_amount")]
fn get_burn_amount(
&self,
Expand Down Expand Up @@ -111,6 +129,48 @@ where
})
}

fn calculate_sell_price_id(
&self,
sold_token_id: TokenId,
bought_token_id: TokenId,
sell_amount: Balance,
at: Option<<Block as BlockT>::Hash>,
) -> Result<RpcResult<Balance>> {
let api = self.client.runtime_api();
let at = BlockId::<Block>::hash(at.unwrap_or_else(||
// If the block hash is not supplied assume the best block.
self.client.info().best_hash));

let runtime_api_result =
api.calculate_sell_price_id(&at, sold_token_id, bought_token_id, sell_amount);
runtime_api_result.map_err(|e| RpcError {
code: ErrorCode::ServerError(1),
message: "Unable to serve the request".into(),
data: Some(format!("{:?}", e).into()),
})
}

fn calculate_buy_price_id(
&self,
sold_token_id: TokenId,
bought_token_id: TokenId,
buy_amount: Balance,
at: Option<<Block as BlockT>::Hash>,
) -> Result<RpcResult<Balance>> {
let api = self.client.runtime_api();
let at = BlockId::<Block>::hash(at.unwrap_or_else(||
// If the block hash is not supplied assume the best block.
self.client.info().best_hash));

let runtime_api_result =
api.calculate_buy_price_id(&at, sold_token_id, bought_token_id, buy_amount);
runtime_api_result.map_err(|e| RpcError {
code: ErrorCode::ServerError(1),
message: "Unable to serve the request".into(),
data: Some(format!("{:?}", e).into()),
})
}

fn get_burn_amount(
&self,
first_asset_id: TokenId,
Expand Down
12 changes: 11 additions & 1 deletion pallets/xyk/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,20 @@ sp_api::decl_runtime_apis! {
sell_amount: Balance
) -> RpcResult<Balance>;
fn calculate_buy_price(
input_reserve: Balance,
input_reserve: Balance,
output_reserve: Balance,
buy_amount: Balance
) -> RpcResult<Balance>;
fn calculate_sell_price_id(
sold_token_id: TokenId,
bought_token_id: TokenId,
sell_amount: Balance
) -> RpcResult<Balance>;
fn calculate_buy_price_id(
sold_token_id: TokenId,
bought_token_id: TokenId,
buy_amount: Balance
) -> RpcResult<Balance>;
fn get_burn_amount(
first_asset_id: TokenId,
second_asset_id: TokenId,
Expand Down
35 changes: 31 additions & 4 deletions pallets/xyk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ decl_module! {
) -> DispatchResult {

let sender = ensure_signed(origin)?;

<Self as XykFunctionsTrait<T::AccountId>>::sell_asset(sender, sold_asset_id.into(), bought_asset_id.into(), sold_asset_amount.into(), min_amount_out.into())

}
Expand Down Expand Up @@ -437,6 +438,7 @@ impl<T: Trait> Module<T> {
let result = numerator
.checked_div(denominator)
.ok_or_else(|| DispatchError::from(Error::<T>::DivisionByZero))?;

Ok(result.saturated_into::<u128>().saturated_into::<Balance>())
}

Expand All @@ -463,16 +465,19 @@ impl<T: Trait> Module<T> {
input_reserve: Balance,
output_reserve: Balance,
buy_amount: Balance,
) -> Balance {
) -> Result<Balance, DispatchError> {
let input_reserve_saturated: U256 = input_reserve.saturated_into::<u128>().into();
let output_reserve_saturated: U256 = output_reserve.saturated_into::<u128>().into();
let buy_amount_saturated: U256 = buy_amount.saturated_into::<u128>().into();

let numerator: U256 = input_reserve_saturated * buy_amount_saturated * 1000;
let denominator: U256 = (output_reserve_saturated - buy_amount_saturated) * 997;
let result: U256 = numerator / denominator + 1;
let result = numerator
.checked_div(denominator)
.ok_or_else(|| DispatchError::from(Error::<T>::DivisionByZero))?
+ 1;

result.saturated_into::<u128>().saturated_into::<Balance>()
Ok(result.saturated_into::<u128>().saturated_into::<Balance>())
}

pub fn get_liquidity_asset(
Expand All @@ -488,6 +493,28 @@ impl<T: Trait> Module<T> {
}
}

pub fn calculate_sell_price_id(
sold_token_id: TokenId,
bought_token_id: TokenId,
sell_amount: Balance,
) -> Result<Balance, DispatchError> {
let input_reserve = Pools::get((sold_token_id, bought_token_id));
let output_reserve = Pools::get((bought_token_id, sold_token_id));

Self::calculate_sell_price(input_reserve, output_reserve, sell_amount)
}

pub fn calculate_buy_price_id(
sold_token_id: TokenId,
bought_token_id: TokenId,
buy_amount: Balance,
) -> Result<Balance, DispatchError> {
let input_reserve = Pools::get((sold_token_id, bought_token_id));
let output_reserve = Pools::get((bought_token_id, sold_token_id));

Self::calculate_buy_price(input_reserve, output_reserve, buy_amount)
}

// Calculate first and second token amounts depending on liquidity amount to burn
pub fn get_burn_amount(
first_asset_id: TokenId,
Expand Down Expand Up @@ -926,7 +953,7 @@ impl<T: Trait> XykFunctionsTrait<T::AccountId> for Module<T> {

// Calculate amount to be paid from bought amount
let sold_asset_amount =
Module::<T>::calculate_buy_price(input_reserve, output_reserve, bought_asset_amount);
Module::<T>::calculate_buy_price(input_reserve, output_reserve, bought_asset_amount)?;

// Ensure user has enought tokens to sell
ensure!(
Expand Down
22 changes: 21 additions & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,27 @@ impl_runtime_apis! {
buy_amount: Balance
) -> RpcResult<Balance> {
RpcResult {
price: Xyk::calculate_buy_price(input_reserve, output_reserve, buy_amount)
price: Xyk::calculate_buy_price(input_reserve, output_reserve, buy_amount).unwrap_or_default()
}
}

fn calculate_sell_price_id(
sold_token_id: TokenId,
bought_token_id: TokenId,
sell_amount: Balance
) -> RpcResult<Balance> {
RpcResult {
price: Xyk::calculate_sell_price_id(sold_token_id, bought_token_id, sell_amount).unwrap_or_default()
}
}

fn calculate_buy_price_id(
sold_token_id: TokenId,
bought_token_id: TokenId,
buy_amount: Balance
) -> RpcResult<Balance> {
RpcResult {
price: Xyk::calculate_buy_price_id(sold_token_id, bought_token_id, buy_amount).unwrap_or_default()
}
}

Expand Down

0 comments on commit 59cb0c9

Please sign in to comment.