Skip to content
This repository has been archived by the owner on Dec 29, 2023. It is now read-only.

Commit

Permalink
feat: add migration endpoint + optimize cancel orders (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
politeWall authored Dec 12, 2023
1 parent 7fc3207 commit 0c4485c
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 162 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "trade_shield_contract"
version = "0.10.0"
version = "0.11.0"
edition = "2021"

[lib]
Expand Down
136 changes: 56 additions & 80 deletions src/action/execute/cancel_margin_orders.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashMap;

use cosmwasm_std::{to_json_binary, Coin, StdError};

use super::*;
Expand All @@ -15,94 +17,69 @@ pub fn cancel_margin_orders(
});
}

let mut orders: Vec<MarginOrder> = MARGIN_ORDER
.prefix_range(deps.storage, None, None, Order::Ascending)
.filter_map(|res| res.ok().map(|r| r.1))
.collect();

let user_orders: Vec<MarginOrder> = orders
.iter()
.filter(|order| order.owner == info.sender)
.cloned()
.collect();
let orders: Vec<MarginOrder> = if let Some(ids) = &order_ids {
if ids.is_empty() {
return Err(StdError::generic_err("order_ids is defined empty").into());
};
let orders = ids
.iter()
.map(|id| MARGIN_ORDER.load(deps.storage, *id))
.collect::<Result<Vec<MarginOrder>, StdError>>()?;

if user_orders.is_empty() {
return Err(ContractError::StdError(StdError::not_found(
"no order found for this user",
)));
}
if orders.iter().any(|order| order.owner != owner_address) {
return Err(ContractError::Unauthorized {
sender: info.sender,
});
}

let filtered_order: Vec<MarginOrder> = filter_order_by_id(&user_orders, &order_ids)?;
if let Some(order) = orders.iter().find(|order| order.status != Status::Pending) {
return Err(ContractError::CancelStatusError {
order_id: order.order_id,
status: order.status.clone(),
});
}

let filtered_order = filter_order_by_type(filtered_order, order_type)?;
orders
} else {
let orders: Vec<MarginOrder> = MARGIN_ORDER
.prefix_range(deps.storage, None, None, Order::Ascending)
.filter_map(|res| {
if let Some(r) = res.ok() {
Some(r.1)
} else {
None
}
})
.filter(|order| {
order.owner.as_str() == &owner_address && order.status == Status::Pending
})
.collect();

if let Some(order) = filtered_order
.iter()
.find(|order| order.status != Status::Pending)
{
return Err(ContractError::CancelStatusError {
order_id: order.order_id,
status: order.status.clone(),
});
}
if orders.is_empty() {
return Err(ContractError::StdError(StdError::not_found(
"no order found for this user",
)));
};

let order_ids: Vec<u64> = match order_ids {
Some(order_ids) => order_ids,
None => filtered_order.iter().map(|order| order.order_id).collect(),
orders
};

let mut orders = filter_order_by_type(orders, order_type)?;

for order in orders.iter_mut() {
if order_ids.contains(&order.order_id) {
order.status = Status::Canceled;
MARGIN_ORDER.save(deps.storage, order.order_id, order)?;
}
order.status = Status::Canceled;
MARGIN_ORDER.save(deps.storage, order.order_id, order)?;
}

let refund_msg = make_refund_msg(filtered_order, owner_address);
let order_ids: Vec<u64> = orders.iter().map(|order| order.order_id).collect();

let refund_msg = make_refund_msg(orders, owner_address);

Ok(Response::new()
.add_message(refund_msg)
.set_data(to_json_binary(&order_ids)?))
}

