Skip to content
This repository has been archived by the owner on Nov 15, 2024. It is now read-only.

Commit

Permalink
Feat/leverage claim rewards (#367)
Browse files Browse the repository at this point in the history
* add: leveragelp query and leveragelp get rewards

* feat: add claim rewards

* refactor: leveragelp querier funcs

* add: usdc and eden rewards

* update: test

* fix

---------

Co-authored-by: Warao <[email protected]>
  • Loading branch information
cryptokage1996 and Wgil authored Jun 18, 2024
1 parent 58cc03d commit 8659727
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 10 deletions.
2 changes: 2 additions & 0 deletions bindings-test/src/multitest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,7 @@ impl Module for ElysModule {
})?)
}
ElysQuery::CommitmentNumberOfCommitments {} => todo!("CommitmentNumberOfCommitments"),
ElysQuery::LeveragelpRewards { .. } => todo!(),
}
}

Expand Down Expand Up @@ -1045,6 +1046,7 @@ impl Module for ElysModule {
data: Some(data),
})
}
ElysMsg::LeveragelpClaimRewards { .. } => todo!(),
}
}

Expand Down
9 changes: 9 additions & 0 deletions bindings/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ pub enum ElysMsg {
amount: Int128,
owner: String,
},

LeveragelpClaimRewards {
sender: String,
id: Vec<u64>,
},
}

impl ElysMsg {
Expand Down Expand Up @@ -364,6 +369,10 @@ impl ElysMsg {
}
}

pub fn leveragelp_withdraw_reward(sender: String, id: Vec<u64>) -> Self {
Self::LeveragelpClaimRewards { sender, id }
}

