diff --git a/bindings/src/account_history/msg/execute.rs b/bindings/src/account_history/msg/execute.rs index 0588fadf..4af4ee62 100644 --- a/bindings/src/account_history/msg/execute.rs +++ b/bindings/src/account_history/msg/execute.rs @@ -11,11 +11,8 @@ pub enum ExecuteMsg { delete_old_data_enabled: Option, delete_epoch: Option, }, - UpdateAccount {}, - CleanHistory { - limit: u64, - }, - CleanOldHistory { + CleanStorage { limit: u64, }, + CleanStorageBulk {}, } diff --git a/bindings/src/account_history/msg/mod.rs b/bindings/src/account_history/msg/mod.rs index 0f3b94c0..6e6323c0 100644 --- a/bindings/src/account_history/msg/mod.rs +++ b/bindings/src/account_history/msg/mod.rs @@ -13,6 +13,7 @@ pub use sudo::SudoMsg; pub mod query_resp { mod get_all_resp; mod get_rewards_resp; + mod get_storage_size; mod liquid_asset; mod membership_tier_response; mod params_resp; @@ -21,6 +22,7 @@ pub mod query_resp { pub use get_all_resp::GetAllResp; pub use get_rewards_resp::GetRewardsResp; + pub use get_storage_size::StorageSizeResp; pub use liquid_asset::LiquidAsset; pub use membership_tier_response::MembershipTierResponse; pub use params_resp::ParamsResp; diff --git a/bindings/src/account_history/msg/query.rs b/bindings/src/account_history/msg/query.rs index 99b769a4..7c4d7d38 100644 --- a/bindings/src/account_history/msg/query.rs +++ b/bindings/src/account_history/msg/query.rs @@ -160,8 +160,8 @@ pub enum QueryMsg { IncentiveAprs {}, #[cfg(feature = "debug")] - #[returns(Uint128)] - AddressQueueSize {}, + #[returns(StorageSizeResp)] + StorageSize {}, #[cfg(feature = "debug")] #[returns(ContractVersion)] diff --git a/bindings/src/account_history/msg/query_resp/get_storage_size.rs b/bindings/src/account_history/msg/query_resp/get_storage_size.rs new file mode 100644 index 00000000..dff0900c --- /dev/null +++ b/bindings/src/account_history/msg/query_resp/get_storage_size.rs @@ -0,0 +1,8 @@ +use cosmwasm_schema::cw_serde; + +#[cw_serde] +pub struct StorageSizeResp { + pub user_address_queue_data_size: u128, + pub history_data_size: u128, + pub old_history_2_data_size: u128, +} diff --git a/contracts/account-history-contract/src/action/execute/clean_up_storage.rs b/contracts/account-history-contract/src/action/execute/clean_up_storage.rs new file mode 100644 index 00000000..98a93352 --- /dev/null +++ b/contracts/account-history-contract/src/action/execute/clean_up_storage.rs @@ -0,0 +1,20 @@ +use cosmwasm_std::{DepsMut, Response, StdResult}; + +use crate::states::{HISTORY, OLD_HISTORY_2, USER_ADDRESS_QUEUE}; +use elys_bindings::{ElysMsg, ElysQuery}; + +pub fn clean_up_storage(deps: &mut DepsMut, limit: u64) -> StdResult> { + // Delete history values + for _ in 0..limit { + if let Some(val) = HISTORY.first(deps.storage)? { + HISTORY.remove(deps.storage, &val.0); + } + if let Some(val) = OLD_HISTORY_2.first(deps.storage)? { + OLD_HISTORY_2.remove(deps.storage, &val.0); + } + if !USER_ADDRESS_QUEUE.is_empty(deps.storage).unwrap() { + let _ = USER_ADDRESS_QUEUE.pop_front(deps.storage); + } + } + Ok(Response::default()) +} diff --git a/contracts/account-history-contract/src/action/mod.rs b/contracts/account-history-contract/src/action/mod.rs index 241f5943..641ed9de 100644 --- a/contracts/account-history-contract/src/action/mod.rs +++ b/contracts/account-history-contract/src/action/mod.rs @@ -1,10 +1,3 @@ -pub mod sudo { - mod update_account_chain; - pub use update_account_chain::{ - clean_old_history, clean_up_history, update_account, update_account_chain, - }; -} - pub mod query { mod get_liquid_assets; use crate::error::ContractError; @@ -70,5 +63,12 @@ pub mod query { pub mod execute { mod add_user_address_to_queue; + mod clean_up_storage; pub use add_user_address_to_queue::add_user_address_to_queue; + pub use clean_up_storage::clean_up_storage; +} + +pub mod sudo { + mod update_metadata_prices; + pub use update_metadata_prices::update_metadata_prices; } diff --git a/contracts/account-history-contract/src/action/sudo/mod.rs b/contracts/account-history-contract/src/action/sudo/mod.rs deleted file mode 100644 index cda648a7..00000000 --- a/contracts/account-history-contract/src/action/sudo/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -use update_account::update_account; -use update_account_chain::update_account_chain; -use clean_up_history::clean_up_history; diff --git a/contracts/account-history-contract/src/action/sudo/update_account_chain.rs b/contracts/account-history-contract/src/action/sudo/update_account_chain.rs deleted file mode 100644 index 289aedf3..00000000 --- a/contracts/account-history-contract/src/action/sudo/update_account_chain.rs +++ /dev/null @@ -1,138 +0,0 @@ -use chrono::NaiveDateTime; -use cosmwasm_std::{DepsMut, Env, Response, StdResult, Timestamp}; -use cw_utils::Expiration; - -use crate::{ - states::{HISTORY, METADATA, OLD_HISTORY_2, PROCESSED_ACCOUNT_PER_BLOCK, USER_ADDRESS_QUEUE}, - types::AccountSnapshotGenerator, - utils::get_today, -}; -use elys_bindings::{ElysMsg, ElysQuerier, ElysQuery}; - -pub fn update_account(deps: DepsMut, env: Env) -> StdResult> { - let querier = ElysQuerier::new(&deps.querier); - - // update metadata prices - let mut metadata = METADATA.load(deps.storage)?; - metadata = metadata.update_prices(&querier)?; - METADATA.save(deps.storage, &metadata)?; - - let today = get_today(&env.block); - - let processed_account_per_block: usize = - PROCESSED_ACCOUNT_PER_BLOCK.load(deps.storage)? as usize; - - let generator = AccountSnapshotGenerator::new(&deps.as_ref())?; - - for _ in 0..processed_account_per_block { - if USER_ADDRESS_QUEUE.is_empty(deps.storage)? == true { - break; - } - - // remove the first element from the queue - let user_address = if let Some(addr) = USER_ADDRESS_QUEUE.pop_back(deps.storage)? { - addr.to_string() - } else { - break; - }; - - let key = today.clone() + &user_address; - - if let Some(_) = HISTORY.may_load(deps.storage, &key)? { - // skip if the account has been updated today - continue; - } - - let new_part = generator.generate_portfolio_balance_snapshot_for_address( - &querier, - &deps.as_ref(), - &env, - &user_address, - )?; - HISTORY.save(deps.storage, &key, &new_part)?; - } - - Ok(Response::default()) -} - -pub fn update_account_chain(deps: DepsMut, env: Env) -> StdResult> { - let processed_account_per_block: usize = - PROCESSED_ACCOUNT_PER_BLOCK.load(deps.storage)? as usize; - - let mut msgs = vec![]; - for _ in 0..processed_account_per_block { - if USER_ADDRESS_QUEUE.is_empty(deps.storage)? == true { - break; - } - - // remove the first element from the queue - let user_address = if let Some(addr) = USER_ADDRESS_QUEUE.pop_back(deps.storage)? { - addr.to_string() - } else { - break; - }; - - let msg: ElysMsg = - ElysMsg::tier_set_portfolio(env.contract.address.to_string(), user_address); - msgs.push(msg) - } - - Ok(Response::default().add_messages(msgs)) -} - -pub fn clean_up_history( - deps: &mut DepsMut, - env: Env, - limit: u64, -) -> StdResult> { - let generator = AccountSnapshotGenerator::new(&deps.as_ref())?; - let block_info = env.block; - let expiration = match generator.expiration { - Expiration::AtHeight(h) => Timestamp::from_seconds(h * 3), // since a block is created every 3 seconds - Expiration::AtTime(t) => t.clone(), - _ => panic!("never expire"), - }; - - if expiration > block_info.time { - return Ok(Response::default()); - } - - let expired_date = NaiveDateTime::from_timestamp_opt( - block_info - .time - .minus_seconds(expiration.seconds()) - .seconds() as i64, - 0, - ) - .expect("Failed to convert block time to date") - .format("%Y-%m-%d") - .to_string(); - - // Delete limit values - for _ in 0..limit { - if let Some(val) = HISTORY.first(deps.storage)? { - let date_part = &val.0[0..10]; - if date_part < expired_date.as_str() { - HISTORY.remove(deps.storage, &val.0); - } - } else { - break; - } - } - Ok(Response::default()) -} - -pub fn clean_old_history( - deps: &mut DepsMut, - limit: u64, -) -> StdResult> { - // Delete limit values - for _ in 0..limit { - if let Some(val) = OLD_HISTORY_2.first(deps.storage)? { - OLD_HISTORY_2.remove(deps.storage, &val.0); - } else { - break; - } - } - Ok(Response::default()) -} diff --git a/contracts/account-history-contract/src/action/sudo/update_metadata_prices.rs b/contracts/account-history-contract/src/action/sudo/update_metadata_prices.rs new file mode 100644 index 00000000..3d5293d5 --- /dev/null +++ b/contracts/account-history-contract/src/action/sudo/update_metadata_prices.rs @@ -0,0 +1,14 @@ +use crate::states::METADATA; +use cosmwasm_std::{DepsMut, Response, StdResult}; +use elys_bindings::{ElysMsg, ElysQuerier, ElysQuery}; + +pub fn update_metadata_prices(deps: DepsMut) -> StdResult> { + let querier = ElysQuerier::new(&deps.querier); + + // update metadata prices + let mut metadata = METADATA.load(deps.storage)?; + metadata = metadata.update_prices(&querier)?; + METADATA.save(deps.storage, &metadata)?; + + Ok(Response::default()) +} diff --git a/contracts/account-history-contract/src/entry_point/execute.rs b/contracts/account-history-contract/src/entry_point/execute.rs index 9398f8b9..de7a742b 100644 --- a/contracts/account-history-contract/src/entry_point/execute.rs +++ b/contracts/account-history-contract/src/entry_point/execute.rs @@ -2,20 +2,17 @@ use cosmwasm_std::{entry_point, DepsMut, Env, MessageInfo, Response, StdError, S use elys_bindings::{account_history::msg::ExecuteMsg, ElysMsg, ElysQuery}; use crate::{ - action::{ - execute::add_user_address_to_queue, - sudo::{clean_old_history, clean_up_history, update_account_chain}, - }, + action::execute::{add_user_address_to_queue, clean_up_storage}, states::{ - DELETE_EPOCH, DELETE_OLD_DATA_ENABLED, PARAMS_ADMIN, PROCESSED_ACCOUNT_PER_BLOCK, - TRADE_SHIELD_ADDRESS, UPDATE_ACCOUNT_ENABLED, + DELETE_EPOCH, DELETE_OLD_DATA_ENABLED, HISTORY, OLD_HISTORY_2, PARAMS_ADMIN, + PROCESSED_ACCOUNT_PER_BLOCK, TRADE_SHIELD_ADDRESS, UPDATE_ACCOUNT_ENABLED, }, }; #[cfg_attr(not(feature = "library"), entry_point)] pub fn execute( mut deps: DepsMut, - env: Env, + _env: Env, info: MessageInfo, msg: ExecuteMsg, ) -> StdResult> { @@ -60,26 +57,20 @@ pub fn execute( } Ok(Response::new()) } - ExecuteMsg::UpdateAccount {} => { - if info.sender != PARAMS_ADMIN.load(deps.storage)? { - return Err(StdError::generic_err("Unauthorized")); - } - let resp = update_account_chain(deps, env)?; - Ok(resp) - } - ExecuteMsg::CleanHistory { limit } => { + ExecuteMsg::CleanStorage { limit } => { if info.sender != PARAMS_ADMIN.load(deps.storage)? { return Err(StdError::generic_err("Unauthorized")); } - let resp = clean_up_history(&mut deps, env, limit)?; + let resp = clean_up_storage(&mut deps, limit)?; Ok(resp) } - ExecuteMsg::CleanOldHistory { limit } => { + ExecuteMsg::CleanStorageBulk {} => { if info.sender != PARAMS_ADMIN.load(deps.storage)? { return Err(StdError::generic_err("Unauthorized")); } - let resp = clean_old_history(&mut deps, limit)?; - Ok(resp) + HISTORY.clear(deps.storage); + OLD_HISTORY_2.clear(deps.storage); + Ok(Response::new()) } } } diff --git a/contracts/account-history-contract/src/entry_point/query.rs b/contracts/account-history-contract/src/entry_point/query.rs index d6f427e1..a629aaf2 100644 --- a/contracts/account-history-contract/src/entry_point/query.rs +++ b/contracts/account-history-contract/src/entry_point/query.rs @@ -6,7 +6,7 @@ use crate::{ get_membership_tier, get_perpetuals_assets, get_pool_balances, get_rewards, get_staked_assets, get_usdc_earn_program_details, }, - states::USER_ADDRESS_QUEUE, + states::{HISTORY, OLD_HISTORY_2, USER_ADDRESS_QUEUE}, types::AccountSnapshotGenerator, }; @@ -19,7 +19,9 @@ use crate::action::query::{ use cosmwasm_std::{entry_point, to_json_binary, Binary, Deps, Env, StdResult}; use cw2::CONTRACT; use elys_bindings::{ - account_history::types::ElysDenom, query_resp::QueryAprResponse, ElysQuerier, ElysQuery, + account_history::{msg::query_resp::StorageSizeResp, types::ElysDenom}, + query_resp::QueryAprResponse, + ElysQuerier, ElysQuery, }; use crate::msg::QueryMsg; @@ -254,10 +256,20 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { + StorageSize {} => { let user_address_queue_data_size = USER_ADDRESS_QUEUE.len(deps.storage)? as u128; + let history_data_size = HISTORY + .keys(deps.storage, None, None, cosmwasm_std::Order::Descending) + .count() as u128; + let old_history_2_data_size = OLD_HISTORY_2 + .keys(deps.storage, None, None, cosmwasm_std::Order::Descending) + .count() as u128; - to_json_binary(&user_address_queue_data_size) + to_json_binary(&StorageSizeResp { + user_address_queue_data_size, + history_data_size, + old_history_2_data_size, + }) } Version {} => to_json_binary(&CONTRACT.load(deps.storage)?), } diff --git a/contracts/account-history-contract/src/entry_point/sudo.rs b/contracts/account-history-contract/src/entry_point/sudo.rs index 4a41fc18..950a6491 100644 --- a/contracts/account-history-contract/src/entry_point/sudo.rs +++ b/contracts/account-history-contract/src/entry_point/sudo.rs @@ -1,28 +1,20 @@ -use crate::msg::SudoMsg; -use crate::states::{DELETE_EPOCH, DELETE_OLD_DATA_ENABLED}; -use crate::{ - action::sudo::{clean_old_history, clean_up_history, update_account}, - states::UPDATE_ACCOUNT_ENABLED, -}; -use cosmwasm_std::{entry_point, DepsMut, Env, Response, StdError, StdResult}; +use crate::action::execute::clean_up_storage; +use crate::action::sudo::update_metadata_prices; +use crate::states::DELETE_OLD_DATA_ENABLED; +use crate::{msg::SudoMsg, states::DELETE_EPOCH}; +use cosmwasm_std::{entry_point, DepsMut, Env, Response, StdResult}; use elys_bindings::{ElysMsg, ElysQuery}; #[cfg_attr(not(feature = "library"), entry_point)] -pub fn sudo(mut deps: DepsMut, env: Env, msg: SudoMsg) -> StdResult> { +pub fn sudo(mut deps: DepsMut, _env: Env, msg: SudoMsg) -> StdResult> { match msg { SudoMsg::ClockEndBlock {} => { - if UPDATE_ACCOUNT_ENABLED.load(deps.storage)? == false { - return Err(StdError::generic_err("Update account is disabled")); - } - let epoch = DELETE_EPOCH.load(deps.storage)?; - if DELETE_OLD_DATA_ENABLED.load(deps.storage)? == true && env.block.height % epoch == 0 - { - clean_old_history(&mut deps, epoch)?; - clean_up_history(&mut deps, env.clone(), epoch)?; + if DELETE_OLD_DATA_ENABLED.load(deps.storage)? == true { + clean_up_storage(&mut deps, epoch)?; } - - update_account(deps, env) + update_metadata_prices(deps)?; + Ok(Response::new()) } } } diff --git a/contracts/account-history-contract/src/tests/get_all_pools.rs b/contracts/account-history-contract/src/tests/get_all_pools.rs index c1957470..764d5914 100644 --- a/contracts/account-history-contract/src/tests/get_all_pools.rs +++ b/contracts/account-history-contract/src/tests/get_all_pools.rs @@ -282,8 +282,9 @@ fn get_all_pools() { ) .unwrap(); - app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}) - .unwrap(); + let msg = app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}); + + println!("{:?}", msg); let resp: QueryEarnPoolResponse = app .wrap() diff --git a/contracts/account-history-contract/src/tests/mod.rs b/contracts/account-history-contract/src/tests/mod.rs index 5617595e..f5708269 100644 --- a/contracts/account-history-contract/src/tests/mod.rs +++ b/contracts/account-history-contract/src/tests/mod.rs @@ -6,5 +6,3 @@ mod get_liquid_assets; mod get_rewards; mod get_staked_assets; mod get_usdc_earn_program_details; -mod update_accounts; -mod week_snapshots; diff --git a/contracts/account-history-contract/src/tests/update_accounts.rs b/contracts/account-history-contract/src/tests/update_accounts.rs deleted file mode 100644 index 52acf446..00000000 --- a/contracts/account-history-contract/src/tests/update_accounts.rs +++ /dev/null @@ -1,465 +0,0 @@ -use std::str::FromStr; - -use crate::msg::query_resp::UserValueResponse; -use crate::msg::SudoMsg; -use crate::msg::{InstantiateMsg, QueryMsg}; -use cosmwasm_std::{coins, Addr, BlockInfo, Coin, Decimal, Decimal256, Timestamp}; -use cw_multi_test::{BankSudo, BasicAppBuilder, ContractWrapper, Executor, SudoMsg as AppSudo}; -use elys_bindings::types::{OracleAssetInfo, Price, SwapAmountInRoute}; -use elys_bindings_test::{ - ACCOUNT, ASSET_INFO, LAST_MODULE_USED, PERPETUAL_OPENED_POSITION, PRICES, -}; -use trade_shield_contract::entry_point::{ - execute as trade_shield_execute, instantiate as trade_shield_init, - migrate as trade_shield_migrate, query as trade_shield_query, -}; -use trade_shield_contract::msg as trade_shield_msg; -use trade_shield_contract::types::{OrderPrice, SpotOrderType}; - -use crate::entry_point::instantiate; -use crate::entry_point::{execute, query, sudo}; -use anyhow::{bail, Error, Result as AnyResult}; -use cosmwasm_std::{to_json_binary, Empty, Int128, SignedDecimal, StdError, Uint128}; -use cw_multi_test::{AppResponse, Module}; - -use elys_bindings::query_resp::{ - AmmSwapEstimationByDenomResponse, DelegationDelegatorReward, Entry, EstakingRewardsResponse, - MasterchefUserPendingRewardData, MasterchefUserPendingRewardResponse, OracleAssetInfoResponse, - QueryGetEntryResponse, QueryGetPriceResponse, QueryStableStakeAprResponse, Validator, -}; -use elys_bindings::types::BalanceAvailable; -use elys_bindings::{ElysMsg, ElysQuery}; -use elys_bindings_test::ElysModule; - -struct ElysModuleWrapper(ElysModule); - -impl Module for ElysModuleWrapper { - type QueryT = ElysQuery; - type ExecT = ElysMsg; - type SudoT = Empty; - - fn query( - &self, - api: &dyn cosmwasm_std::Api, - storage: &dyn cosmwasm_std::Storage, - querier: &dyn cosmwasm_std::Querier, - block: &cosmwasm_std::BlockInfo, - request: Self::QueryT, - ) -> AnyResult { - match request { - ElysQuery::AmmBalance { .. } => { - let resp = BalanceAvailable { - amount: Uint128::new(0), - usd_amount: Decimal::zero(), - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::AssetProfileEntry { base_denom } => { - let resp = match base_denom.as_str() { - "uusdc" => QueryGetEntryResponse { - entry: Entry { - address: "".to_string(), - authority: "elys10d07y265gmmuvt4z0w9aw880jnsr700j6z2zm3".to_string(), - base_denom: "uusdc".to_string(), - commit_enabled: true, - decimals: 6, - denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - display_name: "USDC".to_string(), - display_symbol: "uUSDC".to_string(), - external_symbol: "uUSDC".to_string(), - ibc_channel_id: "channel-12".to_string(), - ibc_counterparty_chain_id: "".to_string(), - ibc_counterparty_channel_id: "channel-19".to_string(), - ibc_counterparty_denom: "".to_string(), - network: "".to_string(), - path: "transfer/channel-12".to_string(), - permissions: vec![], - transfer_limit: "".to_string(), - unit_denom: "uusdc".to_string(), - withdraw_enabled: true, - }, - }, - "ueden" => QueryGetEntryResponse { - entry: Entry { - address: "".to_string(), - authority: "elys10d07y265gmmuvt4z0w9aw880jnsr700j6z2zm3".to_string(), - base_denom: "ueden".to_string(), - commit_enabled: true, - decimals: 6, - denom: "ueden".to_string(), - display_name: "EDEN".to_string(), - display_symbol: "".to_string(), - external_symbol: "".to_string(), - ibc_channel_id: "".to_string(), - ibc_counterparty_chain_id: "".to_string(), - ibc_counterparty_channel_id: "".to_string(), - ibc_counterparty_denom: "".to_string(), - network: "".to_string(), - path: "".to_string(), - permissions: vec![], - transfer_limit: "".to_string(), - unit_denom: "".to_string(), - withdraw_enabled: true, - }, - }, - "uelys" => QueryGetEntryResponse { - entry: Entry { - address: "".to_string(), - authority: "elys10d07y265gmmuvt4z0w9aw880jnsr700j6z2zm3".to_string(), - base_denom: "uelys".to_string(), - commit_enabled: true, - decimals: 6, - denom: "uelys".to_string(), - display_name: "ELYS".to_string(), - display_symbol: "".to_string(), - external_symbol: "".to_string(), - ibc_channel_id: "".to_string(), - ibc_counterparty_chain_id: "".to_string(), - ibc_counterparty_channel_id: "".to_string(), - ibc_counterparty_denom: "".to_string(), - network: "".to_string(), - path: "".to_string(), - permissions: vec![], - transfer_limit: "".to_string(), - unit_denom: "".to_string(), - withdraw_enabled: true, - }, - }, - _ => return Err(Error::new(StdError::not_found(base_denom))), - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::AmmPriceByDenom { token_in, .. } => { - let spot_price = match token_in.denom.as_str() { - "uelys" => Decimal::from_str("3.449114").unwrap(), - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" => { - Decimal::one() - } - "ibc/E2D2F6ADCC68AA3384B2F5DFACCA437923D137C14E86FB8A10207CF3BED0C8D4" => { - Decimal::from_str("9.165195").unwrap() - } - _ => return Err(Error::new(StdError::not_found(token_in.denom.as_str()))), - }; - Ok(to_json_binary(&spot_price)?) - } - ElysQuery::OraclePrice { asset, .. } => { - let resp = match asset.as_str() { - "USDC" => QueryGetPriceResponse { - price: Price { - asset: "USDC".to_string(), - price: Decimal::one(), - source: "uelys".to_string(), - provider: "elys1wzm8dvpxpxxf26y4xn85w5adakcenprg4cq2uf".to_string(), - // set timestamp to now - timestamp: block.time.seconds(), - block_height: block.height, - }, - }, - _ => return Err(Error::new(StdError::not_found(asset))), - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::OracleAssetInfo { denom } => { - let resp = match denom.as_str() { - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" => { - OracleAssetInfoResponse { - asset_info: OracleAssetInfo { - band_ticker: "USDC".to_string(), - decimal: 6, - denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - display: "USDC".to_string(), - elys_ticker: "USDC".to_string(), - }, - } - } - "ibc/47BD209179859CDE4A2806763D7189B6E6FE13A17880FE2B42DE1E6C1E329E23" => { - OracleAssetInfoResponse { - asset_info: OracleAssetInfo { - band_ticker: "OSMO".to_string(), - decimal: 6, - denom: "ibc/47BD209179859CDE4A2806763D7189B6E6FE13A17880FE2B42DE1E6C1E329E23".to_string(), - display: "OSMO".to_string(), - elys_ticker: "OSMO".to_string(), - }, - } - } - "ibc/977D5388D2FBE72D9A33FE2423BF8F4DADF3B591207CC98A295B9ACF81E4DE40" => { - OracleAssetInfoResponse { - asset_info: OracleAssetInfo { - band_ticker: "JUNO".to_string(), - decimal: 6, - denom: "ibc/977D5388D2FBE72D9A33FE2423BF8F4DADF3B591207CC98A295B9ACF81E4DE40".to_string(), - display: "JUNO".to_string(), - elys_ticker: "JUNO".to_string(), - }, - } - } - "ibc/E2D2F6ADCC68AA3384B2F5DFACCA437923D137C14E86FB8A10207CF3BED0C8D4" => { - OracleAssetInfoResponse { - asset_info: OracleAssetInfo { - band_ticker: "ATOM".to_string(), - decimal: 6, - denom: "ibc/E2D2F6ADCC68AA3384B2F5DFACCA437923D137C14E86FB8A10207CF3BED0C8D4".to_string(), - display: "ATOM".to_string(), - elys_ticker: "ATOM".to_string(), - }, - } - }, - _ => return Err(Error::new(StdError::not_found(denom))), - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::AmmSwapEstimationByDenom { denom_out, .. } => { - let resp = AmmSwapEstimationByDenomResponse { - in_route: Some(vec![SwapAmountInRoute { - pool_id: 1, - token_out_denom: denom_out, - }]), - out_route: None, - spot_price: Decimal::from_str("3.5").unwrap(), - amount: Coin { - denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - amount: Uint128::new(100), - }, - swap_fee: SignedDecimal::one(), - discount: SignedDecimal::from_str("20").unwrap(), - available_liquidity: Coin { - denom: "uelys".to_string(), - amount: Uint128::new(100000), - }, - weight_balance_ratio: SignedDecimal::one(), - price_impact: SignedDecimal::zero(), - slippage: Decimal::zero(), - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::EstakingRewards { .. } => { - let resp = EstakingRewardsResponse { - rewards: vec![DelegationDelegatorReward { - validator_address: Validator::EdenBoost.to_string(), - reward: vec![Coin { - denom: "ueden".to_string(), - amount: Uint128::from_str("121").unwrap(), - }], - }], - total: vec![Coin { - denom: "uedenb".to_string(), - amount: Uint128::from_str("121").unwrap(), - }], - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::MasterchefStableStakeApr { .. } => { - let resp = QueryStableStakeAprResponse { - apr: Int128::new(12), - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::MasterchefUserPendingReward { .. } => { - let resp = MasterchefUserPendingRewardResponse { - rewards: vec![MasterchefUserPendingRewardData { - pool_id: 32767u64, - reward: vec![Coin { - denom: "ueden".to_string(), - amount: Uint128::new(20), - }], - }], - total_rewards: vec![Coin { - denom: "ueden".to_string(), - amount: Uint128::new(20), - }], - }; - Ok(to_json_binary(&resp)?) - } - _ => self.0.query(api, storage, querier, block, request), - } - } - - fn execute( - &self, - api: &dyn cosmwasm_std::Api, - storage: &mut dyn cosmwasm_std::Storage, - router: &dyn cw_multi_test::CosmosRouter, - block: &cosmwasm_std::BlockInfo, - sender: Addr, - msg: Self::ExecT, - ) -> AnyResult - where - ExecC: std::fmt::Debug - + Clone - + PartialEq - + schemars::JsonSchema - + serde::de::DeserializeOwned - + 'static, - QueryC: cosmwasm_std::CustomQuery + serde::de::DeserializeOwned + 'static, - { - match msg { - _ => self.0.execute(api, storage, router, block, sender, msg), - } - } - - fn sudo( - &self, - _api: &dyn cosmwasm_std::Api, - _storage: &mut dyn cosmwasm_std::Storage, - _router: &dyn cw_multi_test::CosmosRouter, - _block: &cosmwasm_std::BlockInfo, - _msg: Self::SudoT, - ) -> AnyResult - where - ExecC: std::fmt::Debug - + Clone - + PartialEq - + schemars::JsonSchema - + serde::de::DeserializeOwned - + 'static, - QueryC: cosmwasm_std::CustomQuery + serde::de::DeserializeOwned + 'static, - { - bail!("sudo is not implemented for ElysModule") - } -} - -#[test] -fn history() { - let wallet: Vec<(&str, Vec)> = vec![("user-a", coins(300, "uelys"))]; - std::env::set_var("IS_TEST_ENV", "TESTING"); - - let mut addresses: Vec = vec![]; - let mut app = BasicAppBuilder::::new_custom() - .with_custom(ElysModuleWrapper(ElysModule {})) - .build(|router, _, storage| { - for (wallet_owner, wallet_contenent) in wallet { - router - .bank - .init_balance(storage, &Addr::unchecked(wallet_owner), wallet_contenent) - .unwrap(); - addresses.push(wallet_owner.to_owned()) - } - ACCOUNT.save(storage, &addresses).unwrap(); - PERPETUAL_OPENED_POSITION.save(storage, &vec![]).unwrap(); - ASSET_INFO.save(storage, &vec![]).unwrap(); - PRICES.save(storage, &vec![]).unwrap(); - LAST_MODULE_USED.save(storage, &None).unwrap(); - }); - - // trade shield deployment - let trade_shield_code = - ContractWrapper::new(trade_shield_execute, trade_shield_init, trade_shield_query) - .with_migrate(trade_shield_migrate); - let trade_shield_code_id = app.store_code(Box::new(trade_shield_code)); - let trade_shield_init = trade_shield_msg::InstantiateMsg { - account_history_address: None, - }; - let trade_shield_address = app - .instantiate_contract( - trade_shield_code_id, - Addr::unchecked("owner"), - &trade_shield_init, - &[], - "Contract", - Some("admin".to_string()), - ) - .unwrap() - .to_string(); - - // Create a contract wrapper and store its code. - let code = ContractWrapper::new(execute, instantiate, query).with_sudo(sudo); - let code_id = app.store_code(Box::new(code)); - - // Create a mock message to instantiate the contract with no initial orders. - let instantiate_msg = InstantiateMsg { - limit: Some(3), - expiration: Some(cw_utils::Expiration::AtTime(Timestamp::from_seconds( - 604800, - ))), - trade_shield_address: Some(trade_shield_address.clone()), - }; - - // Instantiate the contract with "owner" as the deployer. - let addr = app - .instantiate_contract( - code_id, - Addr::unchecked("owner"), - &instantiate_msg, - &[], - "Contract", - None, - ) - .unwrap(); - - app.migrate_contract( - Addr::unchecked("admin"), - Addr::unchecked(trade_shield_address.clone()), - &trade_shield_msg::MigrateMsg { - account_history_address: Some(addr.to_string()), - }, - trade_shield_code_id, - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked("user-a"), - Addr::unchecked(trade_shield_address.clone()), - &trade_shield_msg::ExecuteMsg::CreateSpotOrder { - order_type: SpotOrderType::StopLoss, - order_source_denom: "uelys".to_string(), - order_target_denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - order_price: Some(OrderPrice { - base_denom: "uelys".to_string(), - quote_denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - rate: Decimal::one(), - }), - }, - &coins(100, "uelys"), - ) - .unwrap(); - - let update_msg = SudoMsg::ClockEndBlock {}; - - // t0 - app.set_block(BlockInfo { - height: 1, - time: Timestamp::from_seconds(0 * 24 * 60 * 60), - chain_id: "elys-app".to_string(), - }); - - app.wasm_sudo(addr.clone(), &update_msg).unwrap(); - - let query_msg = QueryMsg::UserValue { - user_address: "user-a".to_string(), - }; - - let res: UserValueResponse = app.wrap().query_wasm_smart(&addr, &query_msg).unwrap(); - - assert_eq!( - res.value.total_balance_usd, - Decimal256::from_str("400.00110371648").unwrap(), - ); - - app.sudo(AppSudo::Bank(BankSudo::Mint { - to_address: "user-a".to_string(), - amount: coins(200, "uelys"), - })) - .unwrap(); - - // t1 - app.set_block(BlockInfo { - height: 2, - time: Timestamp::from_seconds(1 * 24 * 60 * 60), - chain_id: "elys-app".to_string(), - }); - - app.wasm_sudo(addr.clone(), &update_msg).unwrap(); - - let res: UserValueResponse = app.wrap().query_wasm_smart(&addr, &query_msg).unwrap(); - - assert_eq!( - res.value.total_balance_usd, - Decimal256::from_str("400.00110371648").unwrap(), - ); // The previous value wasn't removed yet but wasn't read either since it's expired. - std::env::set_var("IS_TEST_ENV", "FALSE"); -} diff --git a/contracts/account-history-contract/src/tests/week_snapshots.rs b/contracts/account-history-contract/src/tests/week_snapshots.rs deleted file mode 100644 index 49ac5fde..00000000 --- a/contracts/account-history-contract/src/tests/week_snapshots.rs +++ /dev/null @@ -1,846 +0,0 @@ -use std::str::FromStr; -use std::vec; - -use crate::entry_point::instantiate; -use crate::{ - entry_point::{execute, query, sudo}, - msg::*, -}; -use anyhow::{bail, Error, Result as AnyResult}; -use cosmwasm_std::{ - coin, coins, to_json_binary, Addr, BlockInfo, Coin, Decimal, Empty, Int128, SignedDecimal, - StdError, Timestamp, Uint128, -}; -use cw_multi_test::{AppResponse, BankSudo, BasicAppBuilder, ContractWrapper, Executor, Module}; -use cw_utils::Expiration; -use elys_bindings::account_history::types::PortfolioBalanceSnapshot; -use elys_bindings::query_resp::{ - AmmSwapEstimationByDenomResponse, DelegationDelegatorReward, Entry, EstakingRewardsResponse, - MasterchefUserPendingRewardData, MasterchefUserPendingRewardResponse, OracleAssetInfoResponse, - QueryGetEntryResponse, QueryGetPriceResponse, QueryStableStakeAprResponse, Validator, -}; -use elys_bindings::types::{OracleAssetInfo, Price, SwapAmountInRoute}; -use elys_bindings::{ElysMsg, ElysQuery}; -use elys_bindings_test::{ - ElysModule, ACCOUNT, ASSET_INFO, LAST_MODULE_USED, PERPETUAL_OPENED_POSITION, PRICES, -}; -use trade_shield_contract::entry_point::{ - execute as trade_shield_execute, instantiate as trade_shield_init, - migrate as trade_shield_migrate, query as trade_shield_query, -}; -use trade_shield_contract::msg as trade_shield_msg; -use trade_shield_contract::types::{OrderPrice, SpotOrderType}; - -struct ElysModuleWrapper(ElysModule); - -impl Module for ElysModuleWrapper { - type QueryT = ElysQuery; - type ExecT = ElysMsg; - type SudoT = Empty; - - fn query( - &self, - api: &dyn cosmwasm_std::Api, - storage: &dyn cosmwasm_std::Storage, - querier: &dyn cosmwasm_std::Querier, - block: &cosmwasm_std::BlockInfo, - request: Self::QueryT, - ) -> AnyResult { - match request { - ElysQuery::AssetProfileEntry { base_denom } => { - let resp = match base_denom.as_str() { - "uusdc" => QueryGetEntryResponse { - entry: Entry { - address: "".to_string(), - authority: "elys10d07y265gmmuvt4z0w9aw880jnsr700j6z2zm3".to_string(), - base_denom: "uusdc".to_string(), - commit_enabled: true, - decimals: 6, - denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - display_name: "USDC".to_string(), - display_symbol: "uUSDC".to_string(), - external_symbol: "uUSDC".to_string(), - ibc_channel_id: "channel-12".to_string(), - ibc_counterparty_chain_id: "".to_string(), - ibc_counterparty_channel_id: "channel-19".to_string(), - ibc_counterparty_denom: "".to_string(), - network: "".to_string(), - path: "transfer/channel-12".to_string(), - permissions: vec![], - transfer_limit: "".to_string(), - unit_denom: "uusdc".to_string(), - withdraw_enabled: true, - }, - }, - "ueden" => QueryGetEntryResponse { - entry: Entry { - address: "".to_string(), - authority: "elys10d07y265gmmuvt4z0w9aw880jnsr700j6z2zm3".to_string(), - base_denom: "ueden".to_string(), - commit_enabled: true, - decimals: 6, - denom: "ueden".to_string(), - display_name: "EDEN".to_string(), - display_symbol: "".to_string(), - external_symbol: "".to_string(), - ibc_channel_id: "".to_string(), - ibc_counterparty_chain_id: "".to_string(), - ibc_counterparty_channel_id: "".to_string(), - ibc_counterparty_denom: "".to_string(), - network: "".to_string(), - path: "".to_string(), - permissions: vec![], - transfer_limit: "".to_string(), - unit_denom: "".to_string(), - withdraw_enabled: true, - }, - }, - "uelys" => QueryGetEntryResponse { - entry: Entry { - address: "".to_string(), - authority: "elys10d07y265gmmuvt4z0w9aw880jnsr700j6z2zm3".to_string(), - base_denom: "uelys".to_string(), - commit_enabled: true, - decimals: 6, - denom: "uelys".to_string(), - display_name: "ELYS".to_string(), - display_symbol: "".to_string(), - external_symbol: "".to_string(), - ibc_channel_id: "".to_string(), - ibc_counterparty_chain_id: "".to_string(), - ibc_counterparty_channel_id: "".to_string(), - ibc_counterparty_denom: "".to_string(), - network: "".to_string(), - path: "".to_string(), - permissions: vec![], - transfer_limit: "".to_string(), - unit_denom: "".to_string(), - withdraw_enabled: true, - }, - }, - _ => return Err(Error::new(StdError::not_found(base_denom))), - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::AmmPriceByDenom { token_in, .. } => { - let spot_price = match token_in.denom.as_str() { - "uelys" => Decimal::from_str("3.449114").unwrap(), - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" => { - Decimal::one() - } - "ibc/E2D2F6ADCC68AA3384B2F5DFACCA437923D137C14E86FB8A10207CF3BED0C8D4" => { - Decimal::from_str("9.165195").unwrap() - } - _ => return Err(Error::new(StdError::not_found(token_in.denom.as_str()))), - }; - Ok(to_json_binary(&spot_price)?) - } - ElysQuery::OraclePrice { asset, .. } => { - let resp = match asset.as_str() { - "USDC" => QueryGetPriceResponse { - price: Price { - asset: "USDC".to_string(), - price: Decimal::one(), - source: "uelys".to_string(), - provider: "elys1wzm8dvpxpxxf26y4xn85w5adakcenprg4cq2uf".to_string(), - // set timestamp to now - timestamp: block.time.seconds(), - block_height: block.height, - }, - }, - _ => return Err(Error::new(StdError::not_found(asset))), - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::OracleAssetInfo { denom } => { - let resp = match denom.as_str() { - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" => { - OracleAssetInfoResponse { - asset_info: OracleAssetInfo { - band_ticker: "USDC".to_string(), - decimal: 6, - denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - display: "USDC".to_string(), - elys_ticker: "USDC".to_string(), - }, - } - } - "ibc/47BD209179859CDE4A2806763D7189B6E6FE13A17880FE2B42DE1E6C1E329E23" => { - OracleAssetInfoResponse { - asset_info: OracleAssetInfo { - band_ticker: "OSMO".to_string(), - decimal: 6, - denom: "ibc/47BD209179859CDE4A2806763D7189B6E6FE13A17880FE2B42DE1E6C1E329E23".to_string(), - display: "OSMO".to_string(), - elys_ticker: "OSMO".to_string(), - }, - } - } - "ibc/977D5388D2FBE72D9A33FE2423BF8F4DADF3B591207CC98A295B9ACF81E4DE40" => { - OracleAssetInfoResponse { - asset_info: OracleAssetInfo { - band_ticker: "JUNO".to_string(), - decimal: 6, - denom: "ibc/977D5388D2FBE72D9A33FE2423BF8F4DADF3B591207CC98A295B9ACF81E4DE40".to_string(), - display: "JUNO".to_string(), - elys_ticker: "JUNO".to_string(), - }, - } - } - "ibc/E2D2F6ADCC68AA3384B2F5DFACCA437923D137C14E86FB8A10207CF3BED0C8D4" => { - OracleAssetInfoResponse { - asset_info: OracleAssetInfo { - band_ticker: "ATOM".to_string(), - decimal: 6, - denom: "ibc/E2D2F6ADCC68AA3384B2F5DFACCA437923D137C14E86FB8A10207CF3BED0C8D4".to_string(), - display: "ATOM".to_string(), - elys_ticker: "ATOM".to_string(), - }, - } - }, - _ => return Err(Error::new(StdError::not_found(denom))), - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::AmmSwapEstimationByDenom { - amount, - denom_out, - discount, - .. - } => { - let resp = AmmSwapEstimationByDenomResponse { - in_route: Some(vec![SwapAmountInRoute { - pool_id: 1, - token_out_denom: denom_out.clone(), - }]), - out_route: None, - spot_price: Decimal::one(), - amount, - swap_fee: SignedDecimal::zero(), - discount: SignedDecimal::from_str(discount.to_string().as_str()).unwrap(), - available_liquidity: coin(999999999, denom_out), - weight_balance_ratio: SignedDecimal::zero(), - price_impact: SignedDecimal::zero(), - slippage: Decimal::zero(), - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::EstakingRewards { .. } => { - let resp = EstakingRewardsResponse { - rewards: vec![DelegationDelegatorReward { - validator_address: Validator::EdenBoost.to_string(), - reward: vec![Coin { - denom: "ueden".to_string(), - amount: Uint128::from_str("121").unwrap(), - }], - }], - total: vec![Coin { - denom: "uedenb".to_string(), - amount: Uint128::from_str("121").unwrap(), - }], - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::MasterchefStableStakeApr { .. } => { - let resp = QueryStableStakeAprResponse { - apr: Int128::new(12), - }; - Ok(to_json_binary(&resp)?) - } - ElysQuery::MasterchefUserPendingReward { .. } => { - let resp = MasterchefUserPendingRewardResponse { - rewards: vec![MasterchefUserPendingRewardData { - pool_id: 32767u64, - reward: vec![Coin { - denom: "ueden".to_string(), - amount: Uint128::new(20), - }], - }], - total_rewards: vec![Coin { - denom: "ueden".to_string(), - amount: Uint128::new(20), - }], - }; - Ok(to_json_binary(&resp)?) - } - _ => self.0.query(api, storage, querier, block, request), - } - } - - fn execute( - &self, - api: &dyn cosmwasm_std::Api, - storage: &mut dyn cosmwasm_std::Storage, - router: &dyn cw_multi_test::CosmosRouter, - block: &cosmwasm_std::BlockInfo, - sender: Addr, - msg: Self::ExecT, - ) -> AnyResult - where - ExecC: std::fmt::Debug - + Clone - + PartialEq - + schemars::JsonSchema - + serde::de::DeserializeOwned - + 'static, - QueryC: cosmwasm_std::CustomQuery + serde::de::DeserializeOwned + 'static, - { - match msg { - _ => self.0.execute(api, storage, router, block, sender, msg), - } - } - - fn sudo( - &self, - _api: &dyn cosmwasm_std::Api, - _storage: &mut dyn cosmwasm_std::Storage, - _router: &dyn cw_multi_test::CosmosRouter, - _block: &cosmwasm_std::BlockInfo, - _msg: Self::SudoT, - ) -> AnyResult - where - ExecC: std::fmt::Debug - + Clone - + PartialEq - + schemars::JsonSchema - + serde::de::DeserializeOwned - + 'static, - QueryC: cosmwasm_std::CustomQuery + serde::de::DeserializeOwned + 'static, - { - bail!("sudo is not implemented for ElysModule") - } -} - -#[test] -fn get_portfolio() { - // Create a wallet for the "user" with an initial balance of 100 usdc - let wallet = vec![( - "user", - vec![coin( - 1445910542, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - )], - )]; - std::env::set_var("IS_TEST_ENV", "TESTING"); - - let mut addresses: Vec = vec![]; - let mut app = BasicAppBuilder::::new_custom() - .with_custom(ElysModuleWrapper(ElysModule {})) - .build(|router, _, storage| { - for (wallet_owner, wallet_contenent) in wallet { - router - .bank - .init_balance(storage, &Addr::unchecked(wallet_owner), wallet_contenent) - .unwrap(); - addresses.push(wallet_owner.to_owned()) - } - ACCOUNT.save(storage, &addresses).unwrap(); - PERPETUAL_OPENED_POSITION.save(storage, &vec![]).unwrap(); - ASSET_INFO.save(storage, &vec![]).unwrap(); - PRICES.save(storage, &vec![]).unwrap(); - LAST_MODULE_USED.save(storage, &None).unwrap(); - }); - - // trade shield deployment - let trade_shield_code = - ContractWrapper::new(trade_shield_execute, trade_shield_init, trade_shield_query) - .with_migrate(trade_shield_migrate); - let trade_shield_code_id = app.store_code(Box::new(trade_shield_code)); - let trade_shield_init = trade_shield_msg::InstantiateMsg { - account_history_address: None, - }; - let trade_shield_address = app - .instantiate_contract( - trade_shield_code_id, - Addr::unchecked("owner"), - &trade_shield_init, - &[], - "Contract", - Some("admin".to_string()), - ) - .unwrap(); - - // Create a contract wrapper and store its code. - let code = ContractWrapper::new(execute, instantiate, query).with_sudo(sudo); - let code_id = app.store_code(Box::new(code)); - - // Create a mock message to instantiate the contract with no initial orders. - let instantiate_msg = InstantiateMsg { - limit: Some(3), - expiration: Some(cw_utils::Expiration::AtTime(Timestamp::from_seconds( - 604800, - ))), - trade_shield_address: Some(trade_shield_address.to_string()), - }; - - // Instantiate the contract with "owner" as the deployer. - let addr = app - .instantiate_contract( - code_id, - Addr::unchecked("owner"), - &instantiate_msg, - &[], - "Contract", - None, - ) - .unwrap(); - - app.migrate_contract( - Addr::unchecked("admin"), - trade_shield_address.clone(), - &trade_shield_msg::MigrateMsg { - account_history_address: Some(addr.to_string()), - }, - trade_shield_code_id, - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked("user"), - trade_shield_address.clone(), - &trade_shield_msg::ExecuteMsg::CreateSpotOrder { - order_type: SpotOrderType::StopLoss, - order_source_denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - order_target_denom: "uelys".to_string(), - order_price: Some(OrderPrice { - base_denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - quote_denom: "uelys".to_string(), - rate: Decimal::one(), - }), - }, - &coins( - 100, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - ), - ) - .unwrap(); - - // t0 - app.set_block(BlockInfo { - height: 1, - time: Timestamp::from_seconds(0), - chain_id: "elys".to_string(), - }); - - // update account - app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}) - .unwrap(); - - // t1 (1d later) - app.set_block(BlockInfo { - height: 2, - time: Timestamp::from_seconds(24 * 60 * 60), - chain_id: "elys".to_string(), - }); - - // mint some coins - app.sudo( - BankSudo::Mint { - to_address: "user".to_string(), - amount: vec![coin( - 100000000, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - )], - } - .into(), - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked("user"), - trade_shield_address.clone(), - &trade_shield_msg::ExecuteMsg::CreateSpotOrder { - order_type: SpotOrderType::StopLoss, - order_source_denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - order_target_denom: "uelys".to_string(), - order_price: Some(OrderPrice { - base_denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - quote_denom: "uelys".to_string(), - rate: Decimal::one(), - }), - }, - &coins( - 100, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - ), - ) - .unwrap(); - // update account - app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}) - .unwrap(); - - // t2 (2d later) - app.set_block(BlockInfo { - height: 3, - time: Timestamp::from_seconds(24 * 60 * 60 * 2), - chain_id: "elys".to_string(), - }); - - // mint some coins - app.sudo( - BankSudo::Mint { - to_address: "user".to_string(), - amount: vec![coin( - 300000000, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - )], - } - .into(), - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked("user"), - trade_shield_address.clone(), - &trade_shield_msg::ExecuteMsg::CreateSpotOrder { - order_type: SpotOrderType::StopLoss, - order_source_denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - order_target_denom: "uelys".to_string(), - order_price: Some(OrderPrice { - base_denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - quote_denom: "uelys".to_string(), - rate: Decimal::one(), - }), - }, - &coins( - 100, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - ), - ) - .unwrap(); - // update account - app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}) - .unwrap(); - - // t3 (3d later) - app.set_block(BlockInfo { - height: 4, - time: Timestamp::from_seconds(24 * 60 * 60 * 3), - chain_id: "elys".to_string(), - }); - - // mint some coins - app.sudo( - BankSudo::Mint { - to_address: "user".to_string(), - amount: vec![coin( - 50000000, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - )], - } - .into(), - ) - .unwrap(); - - app.execute_contract( - Addr::unchecked("user"), - trade_shield_address.clone(), - &trade_shield_msg::ExecuteMsg::CreateSpotOrder { - order_type: SpotOrderType::StopLoss, - order_source_denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - order_target_denom: "uelys".to_string(), - order_price: Some(OrderPrice { - base_denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - quote_denom: "uelys".to_string(), - rate: Decimal::one(), - }), - }, - &coins( - 100, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - ), - ) - .unwrap(); - // update account - app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}) - .unwrap(); - - // Query the contract for the existing order. - let last_snapshot: PortfolioBalanceSnapshot = app - .wrap() - .query_wasm_smart( - &addr, - &QueryMsg::LastSnapshot { - user_address: "user".to_string(), - }, - ) - .unwrap(); - - // test if the response is the same as the expected - assert_eq!( - last_snapshot.date, - Expiration::AtTime(Timestamp::from_seconds(24 * 60 * 60 * 3)) - ); - - //update date 5 hours later - app.set_block(BlockInfo { - height: 5, - time: Timestamp::from_seconds(24 * 60 * 60 * 3 + 5 * 60 * 60), - chain_id: "elys".to_string(), - }); - - app.execute_contract( - Addr::unchecked("user"), - trade_shield_address.clone(), - &trade_shield_msg::ExecuteMsg::CreateSpotOrder { - order_type: SpotOrderType::StopLoss, - order_source_denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - order_target_denom: "uelys".to_string(), - order_price: Some(OrderPrice { - base_denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - quote_denom: "uelys".to_string(), - rate: Decimal::one(), - }), - }, - &coins( - 100, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - ), - ) - .unwrap(); - - app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}) - .unwrap(); - - let last_snapshot: PortfolioBalanceSnapshot = app - .wrap() - .query_wasm_smart( - &addr, - &QueryMsg::LastSnapshot { - user_address: "user".to_string(), - }, - ) - .unwrap(); - - // test if the response is the same as the expected - assert_eq!( - last_snapshot.date, - Expiration::AtTime(Timestamp::from_seconds(24 * 60 * 60 * 3)) - ); - - //update day 4 - app.set_block(BlockInfo { - height: 6, - time: Timestamp::from_seconds(24 * 60 * 60 * 4), - chain_id: "elys".to_string(), - }); - - app.execute_contract( - Addr::unchecked("user"), - trade_shield_address.clone(), - &trade_shield_msg::ExecuteMsg::CreateSpotOrder { - order_type: SpotOrderType::StopLoss, - order_source_denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - order_target_denom: "uelys".to_string(), - order_price: Some(OrderPrice { - base_denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - quote_denom: "uelys".to_string(), - rate: Decimal::one(), - }), - }, - &coins( - 100, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - ), - ) - .unwrap(); - - app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}) - .unwrap(); - - // update day 5 - app.set_block(BlockInfo { - height: 7, - time: Timestamp::from_seconds(24 * 60 * 60 * 5), - chain_id: "elys".to_string(), - }); - - app.execute_contract( - Addr::unchecked("user"), - trade_shield_address.clone(), - &trade_shield_msg::ExecuteMsg::CreateSpotOrder { - order_type: SpotOrderType::StopLoss, - order_source_denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - order_target_denom: "uelys".to_string(), - order_price: Some(OrderPrice { - base_denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - quote_denom: "uelys".to_string(), - rate: Decimal::one(), - }), - }, - &coins( - 100, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - ), - ) - .unwrap(); - - app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}) - .unwrap(); - - // update day 6 - app.set_block(BlockInfo { - height: 8, - time: Timestamp::from_seconds(24 * 60 * 60 * 6), - chain_id: "elys".to_string(), - }); - - app.execute_contract( - Addr::unchecked("user"), - trade_shield_address.clone(), - &trade_shield_msg::ExecuteMsg::CreateSpotOrder { - order_type: SpotOrderType::StopLoss, - order_source_denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - order_target_denom: "uelys".to_string(), - order_price: Some(OrderPrice { - base_denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - quote_denom: "uelys".to_string(), - rate: Decimal::one(), - }), - }, - &coins( - 100, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - ), - ) - .unwrap(); - - app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}) - .unwrap(); - - // update day 7 - app.set_block(BlockInfo { - height: 9, - time: Timestamp::from_seconds(24 * 60 * 60 * 7), - chain_id: "elys".to_string(), - }); - - app.execute_contract( - Addr::unchecked("user"), - trade_shield_address.clone(), - &trade_shield_msg::ExecuteMsg::CreateSpotOrder { - order_type: SpotOrderType::StopLoss, - order_source_denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - order_target_denom: "uelys".to_string(), - order_price: Some(OrderPrice { - base_denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - quote_denom: "uelys".to_string(), - rate: Decimal::one(), - }), - }, - &coins( - 100, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - ), - ) - .unwrap(); - - app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}) - .unwrap(); - - // check the all the snapshots recorded - let snapshots: Vec = app - .wrap() - .query_wasm_smart( - &addr, - &QueryMsg::UserSnapshots { - user_address: "user".to_string(), - }, - ) - .unwrap(); - - assert_eq!(snapshots.len(), 7); - - // update day 8 - app.set_block(BlockInfo { - height: 10, - time: Timestamp::from_seconds(24 * 60 * 60 * 8), - chain_id: "elys".to_string(), - }); - - app.execute_contract( - Addr::unchecked("user"), - trade_shield_address.clone(), - &trade_shield_msg::ExecuteMsg::CreateSpotOrder { - order_type: SpotOrderType::StopLoss, - order_source_denom: - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65".to_string(), - order_target_denom: "uelys".to_string(), - order_price: Some(OrderPrice { - base_denom: "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65" - .to_string(), - quote_denom: "uelys".to_string(), - rate: Decimal::one(), - }), - }, - &coins( - 100, - "ibc/2180E84E20F5679FCC760D8C165B60F42065DEF7F46A72B447CFF1B7DC6C0A65", - ), - ) - .unwrap(); - - app.wasm_sudo(addr.clone(), &SudoMsg::ClockEndBlock {}) - .unwrap(); - - // check the all the snapshots recorded - let snapshots: Vec = app - .wrap() - .query_wasm_smart( - &addr, - &QueryMsg::UserSnapshots { - user_address: "user".to_string(), - }, - ) - .unwrap(); - - assert_eq!(snapshots.len(), 7); - - assert_eq!( - snapshots[0].date, - Expiration::AtTime(Timestamp::from_seconds(24 * 60 * 60 * 2)) - ); - assert_eq!( - snapshots[1].date, - Expiration::AtTime(Timestamp::from_seconds(24 * 60 * 60 * 3)) - ); - assert_eq!( - snapshots[2].date, - Expiration::AtTime(Timestamp::from_seconds(24 * 60 * 60 * 4)) - ); - assert_eq!( - snapshots[3].date, - Expiration::AtTime(Timestamp::from_seconds(24 * 60 * 60 * 5)) - ); - assert_eq!( - snapshots[4].date, - Expiration::AtTime(Timestamp::from_seconds(24 * 60 * 60 * 6)) - ); - assert_eq!( - snapshots[5].date, - Expiration::AtTime(Timestamp::from_seconds(24 * 60 * 60 * 7)) - ); - assert_eq!( - snapshots[6].date, - Expiration::AtTime(Timestamp::from_seconds(24 * 60 * 60 * 8)) - ); - std::env::set_var("IS_TEST_ENV", "FALSE"); -}