fn filter_order_by_id(
orders: &Vec<MarginOrder>,
order_ids: &Option<Vec<u64>>,
) -> Result<Vec<MarginOrder>, ContractError> {
let order_ids = match order_ids {
Some(order_ids) => order_ids,
None => return Ok(orders.to_owned()),
};

if order_ids.is_empty() {
return Err(StdError::generic_err("order_ids is defined empty").into());
}

let filtered_order: Vec<MarginOrder> = orders
.iter()
.filter(|order| order_ids.contains(&order.order_id))
.cloned()
.collect();

if order_ids.len() != filtered_order.len() {
let missing_order_ids: Vec<u64> = order_ids
.iter()
.filter(|order_id| {
!filtered_order
.iter()
.any(|order| order.order_id == **order_id)
})
.cloned()
.collect();

return Err(ContractError::OrdersNotFound {
order_ids: missing_order_ids,
});
}

Ok(filtered_order)
}

fn filter_order_by_type(
orders: Vec<MarginOrder>,
order_type: Option<MarginOrderType>,
Expand Down Expand Up @@ -139,19 +116,18 @@ fn make_refund_msg(orders: Vec<MarginOrder>, user: String) -> BankMsg {
})
.collect();

let mut merged_amounts: Vec<Coin> = Vec::new();
let mut merged_amounts: HashMap<String, Coin> = HashMap::new();