pub fn estaking_withdraw_reward(delegator_address: String, validator_address: String) -> Self {
Self::EstakingWithdrawReward {
delegator_address,
Expand Down
57 changes: 50 additions & 7 deletions bindings/src/querier.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::collections::HashMap;
use std::str::FromStr;
use std::{ascii::AsciiExt, collections::HashMap};

use cosmwasm_std::{
coin, to_json_vec, Binary, Coin, ContractResult, Decimal, Int128, QuerierWrapper, QueryRequest,
Expand Down Expand Up @@ -790,6 +790,17 @@ impl<'a> ElysQuerier<'a> {
))
}

pub fn query_leverage_lp_rewards(
&self,
address: String,
ids: Vec<u64>,
) -> StdResult<GetLeverageLpRewardsResp> {
self.querier
.query(&QueryRequest::Custom(ElysQuery::query_leverage_lp_rewards(
address, ids,
)))
}

pub fn get_masterchef_pool_apr(&self, pool_ids: Vec<u64>) -> StdResult<QueryPoolAprsResponse> {
let query = ElysQuery::get_masterchef_pool_apr(pool_ids);
let request = QueryRequest::Custom(query);
Expand Down Expand Up @@ -885,22 +896,54 @@ impl<'a> ElysQuerier<'a> {
};
Ok(resp)
}
pub fn leveragelp_query_positions_for_address(

fn leveragelp_query_positions_for_address(
&self,
address: impl Into<String>,
pagination: Option<PageRequest>,
) -> StdResult<LeveragelpPositionsResponse> {
) -> StdResult<LeveragelpPositionsResponseRaw> {
let req = QueryRequest::Custom(ElysQuery::leveragelp_query_positions_for_address(
address.into(),
pagination,
));
let raw_resp: LeveragelpPositionsResponseRaw = self.querier.query(&req)?;
let positions = raw_resp.positions.unwrap_or(vec![]);
Ok(LeveragelpPositionsResponse {
positions,
self.querier.query(&req)
}

pub fn get_leveragelp_query_positions_for_address(
&self,
address: impl Into<String>,
prev_pagination: Option<PageRequest>,
) -> StdResult<LeveragelpPositionsAndRewardsResponse> {
let address: String = address.into();
let raw_resp: LeveragelpPositionsResponseRaw =
self.leveragelp_query_positions_for_address(address.to_string(), prev_pagination)?;
let leverage_reward_data =
self.query_leverage_lp_rewards(address.to_string(), raw_resp.get_pools())?;

let mut usdc = Decimal::zero();
let mut eden = Uint128::zero();

for coin in leverage_reward_data.total_rewards {
if coin.denom == "uusdc".to_string() {
usdc = CoinValue::from_coin(&coin, self)?.amount_usd;
} else {
eden = coin.amount;
}
}

Ok(LeveragelpPositionsAndRewardsResponse {
positions: raw_resp.positions.unwrap_or(vec![]),
pagination: raw_resp.pagination,
usdc,
eden,
})
}
pub fn leveragelp_pool_ids_for_address(&self, address: String) -> StdResult<Vec<u64>> {
let pagination = PageRequest::total();
let raw_resp =
self.leveragelp_query_positions_for_address(address.clone(), Some(pagination.clone()))?;
Ok(raw_resp.get_pools())
}
pub fn leveragelp_get_whitelist(
&self,
pagination: Option<PageRequest>,
Expand Down
5 changes: 5 additions & 0 deletions bindings/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ pub enum ElysQuery {
CommitmentVestingInfo { address: String },
#[returns(CommitmentNumberOfCommitmentsResponse)]
CommitmentNumberOfCommitments {},
#[returns(GetLeverageLpRewardsResp)]
LeveragelpRewards { address: String, ids: Vec<u64> },

// Define Incentive
#[returns(QueryAprResponse)]
Expand Down Expand Up @@ -451,4 +453,7 @@ impl ElysQuery {
pub fn commitment_number_of_commitments() -> Self {
Self::CommitmentNumberOfCommitments {}
}
pub fn query_leverage_lp_rewards(address: String, ids: Vec<u64>) -> Self {
Self::LeveragelpRewards { address, ids }
}
}
41 changes: 41 additions & 0 deletions bindings/src/query_resp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,12 +611,31 @@ pub struct LeveragelpPositionsResponseRaw {
pub pagination: Option<PageResponse>,
}

impl LeveragelpPositionsResponseRaw {
pub fn get_pools(&self) -> Vec<u64> {
self.positions
.clone()
.unwrap_or(vec![])
.iter()
.map(|x| x.amm_pool_id)
.collect()
}
}

#[cw_serde]
pub struct LeveragelpPositionsResponse {
pub positions: Vec<LeveragelpPosition>,
pub pagination: Option<PageResponse>,
}

#[cw_serde]
pub struct LeveragelpPositionsAndRewardsResponse {
pub positions: Vec<LeveragelpPosition>,
pub pagination: Option<PageResponse>,
pub usdc: Decimal,
pub eden: Uint128,
}

#[cw_serde]
pub struct LeveragelpStatusResponse {
pub open_position_count: u64,
Expand Down Expand Up @@ -955,3 +974,25 @@ pub struct CommitmentNumberOfCommitmentsResponseRaw {
pub struct CommitmentNumberOfCommitmentsResponse {
pub number: i64,
}

#[cw_serde]
pub struct GetLeverageLpRewardsResp {
pub rewards: RewardInfo,
pub total_rewards: Vec<Coin>,
}

#[cw_serde]
pub struct RewardInfo {
pub position_id: u64,
pub reward: Vec<Coin>,
}

impl GetLeverageLpRewardsResp {
pub fn total_rewards_to_coin(&self, querier: &ElysQuerier<'_>) -> StdResult<Vec<CoinValue>> {
let mut coin_values = Vec::new();
for reward in &self.total_rewards {
coin_values.push(CoinValue::from_coin(reward, querier)?);
}
Ok(coin_values)
}
}
2 changes: 2 additions & 0 deletions bindings/src/trade_shield/msg/query_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ pub enum QueryMsg {
},
#[returns(LeveragelpPositionResponse)]
LeveragelpPosition { address: String, id: u64 },
#[returns(GetLeverageLpRewardsResp)]
LeveragelpRewards { address: String, ids: Vec<u64> },
#[returns(TradeShieldParamsResponse)]
GetParams {},
#[returns(NumberOfPendingOrderResp)]
Expand Down
10 changes: 10 additions & 0 deletions bindings/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@ impl PageRequest {
pub fn update(&mut self, key: Option<Binary>) -> () {
self.key = key;
}

pub fn total() -> Self {
Self {
key: None,
offset: Some(0),
limit: 0,
count_total: true,
reverse: false,
}
}
}

#[cw_serde]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ pub fn claim_rewards_request(
pools_ids_to_claim,
));
}
let ids = querier.leveragelp_pool_ids_for_address(info.sender.to_string())?;

if !ids.is_empty() {
msgs.push(ElysMsg::leveragelp_withdraw_reward(
info.sender.to_string(),
ids,
));
}

let resp = Response::new().add_messages(msgs);

Expand Down
5 changes: 4 additions & 1 deletion contracts/trade-shield-contract/src/entry_point/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,14 @@ pub fn query(deps: Deps<ElysQuery>, env: Env, msg: QueryMsg) -> Result<Binary, C
address,
pagination,
} => Ok(to_json_binary(
&querier.leveragelp_query_positions_for_address(address, pagination)?,
&querier.get_leveragelp_query_positions_for_address(address, pagination)?,
)?),
LeveragelpGetWhitelist { pagination } => Ok(to_json_binary(
&querier.leveragelp_get_whitelist(pagination)?,
)?),
LeveragelpRewards { address, ids } => Ok(to_json_binary(
&querier.query_leverage_lp_rewards(address, ids)?,
)?),
LeveragelpIsWhitelisted { address } => Ok(to_json_binary(
&querier.leveragelp_is_whitelisted(address)?,
)?),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use crate::entry_point::{execute, query};
use anyhow::{bail, Result as AnyResult};
use cosmwasm_std::coin;
use cosmwasm_std::Coin;
use cosmwasm_std::Decimal;
use cosmwasm_std::Int128;
use cosmwasm_std::StdError;
use cosmwasm_std::Uint128;
use cosmwasm_std::{to_json_binary, Addr, Empty};
Expand All @@ -19,10 +21,13 @@ use cw_storage_plus::Item;
use cw_storage_plus::Map;
use elys_bindings::query_resp::DelegationDelegatorReward;
use elys_bindings::query_resp::EstakingRewardsResponse;
use elys_bindings::query_resp::LeveragelpPosition;
use elys_bindings::query_resp::LeveragelpPositionsResponse;
use elys_bindings::query_resp::MasterchefUserPendingRewardData;
use elys_bindings::query_resp::MasterchefUserPendingRewardResponse;
use elys_bindings::query_resp::Validator;
use elys_bindings::trade_shield::msg::ExecuteMsg;
use elys_bindings::types::PageResponse;
use elys_bindings::{ElysMsg, ElysQuery};
use elys_bindings_test::ElysModule;

Expand Down Expand Up @@ -115,6 +120,32 @@ impl Module for ElysModuleWrapper {
};
Ok(to_json_binary(&resp)?)
}
ElysQuery::LeveragelpQueryPositionsForAddress { .. } => {
let position = LeveragelpPosition {
address: "user".to_string(),
collateral: Coin {
denom: "uelys".to_string(),
amount: Uint128::new(100000000),
},
liabilities: Int128::zero(),
interest_paid: Int128::zero(),
leverage: Decimal::new(Uint128::new(10)),
leveraged_lp_amount: Int128::new(10000000),
position_health: Decimal::one(),
id: 1,
amm_pool_id: 1,
stop_loss_price: Decimal::one(),
};

let resp = LeveragelpPositionsResponse {
positions: vec![position],
pagination: Some(PageResponse {
next_key: None,
total: Some(1),
}),
};
Ok(to_json_binary(&resp)?)
}
_ => panic!("not implemented {request:?}"),
}
}
Expand Down Expand Up @@ -197,6 +228,20 @@ impl Module for ElysModuleWrapper {
}),
)
}
ElysMsg::LeveragelpClaimRewards { sender, .. } => router.sudo(
api,
storage,
block,
SudoMsg::Bank(BankSudo::Mint {
to_address: sender,
amount: vec![Coin {
denom:
"ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65"
.to_string(),
amount: Uint128::new(10000000),
}],
}),
),
_ => bail!("not implemented {msg:?}"),
}
}
Expand Down Expand Up @@ -281,7 +326,7 @@ fn claim_rewards_request() {

let msgs_called = app.init_modules(|_, _, storage| MSG_CALLED.load(storage).unwrap());

assert_eq!(msgs_called.len(), 3);
assert_eq!(msgs_called.len(), 4);
assert_eq!(
msgs_called[0],
ElysMsg::estaking_withdraw_elys_staking_rewards("user".to_string())
Expand All @@ -294,10 +339,14 @@ fn claim_rewards_request() {
msgs_called[2],
ElysMsg::get_masterchef_claim_rewards("user".to_string(), vec![2])
);
assert_eq!(
msgs_called[3],
ElysMsg::leveragelp_withdraw_reward("user".to_string(), vec![1])
);

let user_usdc_balance = app.wrap().query_balance("user", DENOM_INFO[0].0).unwrap();
let user_uelys_balance = app.wrap().query_balance("user", "uelys").unwrap();

assert_eq!(user_usdc_balance, coin(500, DENOM_INFO[0].0));
assert_eq!(user_usdc_balance, coin(10000500, DENOM_INFO[0].0));
assert_eq!(user_uelys_balance, coin(24100000, "uelys"));
}

0 comments on commit 8659727

Please sign in to comment.