for amount in orders_amount {
if let Some(existing_amount) = merged_amounts
.iter_mut()
.find(|coin| coin.denom == amount.denom)
{
existing_amount.amount += amount.amount;
for order_amount in orders_amount {
if let Some(entry) = merged_amounts.get_mut(&order_amount.denom) {
entry.amount += order_amount.amount;
} else {
merged_amounts.push(amount);
merged_amounts.insert(order_amount.denom.clone(), order_amount);
}
}

let merged_amounts: Vec<Coin> = merged_amounts.values().cloned().collect();

BankMsg::Send {
to_address: user,
amount: merged_amounts,
Expand Down
139 changes: 59 additions & 80 deletions src/action/execute/cancel_spot_orders.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashMap;

use cosmwasm_std::{to_json_binary, Coin, StdError};

use super::*;
Expand All @@ -15,94 +17,72 @@ pub fn cancel_spot_orders(
});
}

let mut orders: Vec<SpotOrder> = SPOT_ORDER
.prefix_range(deps.storage, None, None, Order::Ascending)
.filter_map(|res| res.ok().map(|r| r.1))
.collect();

let user_orders: Vec<SpotOrder> = orders
.iter()
.filter(|order| order.owner_address == info.sender)
.cloned()
.collect();
let orders: Vec<SpotOrder> = if let Some(ids) = &order_ids {
if ids.is_empty() {
return Err(StdError::generic_err("order_ids is defined empty").into());
};
let orders = ids
.iter()
.map(|id| SPOT_ORDER.load(deps.storage, *id))
.collect::<Result<Vec<SpotOrder>, StdError>>()?;

if user_orders.is_empty() {
return Err(ContractError::StdError(StdError::not_found(
"no order found for this user",
)));
}
if orders
.iter()
.any(|order| order.owner_address != owner_address)
{
return Err(ContractError::Unauthorized {
sender: info.sender,
});
}

let filtered_order: Vec<SpotOrder> = filter_order_by_id(&user_orders, &order_ids)?;
if let Some(order) = orders.iter().find(|order| order.status != Status::Pending) {
return Err(ContractError::CancelStatusError {
order_id: order.order_id,
status: order.status.clone(),
});
}

let filtered_order = filter_order_by_type(filtered_order, order_type)?;
orders
} else {
let orders: Vec<SpotOrder> = SPOT_ORDER
.prefix_range(deps.storage, None, None, Order::Ascending)
.filter_map(|res| {
if let Some(r) = res.ok() {
Some(r.1)
} else {
None
}
})
.filter(|order| {
order.owner_address.as_str() == &owner_address && order.status == Status::Pending
})
.collect();

if let Some(order) = filtered_order
.iter()
.find(|order| order.status != Status::Pending)
{
return Err(ContractError::CancelStatusError {
order_id: order.order_id,
status: order.status.clone(),
});
}
if orders.is_empty() {
return Err(ContractError::StdError(StdError::not_found(
"no order found for this user",
)));
};

let order_ids: Vec<u64> = match order_ids {
Some(order_ids) => order_ids,
None => filtered_order.iter().map(|order| order.order_id).collect(),
orders
};

let mut orders = filter_order_by_type(orders, order_type)?;

for order in orders.iter_mut() {
if order_ids.contains(&order.order_id) {
order.status = Status::Canceled;
SPOT_ORDER.save(deps.storage, order.order_id, &order)?;
}
order.status = Status::Canceled;
SPOT_ORDER.save(deps.storage, order.order_id, &order)?;
}

let refund_msg = make_refund_msg(filtered_order, owner_address);
let order_ids: Vec<u64> = orders.iter().map(|order| order.order_id).collect();

let refund_msg = make_refund_msg(orders, owner_address);

Ok(Response::new()
.add_message(refund_msg)
.set_data(to_json_binary(&order_ids)?))
}

fn filter_order_by_id(
orders: &Vec<SpotOrder>,
order_ids: &Option<Vec<u64>>,
) -> Result<Vec<SpotOrder>, ContractError> {
let order_ids = match order_ids {
Some(order_ids) => order_ids,
None => return Ok(orders.to_owned()),
};

if order_ids.is_empty() {
return Err(StdError::generic_err("order_ids is defined empty").into());
}

let filtered_order: Vec<SpotOrder> = orders
.iter()
.filter(|order| order_ids.contains(&order.order_id))
.cloned()
.collect();

if order_ids.len() != filtered_order.len() {
let missing_order_ids: Vec<u64> = order_ids
.iter()
.filter(|order_id| {
!filtered_order
.iter()
.any(|order| order.order_id == **order_id)
})
.cloned()
.collect();

return Err(ContractError::OrdersNotFound {
order_ids: missing_order_ids,
});
}

Ok(filtered_order)
}

fn filter_order_by_type(
orders: Vec<SpotOrder>,
order_type: Option<SpotOrderType>,
Expand Down Expand Up @@ -130,19 +110,18 @@ fn filter_order_by_type(
fn make_refund_msg(orders: Vec<SpotOrder>, user: String) -> BankMsg {
let orders_amount: Vec<Coin> = orders.into_iter().map(|order| order.order_amount).collect();

let mut merged_amounts: Vec<Coin> = Vec::new();
let mut merged_amounts: HashMap<String, Coin> = HashMap::new();

for amount in orders_amount {
if let Some(existing_amount) = merged_amounts
.iter_mut()
.find(|coin| coin.denom == amount.denom)
{
existing_amount.amount += amount.amount;
for order_amount in orders_amount {
if let Some(entry) = merged_amounts.get_mut(&order_amount.denom) {
entry.amount += order_amount.amount;
} else {
merged_amounts.push(amount);
merged_amounts.insert(order_amount.denom.clone(), order_amount);
}
}

let merged_amounts: Vec<Coin> = merged_amounts.values().cloned().collect();

BankMsg::Send {
to_address: user,
amount: merged_amounts,
Expand Down
13 changes: 13 additions & 0 deletions src/entry_point/migrate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use cosmwasm_std::Empty;

use super::*;

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn migrate(
_deps: DepsMut<ElysQuery>,
_env: Env,
_info: MessageInfo,
_msg: Empty,
) -> StdResult<Response<ElysMsg>> {
Ok(Response::new())
}
2 changes: 2 additions & 0 deletions src/entry_point/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ use elys_bindings::*;

mod execute;
mod instantiate;
mod migrate;
mod query;
mod reply;
mod sudo;

pub use execute::execute;
pub use instantiate::instantiate;
pub use migrate::migrate;
pub use query::query;
pub use reply::reply;
pub use sudo::sudo;

0 comments on commit 0c4485c

Please sign in to comment.