From cbfd7a7e9b93945a4a7b7a684fc11337d2a71a2c Mon Sep 17 00:00:00 2001 From: jbernal87 Date: Fri, 2 Feb 2024 16:11:57 +0100 Subject: [PATCH 01/13] initial test query exchange param test query exchange spot market test query subaccount deposit test --- Cargo.lock | 98 ++++----- contracts/injective-cosmwasm-mock/Cargo.toml | 23 +- .../injective-cosmwasm-mock/src/contract.rs | 17 +- contracts/injective-cosmwasm-mock/src/lib.rs | 2 + contracts/injective-cosmwasm-mock/src/msg.rs | 2 + .../src/testing/mod.rs | 2 +- .../src/testing/query_exchange_test.rs | 196 ++++++++++++++++++ .../src/testing/query_spot_market_test.rs | 80 ------- .../injective-cosmwasm-mock/src/utils.rs | 153 +++++++++++--- 9 files changed, 398 insertions(+), 175 deletions(-) create mode 100644 contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs delete mode 100644 contracts/injective-cosmwasm-mock/src/testing/query_spot_market_test.rs diff --git a/Cargo.lock b/Cargo.lock index 2421ddf4..366282ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,7 +95,7 @@ dependencies = [ "injective-protobuf", "protobuf", "schemars", - "serde 1.0.194", + "serde 1.0.196", "thiserror", ] @@ -271,7 +271,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -402,7 +402,7 @@ dependencies = [ "getrandom", "k256 0.13.2", "rand_core 0.6.4", - "serde 1.0.194", + "serde 1.0.196", "serde_json 1.0.111", "subtle-encoding", "tendermint", @@ -441,7 +441,7 @@ checksum = "0df41ea55f2946b6b43579659eec048cc2f66e8c8e2e3652fc5e5e476f673856" dependencies = [ "cosmwasm-schema-derive", "schemars", - "serde 1.0.194", + "serde 1.0.196", "serde_json 1.0.111", "thiserror", ] @@ -472,7 +472,7 @@ dependencies = [ "forward_ref", "hex", "schemars", - "serde 1.0.194", + "serde 1.0.196", "serde-json-wasm 0.5.1", "sha2 0.10.8", "static_assertions 1.1.0", @@ -486,7 +486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd2b4ae72a03e8f56c85df59d172d51d2d7dc9cec6e2bc811e3fb60c588032a4" dependencies = [ "cosmwasm-std", - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -588,7 +588,7 @@ dependencies = [ "k256 0.11.6", "prost 0.9.0", "schemars", - "serde 1.0.194", + "serde 1.0.196", "thiserror", ] @@ -600,7 +600,7 @@ checksum = "d9b6f91c0b94481a3e9ef1ceb183c37d00764f8751e39b45fc09f4d9b970d469" dependencies = [ "cosmwasm-std", "schemars", - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -611,7 +611,7 @@ checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" dependencies = [ "cosmwasm-std", "schemars", - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -625,7 +625,7 @@ dependencies = [ "cw2 0.16.0", "schemars", "semver", - "serde 1.0.194", + "serde 1.0.196", "thiserror", ] @@ -640,7 +640,7 @@ dependencies = [ "cw2 1.1.2", "schemars", "semver", - "serde 1.0.194", + "serde 1.0.196", "thiserror", ] @@ -654,7 +654,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus 0.16.0", "schemars", - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -668,7 +668,7 @@ dependencies = [ "cw-storage-plus 1.2.0", "schemars", "semver", - "serde 1.0.194", + "serde 1.0.196", "thiserror", ] @@ -776,7 +776,7 @@ dependencies = [ "cw2 0.16.0", "injective-cosmwasm 0.2.21", "schemars", - "serde 1.0.194", + "serde 1.0.196", "thiserror", ] @@ -845,7 +845,7 @@ dependencies = [ "hashbrown 0.12.3", "hex", "rand_core 0.6.4", - "serde 1.0.194", + "serde 1.0.196", "sha2 0.9.9", "zeroize", ] @@ -968,7 +968,7 @@ dependencies = [ "ethbloom", "ethereum-types-serialize", "fixed-hash 0.3.2", - "serde 1.0.194", + "serde 1.0.196", "uint 0.5.0", ] @@ -978,7 +978,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1873d77b32bc1891a79dad925f2acbc318ee942b38b9110f9dbc5fbeffcea350" dependencies = [ - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -1311,7 +1311,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" dependencies = [ - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -1487,7 +1487,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58e3cae7e99c7ff5a995da2cf78dd0a5383740eda71d98cf7b1910c301ac69b8" dependencies = [ - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -1528,7 +1528,7 @@ dependencies = [ "hex", "injective-math 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "schemars", - "serde 1.0.194", + "serde 1.0.196", "serde_repr", "subtle-encoding", "tiny-keccak", @@ -1545,7 +1545,7 @@ dependencies = [ "hex", "injective-math 0.2.4", "schemars", - "serde 1.0.194", + "serde 1.0.196", "serde-json-wasm 1.0.0", "serde_repr", "serde_test", @@ -1565,7 +1565,7 @@ dependencies = [ "injective-std 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "injective-test-tube", "schemars", - "serde 1.0.194", + "serde 1.0.196", "thiserror", ] @@ -1578,7 +1578,7 @@ dependencies = [ "ethereum-types", "primitive-types", "schemars", - "serde 1.0.194", + "serde 1.0.196", "subtle-encoding", ] @@ -1592,7 +1592,7 @@ dependencies = [ "ethereum-types", "primitive-types", "schemars", - "serde 1.0.194", + "serde 1.0.196", "subtle-encoding", ] @@ -1607,7 +1607,7 @@ dependencies = [ "protobuf", "protobuf-codegen-pure", "schemars", - "serde 1.0.194", + "serde 1.0.196", "subtle-encoding", ] @@ -1621,7 +1621,7 @@ dependencies = [ "prost 0.11.9", "prost-types", "schemars", - "serde 1.0.194", + "serde 1.0.196", "serde-cw-value", ] @@ -1637,15 +1637,15 @@ dependencies = [ "prost 0.11.9", "prost-types", "schemars", - "serde 1.0.194", + "serde 1.0.196", "serde-cw-value", ] [[package]] name = "injective-test-tube" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f42f6affb7a2a6b2460d07c1bc4f470a1b0766ea46cf1d265a4ce7a2d3bd73" +checksum = "61cb772fd4c8c1da872b742633e73928cbf1cf0505a09ec8ad41934a4d7f10b4" dependencies = [ "base64 0.13.1", "bindgen", @@ -1655,7 +1655,7 @@ dependencies = [ "injective-cosmwasm 0.2.18", "injective-std 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "prost 0.11.9", - "serde 1.0.194", + "serde 1.0.196", "serde_json 1.0.111", "test-tube-inj", "thiserror", @@ -1673,7 +1673,7 @@ dependencies = [ "injective-math 0.2.4", "rand 0.4.6", "secp256k1", - "serde 1.0.194", + "serde 1.0.196", "tiny-keccak", ] @@ -2494,7 +2494,7 @@ dependencies = [ "dyn-clone", "enumset", "schemars_derive", - "serde 1.0.194", + "serde 1.0.196", "serde_json 1.0.111", ] @@ -2603,9 +2603,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.194" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] @@ -2616,7 +2616,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75d32da6b8ed758b7d850b6c3c08f1d7df51a4df3cb201296e63e34a78e99d4" dependencies = [ - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -2625,7 +2625,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137" dependencies = [ - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -2634,7 +2634,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83c37d03f3b0f6b5f77c11af1e7c772de1c9af83e50bef7bb6069601900ba67b" dependencies = [ - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -2643,14 +2643,14 @@ version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" dependencies = [ - "serde 1.0.194", + "serde 1.0.196", ] [[package]] name = "serde_derive" -version = "1.0.194" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", @@ -2686,7 +2686,7 @@ checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -2706,7 +2706,7 @@ version = "1.0.176" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a2f49ace1498612d14f7e0b8245519584db8299541dfe31a06374a828d620ab" dependencies = [ - "serde 1.0.194", + "serde 1.0.196", ] [[package]] @@ -2894,7 +2894,7 @@ dependencies = [ "prost 0.11.9", "prost-types", "ripemd", - "serde 1.0.194", + "serde 1.0.196", "serde_bytes", "serde_json 1.0.111", "serde_repr", @@ -2914,7 +2914,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71a72dbbea6dde12045d261f2c70c0de039125675e8a026c8d5ad34522756372" dependencies = [ "flex-error", - "serde 1.0.194", + "serde 1.0.196", "serde_json 1.0.111", "tendermint", "toml", @@ -2933,7 +2933,7 @@ dependencies = [ "num-traits", "prost 0.11.9", "prost-types", - "serde 1.0.194", + "serde 1.0.196", "serde_bytes", "subtle-encoding", "time", @@ -2957,7 +2957,7 @@ dependencies = [ "peg", "pin-project", "semver", - "serde 1.0.194", + "serde 1.0.196", "serde_bytes", "serde_json 1.0.111", "subtle", @@ -2993,7 +2993,7 @@ dependencies = [ "cosmrs", "cosmwasm-std", "prost 0.11.9", - "serde 1.0.194", + "serde 1.0.196", "serde_json 1.0.111", "tendermint-proto", "thiserror", @@ -3033,7 +3033,7 @@ checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "powerfmt", - "serde 1.0.194", + "serde 1.0.196", "time-core", "time-macros", ] @@ -3136,7 +3136,7 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ - "serde 1.0.194", + "serde 1.0.196", ] [[package]] diff --git a/contracts/injective-cosmwasm-mock/Cargo.toml b/contracts/injective-cosmwasm-mock/Cargo.toml index f1fc193b..2650677d 100644 --- a/contracts/injective-cosmwasm-mock/Cargo.toml +++ b/contracts/injective-cosmwasm-mock/Cargo.toml @@ -20,6 +20,7 @@ crate-type = [ "cdylib", "rlib" ] backtraces = [ "cosmwasm-std/backtraces" ] # use library feature to disable all instantiate/execute/query exports library = [ ] +integration = [ ] [package.metadata.scripts] optimize = """docker run --rm -v "$(pwd)":/code \ @@ -29,13 +30,15 @@ optimize = """docker run --rm -v "$(pwd)":/code \ """ [dependencies] -cosmwasm-std = { version = "1.5.0", features = [ "abort", "cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4", "iterator", "stargate" ] } -cw-storage-plus = "1.2.0" -cw2 = "0.16.0" -injective-cosmwasm = { path = "../../packages/injective-cosmwasm" } -injective-math = { path = "../../packages/injective-math" } -injective-std = { version = "0.1.5" } -injective-test-tube = "1.1.6" -schemars = "0.8.8" -serde = { version = "1.0.137", default-features = false, features = [ "derive" ] } -thiserror = { version = "1.0.31" } +cosmwasm-std = { version = "1.5.0", features = [ "abort", "cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4", "iterator", "stargate" ] } +cw-storage-plus = "1.2.0" +cw2 = "0.16.0" +injective-cosmwasm = { path = "../../packages/injective-cosmwasm" } +injective-math = { path = "../../packages/injective-math" } +schemars = { version ="0.8.16"} +serde = { version = "1.0.196", default-features = false, features = [ "derive" ] } +thiserror = { version = "1.0.56" } + +[dev-dependencies] +injective-test-tube = "1.1.7" +injective-std = { version = "0.1.5" } diff --git a/contracts/injective-cosmwasm-mock/src/contract.rs b/contracts/injective-cosmwasm-mock/src/contract.rs index b85d3e2c..07f52144 100644 --- a/contracts/injective-cosmwasm-mock/src/contract.rs +++ b/contracts/injective-cosmwasm-mock/src/contract.rs @@ -1,12 +1,13 @@ -#[cfg(not(feature = "library"))] -use cosmwasm_std::entry_point; +use crate::{ + error::ContractError, + msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, +}; use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; use cw2::set_contract_version; - use injective_cosmwasm::{create_deposit_msg, InjectiveMsgWrapper, InjectiveQuerier, InjectiveQueryWrapper}; -use crate::error::ContractError; -use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; const CONTRACT_NAME: &str = "crates.io:injective:dummy"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -33,9 +34,11 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { - let querier = InjectiveQuerier::new(&deps.querier); + let querier: InjectiveQuerier = InjectiveQuerier::new(&deps.querier); match msg { - QueryMsg::TestSpotMarketQuery { market_id } => to_json_binary(&querier.query_spot_market(&market_id)?.market), + QueryMsg::TestSpotMarketQuery { market_id } => to_json_binary(&querier.query_spot_market(&market_id)?), + QueryMsg::TestExchangeParamsQuery {} => to_json_binary(&querier.query_exchange_params()?), + QueryMsg::TestSubAccountDepositQuery { subaccount_id, denom } => to_json_binary(&querier.query_subaccount_deposit(&subaccount_id, &denom)?), } } diff --git a/contracts/injective-cosmwasm-mock/src/lib.rs b/contracts/injective-cosmwasm-mock/src/lib.rs index 39d14d52..213e21b9 100644 --- a/contracts/injective-cosmwasm-mock/src/lib.rs +++ b/contracts/injective-cosmwasm-mock/src/lib.rs @@ -3,6 +3,8 @@ mod error; pub mod msg; #[cfg(test)] mod testing; + +#[cfg(test)] pub mod utils; pub use crate::error::ContractError; diff --git a/contracts/injective-cosmwasm-mock/src/msg.rs b/contracts/injective-cosmwasm-mock/src/msg.rs index 523c43b5..62163e26 100644 --- a/contracts/injective-cosmwasm-mock/src/msg.rs +++ b/contracts/injective-cosmwasm-mock/src/msg.rs @@ -15,5 +15,7 @@ pub enum ExecuteMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { + TestExchangeParamsQuery {}, TestSpotMarketQuery { market_id: MarketId }, + TestSubAccountDepositQuery { subaccount_id: SubaccountId, denom: String }, } diff --git a/contracts/injective-cosmwasm-mock/src/testing/mod.rs b/contracts/injective-cosmwasm-mock/src/testing/mod.rs index 1cbb6c94..fb694d0c 100644 --- a/contracts/injective-cosmwasm-mock/src/testing/mod.rs +++ b/contracts/injective-cosmwasm-mock/src/testing/mod.rs @@ -1 +1 @@ -mod query_spot_market_test; +mod query_exchange_test; diff --git a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs new file mode 100644 index 00000000..dc31a400 --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs @@ -0,0 +1,196 @@ +use crate::{ + msg::{ExecuteMsg, QueryMsg}, + utils::{human_to_dec, human_to_proto, str_coin, Setup, BASE_DECIMALS, BASE_DENOM, QUOTE_DECIMALS, QUOTE_DENOM}, +}; + +use cosmwasm_std::Coin; +use injective_cosmwasm::{ExchangeParamsResponse, MarketId, SubaccountDepositResponse}; +use injective_math::{scale::Scaled, FPDecimal}; +use injective_std::types::injective::exchange::v1beta1::{ + Deposit, MsgDeposit, MsgInstantSpotMarketLaunch, QuerySpotMarketsRequest, QuerySubaccountDepositsRequest, +}; +use injective_test_tube::{injective_cosmwasm::SpotMarketResponse, Account, Exchange, Module, RunnerResult, Wasm}; + +pub fn dec_to_proto(val: FPDecimal) -> String { + val.scaled(18).to_string() +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_msg_deposit() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + let user = &env.users[0]; + + // Execute contract + let res = wasm.execute( + &env.contract_address, + &ExecuteMsg::TestDepositMsg { + subaccount_id: user.subaccount_id.clone(), + amount: Coin::new(100, "usdt"), + }, + &[Coin::new(100, "usdt")], + &user.account, + ); + assert!(res.is_ok(), "Execution failed with error: {:?}", res.unwrap_err()); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_exchange_params() { + let env = Setup::new(); + let wasm = Wasm::new(&env.app); + let res: ExchangeParamsResponse = wasm.query(&env.contract_address, &QueryMsg::TestExchangeParamsQuery {}).unwrap(); + + assert!(res.params.is_some()); + let params = res.params.unwrap(); + + let listing_fee_coin = str_coin("1000", BASE_DENOM, BASE_DECIMALS); + assert_eq!(params.spot_market_instant_listing_fee, listing_fee_coin); + assert_eq!(params.derivative_market_instant_listing_fee, listing_fee_coin); + assert_eq!(params.trading_rewards_vesting_duration, 604800); + assert_eq!(params.is_instant_derivative_market_launch_enabled, Some(true)); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_spot_market_no_market_on_exchange() { + let env = Setup::new(); + let wasm = Wasm::new(&env.app); + + // Query + let market_id = MarketId::new("0xd5a22be807011d5e42d5b77da3f417e22676efae494109cd01c242ad46630115").unwrap(); + let query_msg = QueryMsg::TestSpotMarketQuery { market_id }; + let res: RunnerResult = wasm.query(&env.contract_address, &query_msg); + assert_eq!(res, Ok(SpotMarketResponse { market: None })); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_spot_market() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + + // Instantiate spot market + let ticker = "INJ/USDT".to_string(); + let min_price_tick_size = FPDecimal::must_from_str("0.000000000000001"); + let min_quantity_tick_size = FPDecimal::must_from_str("1000000000000000"); + + exchange + .instant_spot_market_launch( + MsgInstantSpotMarketLaunch { + sender: env.signer.address(), + ticker: ticker.clone(), + base_denom: BASE_DENOM.to_string(), + quote_denom: QUOTE_DENOM.to_string(), + min_price_tick_size: dec_to_proto(min_price_tick_size), + min_quantity_tick_size: dec_to_proto(min_quantity_tick_size), + }, + &env.signer, + ) + .unwrap(); + + let spot_markets = exchange + .query_spot_markets(&QuerySpotMarketsRequest { + status: "Active".to_string(), + market_ids: vec![], + }) + .unwrap() + .markets; + + let market = spot_markets.iter().find(|m| m.ticker == ticker).unwrap(); + let spot_market_id = market.market_id.to_string(); + + // Query + let market_id = MarketId::new(spot_market_id.clone()).unwrap(); + let query_msg = QueryMsg::TestSpotMarketQuery { market_id }; + let res: SpotMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + + let response_market = res.market.unwrap(); + assert_eq!(response_market.market_id.as_str(), spot_market_id); + assert_eq!(response_market.ticker.as_str(), ticker); + assert_eq!(response_market.base_denom.as_str(), BASE_DENOM); + assert_eq!(response_market.quote_denom.as_str(), QUOTE_DENOM); + assert_eq!(response_market.min_price_tick_size.clone().to_string(), min_price_tick_size.to_string()); + assert_eq!(response_market.min_quantity_tick_size.to_string(), min_quantity_tick_size.to_string()); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_subaccount_deposit() { + let env = Setup::new(); + + let exchange = Exchange::new(&env.app); + let wasm = Wasm::new(&env.app); + + { + exchange + .deposit( + MsgDeposit { + sender: env.users[0].account.address(), + subaccount_id: env.users[0].subaccount_id.to_string(), + amount: Some(injective_std::types::cosmos::base::v1beta1::Coin { + amount: "10000000000000000000".to_string(), + denom: env.denoms["base"].clone(), + }), + }, + &env.users[0].account, + ) + .unwrap(); + } + + { + exchange + .deposit( + MsgDeposit { + sender: env.users[0].account.address(), + subaccount_id: env.users[0].subaccount_id.to_string(), + amount: Some(injective_std::types::cosmos::base::v1beta1::Coin { + amount: "100000000".to_string(), + denom: env.denoms["quote"].clone(), + }), + }, + &env.users[0].account, + ) + .unwrap(); + } + + let response = exchange + .query_subaccount_deposits(&QuerySubaccountDepositsRequest { + subaccount_id: env.users[0].subaccount_id.clone().to_string(), + subaccount: None, + }) + .unwrap(); + + assert_eq!( + response.deposits[&env.denoms["base"].clone()], + Deposit { + available_balance: human_to_proto("10.0", BASE_DECIMALS), + total_balance: human_to_proto("10.0", BASE_DECIMALS), + } + ); + assert_eq!( + response.deposits[&env.denoms["quote"].clone()], + Deposit { + available_balance: human_to_proto("100.0", QUOTE_DECIMALS), + total_balance: human_to_proto("100.0", QUOTE_DECIMALS), + } + ); + + let query_msg = QueryMsg::TestSubAccountDepositQuery { + subaccount_id: env.users[0].subaccount_id.clone(), + denom: BASE_DENOM.to_string(), + }; + let contract_response: SubaccountDepositResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(contract_response.deposits.total_balance, human_to_dec("10.0", BASE_DECIMALS)); + + let query_msg = QueryMsg::TestSubAccountDepositQuery { + subaccount_id: env.users[0].subaccount_id.clone(), + denom: QUOTE_DENOM.to_string(), + }; + let contract_response: SubaccountDepositResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(contract_response.deposits.available_balance, human_to_dec("100.0", QUOTE_DECIMALS)); +} diff --git a/contracts/injective-cosmwasm-mock/src/testing/query_spot_market_test.rs b/contracts/injective-cosmwasm-mock/src/testing/query_spot_market_test.rs deleted file mode 100644 index 1b42b787..00000000 --- a/contracts/injective-cosmwasm-mock/src/testing/query_spot_market_test.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::{ - msg::{ExecuteMsg, QueryMsg}, - utils::test_setup, -}; -use cosmwasm_std::{Addr, Coin}; -use injective_cosmwasm::{checked_address_to_subaccount_id, MarketId}; -use injective_math::{scale::Scaled, FPDecimal}; -use injective_std::types::injective::exchange::v1beta1::{MsgInstantSpotMarketLaunch, QuerySpotMarketsRequest}; -use injective_test_tube::{injective_cosmwasm::SpotMarketResponse, Account, Exchange, Module, Wasm}; - -pub const BASE_DENOM: &str = "inj"; -pub const QUOTE_DENOM: &str = "usdt"; - -pub fn dec_to_proto(val: FPDecimal) -> String { - val.scaled(18).to_string() -} - -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_msg_deposit() { - let (app, accs, contract_address) = test_setup(); - - let wasm = Wasm::new(&app); - let buyer = &accs[1]; - - // Execute contract - let buyer_subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(buyer.address()), 1u32); - let res = wasm.execute( - &contract_address, - &ExecuteMsg::TestDepositMsg { - subaccount_id: buyer_subaccount_id, - amount: Coin::new(100, "usdt"), - }, - &[Coin::new(100, "usdt")], - buyer, - ); - assert!(res.is_ok(), "Execution failed with error: {:?}", res.unwrap_err()); -} - -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_spot_market() { - let (app, accs, contract_address) = test_setup(); - let signer = &accs[2]; - let wasm = Wasm::new(&app); - let exchange = Exchange::new(&app); - - // Instantiate spot market - let ticker = "INJ/USDT".to_string(); - exchange - .instant_spot_market_launch( - MsgInstantSpotMarketLaunch { - sender: signer.address(), - ticker: ticker.clone(), - base_denom: BASE_DENOM.to_string(), - quote_denom: QUOTE_DENOM.to_string(), - min_price_tick_size: dec_to_proto(FPDecimal::must_from_str("0.000000000000001")), - min_quantity_tick_size: dec_to_proto(FPDecimal::must_from_str("1000000000000000")), - }, - signer, - ) - .unwrap(); - - let spot_markets = exchange - .query_spot_markets(&QuerySpotMarketsRequest { - status: "Active".to_string(), - market_ids: vec![], - }) - .unwrap() - .markets; - - let market = spot_markets.iter().find(|m| m.ticker == ticker).unwrap(); - let spot_market_id = market.market_id.to_string(); - - // Query - let market_id = MarketId::new(spot_market_id.clone()).unwrap(); - let query_msg = QueryMsg::TestSpotMarketQuery { market_id }; - let res: SpotMarketResponse = wasm.query(&contract_address, &query_msg).unwrap(); - assert_eq!(res.market.clone().unwrap().market_id.as_str(), spot_market_id.clone()); -} diff --git a/contracts/injective-cosmwasm-mock/src/utils.rs b/contracts/injective-cosmwasm-mock/src/utils.rs index e60f7b65..04a131e3 100644 --- a/contracts/injective-cosmwasm-mock/src/utils.rs +++ b/contracts/injective-cosmwasm-mock/src/utils.rs @@ -1,32 +1,129 @@ use crate::msg::InstantiateMsg; -use cosmwasm_std::Coin; +use cosmwasm_std::{coin, Addr, Coin}; +use injective_cosmwasm::{checked_address_to_subaccount_id, SubaccountId}; +use injective_math::{scale::Scaled, FPDecimal}; use injective_test_tube::{Account, InjectiveTestApp, Module, SigningAccount, Wasm}; +use std::collections::HashMap; -pub fn test_setup() -> (InjectiveTestApp, Vec, String) { - let app = InjectiveTestApp::new(); - let mut accs = app - .init_accounts(&[Coin::new(1_000_000_000_000, "usdt"), Coin::new(1_000_000_000_000, "inj")], 2) - .unwrap(); - accs.push(app.init_account(&[Coin::new(1_000_000_000_000_000_000_000_000_000, "inj")]).unwrap()); - - let seller = &accs[0]; - let buyer = &accs[1]; - - // `Wasm` is the module we use to interact with cosmwasm releated logic on the appchain - // it implements `Module` trait which you will see more later. - let wasm = Wasm::new(&app); - - // Load compiled wasm bytecode - let wasm_byte_code = std::fs::read("../../artifacts/injective_cosmwasm_mock-aarch64.wasm").unwrap(); - let code_id = wasm.store_code(&wasm_byte_code, None, buyer).unwrap().data.code_id; - - // Instantiate contract - let contract_address: String = wasm - .instantiate(code_id, &InstantiateMsg {}, Some(&seller.address()), Some("mock-contract"), &[], seller) - .unwrap() - .data - .address; - assert!(!contract_address.is_empty(), "Contract address is empty"); - - (app, accs, contract_address) +pub const EXCHANGE_DECIMALS: i32 = 18i32; +pub const BASE_DECIMALS: i32 = 18i32; +pub const ATOM_DECIMALS: i32 = 8i32; +pub const QUOTE_DECIMALS: i32 = 6i32; + +pub const ATOM_DENOM: &str = "atom"; +pub const BASE_DENOM: &str = "inj"; +pub const QUOTE_DENOM: &str = "usdt"; + +pub struct UserInfo { + pub account: SigningAccount, + pub subaccount_id: SubaccountId, +} +pub struct Setup { + pub app: InjectiveTestApp, + pub owner: SigningAccount, + pub signer: SigningAccount, + pub users: Vec, + pub denoms: HashMap, + pub contract_address: String, + pub code_id: u64, +} + +impl Setup { + pub fn new() -> Self { + let app = InjectiveTestApp::new(); + let wasm = Wasm::new(&app); + + let mut denoms = HashMap::new(); + denoms.insert("atom".to_string(), ATOM_DENOM.to_string()); + denoms.insert("quote".to_string(), QUOTE_DENOM.to_string()); + denoms.insert("base".to_string(), BASE_DENOM.to_string()); + + let signer = app.init_account(&[str_coin("1000000", BASE_DENOM, BASE_DECIMALS)]).unwrap(); + + let owner = app + .init_account(&[ + str_coin("1000000", ATOM_DENOM, ATOM_DECIMALS), + str_coin("1000000", BASE_DENOM, BASE_DECIMALS), + str_coin("1000000", QUOTE_DENOM, QUOTE_DECIMALS), + ]) + .unwrap(); + + let mut users: Vec = Vec::new(); + for _ in 0..10 { + let user = app + .init_account(&[ + str_coin("1000000", ATOM_DENOM, ATOM_DECIMALS), + str_coin("1000000", BASE_DENOM, BASE_DECIMALS), + str_coin("1000", QUOTE_DENOM, QUOTE_DECIMALS), + ]) + .unwrap(); + + let user_subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(user.address()), 1u32); + + users.push(UserInfo { + account: user, + subaccount_id: user_subaccount_id, + }); + } + + let wasm_byte_code = std::fs::read(wasm_file("injective_cosmwasm_mock".to_string())).unwrap(); + let code_id = wasm.store_code(&wasm_byte_code, None, &owner).unwrap().data.code_id; + + // Instantiate contract + let contract_address: String = wasm + .instantiate(code_id, &InstantiateMsg {}, Some(&owner.address()), Some("mock-contract"), &[], &owner) + .unwrap() + .data + .address; + + assert!(!contract_address.is_empty(), "Contract address is empty"); + + Self { + app, + owner, + signer, + users, + denoms, + contract_address, + code_id, + } + } +} + +impl Default for Setup { + fn default() -> Self { + Self::new() + } +} + +pub fn wasm_file(contract_name: String) -> String { + let snaked_name = contract_name.replace('-', "_"); + let arch = std::env::consts::ARCH; + + let target = format!("../../target/wasm32-unknown-unknown/release/{snaked_name}.wasm"); + + let artifacts_dir = std::env::var("ARTIFACTS_DIR_PATH").unwrap_or_else(|_| "artifacts".to_string()); + let arch_target = format!("../../{artifacts_dir}/{snaked_name}-{arch}.wasm"); + + if std::path::Path::new(&target).exists() { + target + } else if std::path::Path::new(&arch_target).exists() { + arch_target + } else { + format!("../../{artifacts_dir}/{snaked_name}.wasm") + } +} + +pub fn str_coin(human_amount: &str, denom: &str, decimals: i32) -> Coin { + let scaled_amount = human_to_dec(human_amount, decimals); + let as_int: u128 = scaled_amount.into(); + coin(as_int, denom) +} + +pub fn human_to_proto(raw_number: &str, decimals: i32) -> String { + FPDecimal::must_from_str(&raw_number.replace('_', "")).scaled(18 + decimals).to_string() +} + +pub fn human_to_dec(raw_number: &str, decimals: i32) -> FPDecimal { + FPDecimal::must_from_str(&raw_number.replace('_', "")).scaled(decimals) } From 4ce1d5233dbf7c778570a3a07b2fd48e033477c1 Mon Sep 17 00:00:00 2001 From: jbernal87 Date: Tue, 13 Feb 2024 16:29:50 +0100 Subject: [PATCH 02/13] derivative market query test --- Cargo.lock | 30 ++- contracts/injective-cosmwasm-mock/Cargo.toml | 2 + .../injective-cosmwasm-mock/src/contract.rs | 3 +- contracts/injective-cosmwasm-mock/src/msg.rs | 1 + .../src/testing/query_exchange_test.rs | 205 ++++++++++++------ .../injective-cosmwasm-mock/src/utils.rs | 163 +++++++++++++- 6 files changed, 331 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 366282ba..bea96f65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,7 +93,7 @@ dependencies = [ "injective-cosmwasm 0.2.21", "injective-math 0.2.4", "injective-protobuf", - "protobuf", + "protobuf 2.28.0", "schemars", "serde 1.0.196", "thiserror", @@ -1564,6 +1564,8 @@ dependencies = [ "injective-math 0.2.4", "injective-std 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "injective-test-tube", + "prost 0.11.9", + "protobuf 3.3.0", "schemars", "serde 1.0.196", "thiserror", @@ -1604,7 +1606,7 @@ dependencies = [ "cosmwasm-std", "ethereum-types", "num 0.4.1", - "protobuf", + "protobuf 2.28.0", "protobuf-codegen-pure", "schemars", "serde 1.0.196", @@ -2213,13 +2215,24 @@ dependencies = [ "bytes", ] +[[package]] +name = "protobuf" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b65f4a8ec18723a734e5dc09c173e0abf9690432da5340285d536edcb4dac190" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror", +] + [[package]] name = "protobuf-codegen" version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "033460afb75cf755fcfc16dfaed20b86468082a2ea24e05ac35ab4a099a017d6" dependencies = [ - "protobuf", + "protobuf 2.28.0", ] [[package]] @@ -2228,10 +2241,19 @@ version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a29399fc94bcd3eeaa951c715f7bea69409b2445356b00519740bcd6ddd865" dependencies = [ - "protobuf", + "protobuf 2.28.0", "protobuf-codegen", ] +[[package]] +name = "protobuf-support" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6872f4d4f4b98303239a2b5838f5bbbb77b01ffc892d627957f37a22d7cfe69c" +dependencies = [ + "thiserror", +] + [[package]] name = "quote" version = "1.0.35" diff --git a/contracts/injective-cosmwasm-mock/Cargo.toml b/contracts/injective-cosmwasm-mock/Cargo.toml index 2650677d..71c3868a 100644 --- a/contracts/injective-cosmwasm-mock/Cargo.toml +++ b/contracts/injective-cosmwasm-mock/Cargo.toml @@ -38,6 +38,8 @@ injective-math = { path = "../../packages/injective-math" } schemars = { version ="0.8.16"} serde = { version = "1.0.196", default-features = false, features = [ "derive" ] } thiserror = { version = "1.0.56" } +protobuf = "3.3.0" +prost = "0.11.9" [dev-dependencies] injective-test-tube = "1.1.7" diff --git a/contracts/injective-cosmwasm-mock/src/contract.rs b/contracts/injective-cosmwasm-mock/src/contract.rs index 07f52144..bb2c6964 100644 --- a/contracts/injective-cosmwasm-mock/src/contract.rs +++ b/contracts/injective-cosmwasm-mock/src/contract.rs @@ -37,8 +37,9 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Std let querier: InjectiveQuerier = InjectiveQuerier::new(&deps.querier); match msg { - QueryMsg::TestSpotMarketQuery { market_id } => to_json_binary(&querier.query_spot_market(&market_id)?), QueryMsg::TestExchangeParamsQuery {} => to_json_binary(&querier.query_exchange_params()?), QueryMsg::TestSubAccountDepositQuery { subaccount_id, denom } => to_json_binary(&querier.query_subaccount_deposit(&subaccount_id, &denom)?), + QueryMsg::TestSpotMarketQuery { market_id } => to_json_binary(&querier.query_spot_market(&market_id)?), + QueryMsg::TestDerivativeMarketQuery { market_id } => to_json_binary(&querier.query_derivative_market(&market_id)?), } } diff --git a/contracts/injective-cosmwasm-mock/src/msg.rs b/contracts/injective-cosmwasm-mock/src/msg.rs index 62163e26..95a690dc 100644 --- a/contracts/injective-cosmwasm-mock/src/msg.rs +++ b/contracts/injective-cosmwasm-mock/src/msg.rs @@ -17,5 +17,6 @@ pub enum ExecuteMsg { pub enum QueryMsg { TestExchangeParamsQuery {}, TestSpotMarketQuery { market_id: MarketId }, + TestDerivativeMarketQuery { market_id: MarketId }, TestSubAccountDepositQuery { subaccount_id: SubaccountId, denom: String }, } diff --git a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs index dc31a400..5801edbd 100644 --- a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs +++ b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs @@ -4,10 +4,11 @@ use crate::{ }; use cosmwasm_std::Coin; -use injective_cosmwasm::{ExchangeParamsResponse, MarketId, SubaccountDepositResponse}; +use injective_cosmwasm::{DerivativeMarketResponse, ExchangeParamsResponse, MarketId, SubaccountDepositResponse}; use injective_math::{scale::Scaled, FPDecimal}; use injective_std::types::injective::exchange::v1beta1::{ - Deposit, MsgDeposit, MsgInstantSpotMarketLaunch, QuerySpotMarketsRequest, QuerySubaccountDepositsRequest, + Deposit, MsgDeposit, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, QueryDerivativeMarketsRequest, QuerySpotMarketsRequest, + QuerySubaccountDepositsRequest, }; use injective_test_tube::{injective_cosmwasm::SpotMarketResponse, Account, Exchange, Module, RunnerResult, Wasm}; @@ -53,6 +54,82 @@ fn test_exchange_params() { assert_eq!(params.is_instant_derivative_market_launch_enabled, Some(true)); } +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_subaccount_deposit() { + let env = Setup::new(); + let exchange = Exchange::new(&env.app); + let wasm = Wasm::new(&env.app); + + { + exchange + .deposit( + MsgDeposit { + sender: env.users[0].account.address(), + subaccount_id: env.users[0].subaccount_id.to_string(), + amount: Some(injective_std::types::cosmos::base::v1beta1::Coin { + amount: "10000000000000000000".to_string(), + denom: env.denoms["base"].clone(), + }), + }, + &env.users[0].account, + ) + .unwrap(); + } + + { + exchange + .deposit( + MsgDeposit { + sender: env.users[0].account.address(), + subaccount_id: env.users[0].subaccount_id.to_string(), + amount: Some(injective_std::types::cosmos::base::v1beta1::Coin { + amount: "100000000".to_string(), + denom: env.denoms["quote"].clone(), + }), + }, + &env.users[0].account, + ) + .unwrap(); + } + + let response = exchange + .query_subaccount_deposits(&QuerySubaccountDepositsRequest { + subaccount_id: env.users[0].subaccount_id.clone().to_string(), + subaccount: None, + }) + .unwrap(); + + assert_eq!( + response.deposits[&env.denoms["base"].clone()], + Deposit { + available_balance: human_to_proto("10.0", BASE_DECIMALS), + total_balance: human_to_proto("10.0", BASE_DECIMALS), + } + ); + assert_eq!( + response.deposits[&env.denoms["quote"].clone()], + Deposit { + available_balance: human_to_proto("100.0", QUOTE_DECIMALS), + total_balance: human_to_proto("100.0", QUOTE_DECIMALS), + } + ); + + let query_msg = QueryMsg::TestSubAccountDepositQuery { + subaccount_id: env.users[0].subaccount_id.clone(), + denom: BASE_DENOM.to_string(), + }; + let contract_response: SubaccountDepositResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(contract_response.deposits.total_balance, human_to_dec("10.0", BASE_DECIMALS)); + + let query_msg = QueryMsg::TestSubAccountDepositQuery { + subaccount_id: env.users[0].subaccount_id.clone(), + denom: QUOTE_DENOM.to_string(), + }; + let contract_response: SubaccountDepositResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(contract_response.deposits.available_balance, human_to_dec("100.0", QUOTE_DECIMALS)); +} + #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_spot_market_no_market_on_exchange() { @@ -70,7 +147,6 @@ fn test_query_spot_market_no_market_on_exchange() { #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_spot_market() { let env = Setup::new(); - let wasm = Wasm::new(&env.app); let exchange = Exchange::new(&env.app); @@ -120,77 +196,74 @@ fn test_query_spot_market() { #[test] #[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_subaccount_deposit() { +fn test_query_derivative_market() { let env = Setup::new(); - - let exchange = Exchange::new(&env.app); let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); - { - exchange - .deposit( - MsgDeposit { - sender: env.users[0].account.address(), - subaccount_id: env.users[0].subaccount_id.to_string(), - amount: Some(injective_std::types::cosmos::base::v1beta1::Coin { - amount: "10000000000000000000".to_string(), - denom: env.denoms["base"].clone(), - }), - }, - &env.users[0].account, - ) - .unwrap(); - } + let ticker = "INJ/USDT".to_string(); + let initial_margin_ratio = FPDecimal::must_from_str("0.195"); + let maintenance_margin_ratio = FPDecimal::must_from_str("0.05"); + let min_price_tick_size = FPDecimal::must_from_str("1000000000000000000000"); + let min_quantity_tick_size = FPDecimal::must_from_str("1000000000000000"); + let quote_denom = QUOTE_DENOM.to_string(); + let maker_fee_rate = FPDecimal::ZERO; + let taker_fee_rate = FPDecimal::ZERO; - { - exchange - .deposit( - MsgDeposit { - sender: env.users[0].account.address(), - subaccount_id: env.users[0].subaccount_id.to_string(), - amount: Some(injective_std::types::cosmos::base::v1beta1::Coin { - amount: "100000000".to_string(), - denom: env.denoms["quote"].clone(), - }), - }, - &env.users[0].account, - ) - .unwrap(); - } + println!("{} {}", initial_margin_ratio, dec_to_proto(initial_margin_ratio)); + exchange + .instant_perpetual_market_launch( + MsgInstantPerpetualMarketLaunch { + sender: env.signer.address(), + ticker: ticker.to_owned(), + quote_denom: quote_denom.to_owned(), + oracle_base: BASE_DENOM.to_owned(), + oracle_quote: quote_denom.to_owned(), + oracle_scale_factor: 6u32, + oracle_type: 2i32, + maker_fee_rate: dec_to_proto(maker_fee_rate).to_string(), + taker_fee_rate: dec_to_proto(taker_fee_rate), + initial_margin_ratio: dec_to_proto(initial_margin_ratio), + maintenance_margin_ratio: dec_to_proto(maintenance_margin_ratio), + min_price_tick_size: dec_to_proto(min_price_tick_size), + min_quantity_tick_size: dec_to_proto(min_quantity_tick_size), + }, + &env.signer, + ) + .unwrap(); - let response = exchange - .query_subaccount_deposits(&QuerySubaccountDepositsRequest { - subaccount_id: env.users[0].subaccount_id.clone().to_string(), - subaccount: None, + let derivative_markets = exchange + .query_derivative_markets(&QueryDerivativeMarketsRequest { + status: "Active".to_string(), + market_ids: vec![], + with_mid_price_and_tob: false, }) + .unwrap() + .markets; + + let market = derivative_markets + .iter() + .filter(|m| m.market.is_some()) + .find(|m| m.market.as_ref().unwrap().ticker == ticker) + .unwrap() + .market + .as_ref() .unwrap(); - assert_eq!( - response.deposits[&env.denoms["base"].clone()], - Deposit { - available_balance: human_to_proto("10.0", BASE_DECIMALS), - total_balance: human_to_proto("10.0", BASE_DECIMALS), - } - ); - assert_eq!( - response.deposits[&env.denoms["quote"].clone()], - Deposit { - available_balance: human_to_proto("100.0", QUOTE_DECIMALS), - total_balance: human_to_proto("100.0", QUOTE_DECIMALS), - } - ); + let derivative_market_id = market.market_id.to_string(); - let query_msg = QueryMsg::TestSubAccountDepositQuery { - subaccount_id: env.users[0].subaccount_id.clone(), - denom: BASE_DENOM.to_string(), - }; - let contract_response: SubaccountDepositResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - assert_eq!(contract_response.deposits.total_balance, human_to_dec("10.0", BASE_DECIMALS)); + let market_id = MarketId::new(derivative_market_id.clone()).unwrap(); + let query_msg = QueryMsg::TestDerivativeMarketQuery { market_id }; + let res: DerivativeMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - let query_msg = QueryMsg::TestSubAccountDepositQuery { - subaccount_id: env.users[0].subaccount_id.clone(), - denom: QUOTE_DENOM.to_string(), - }; - let contract_response: SubaccountDepositResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - assert_eq!(contract_response.deposits.available_balance, human_to_dec("100.0", QUOTE_DECIMALS)); + let response_market = res.market.unwrap().market.unwrap(); + println!("{:?}", response_market); + assert_eq!(response_market.market_id.as_str(), derivative_market_id); + assert_eq!(response_market.ticker, ticker); + assert_eq!(response_market.quote_denom, quote_denom); + assert_eq!(response_market.min_price_tick_size, min_price_tick_size); + assert_eq!(response_market.min_quantity_tick_size, min_quantity_tick_size); + assert_eq!(response_market.maker_fee_rate, maker_fee_rate); + assert_eq!(response_market.taker_fee_rate, taker_fee_rate); + assert_eq!(response_market.initial_margin_ratio, initial_margin_ratio); } diff --git a/contracts/injective-cosmwasm-mock/src/utils.rs b/contracts/injective-cosmwasm-mock/src/utils.rs index 04a131e3..d4219ba2 100644 --- a/contracts/injective-cosmwasm-mock/src/utils.rs +++ b/contracts/injective-cosmwasm-mock/src/utils.rs @@ -2,8 +2,24 @@ use crate::msg::InstantiateMsg; use cosmwasm_std::{coin, Addr, Coin}; use injective_cosmwasm::{checked_address_to_subaccount_id, SubaccountId}; use injective_math::{scale::Scaled, FPDecimal}; -use injective_test_tube::{Account, InjectiveTestApp, Module, SigningAccount, Wasm}; -use std::collections::HashMap; +use injective_test_tube::{Account, Bank, Gov, InjectiveTestApp, Insurance, Module, Oracle, SigningAccount, Wasm}; + +use prost::Message; +use std::{collections::HashMap, str::FromStr}; + +use injective_std::types::injective::insurance::v1beta1::MsgCreateInsuranceFund; +use injective_std::types::injective::oracle::v1beta1::OracleType; +use injective_std::{ + shim::Any, + types::{ + cosmos::{ + bank::v1beta1::MsgSend, + base::v1beta1::Coin as BaseCoin, + gov::{v1::MsgVote, v1beta1::MsgSubmitProposal as MsgSubmitProposalV1Beta1}, + }, + injective::oracle::v1beta1::{GrantPriceFeederPrivilegeProposal, MsgRelayPriceFeedPrice}, + }, +}; pub const EXCHANGE_DECIMALS: i32 = 18i32; pub const BASE_DECIMALS: i32 = 18i32; @@ -22,6 +38,7 @@ pub struct Setup { pub app: InjectiveTestApp, pub owner: SigningAccount, pub signer: SigningAccount, + pub validator: SigningAccount, pub users: Vec, pub denoms: HashMap, pub contract_address: String, @@ -40,6 +57,8 @@ impl Setup { let signer = app.init_account(&[str_coin("1000000", BASE_DENOM, BASE_DECIMALS)]).unwrap(); + let validator = app.get_first_validator_signing_account(BASE_DENOM.to_string(), 1.2f64).unwrap(); + let owner = app .init_account(&[ str_coin("1000000", ATOM_DENOM, ATOM_DECIMALS), @@ -78,10 +97,32 @@ impl Setup { assert!(!contract_address.is_empty(), "Contract address is empty"); + send(&Bank::new(&app), "1000000000000000000000", BASE_DENOM, &owner, &validator); + + launch_insurance_fund( + &app, + &owner, + "INJ/USDT", + denoms["quote"].as_str(), + denoms["base"].as_str(), + denoms["quote"].as_str(), + OracleType::PriceFeed, + ); + + launch_price_feed_oracle( + &app, + &signer, + &validator, + denoms["base"].as_str(), + denoms["quote"].as_str(), + human_to_dec("10.01", BASE_DECIMALS).to_string(), + ); + Self { app, owner, signer, + validator, users, denoms, contract_address, @@ -127,3 +168,121 @@ pub fn human_to_proto(raw_number: &str, decimals: i32) -> String { pub fn human_to_dec(raw_number: &str, decimals: i32) -> FPDecimal { FPDecimal::must_from_str(&raw_number.replace('_', "")).scaled(decimals) } + +pub fn send(bank: &Bank, amount: &str, denom: &str, from: &SigningAccount, to: &SigningAccount) { + bank.send( + MsgSend { + from_address: from.address(), + to_address: to.address(), + amount: vec![BaseCoin { + amount: amount.to_string(), + denom: denom.to_string(), + }], + }, + from, + ) + .unwrap(); +} + +pub fn launch_price_feed_oracle( + app: &InjectiveTestApp, + signer: &SigningAccount, + validator: &SigningAccount, + base: &str, + quote: &str, + dec_price: String, +) { + let gov = Gov::new(app); + let oracle = Oracle::new(app); + + let mut buf = vec![]; + GrantPriceFeederPrivilegeProposal::encode( + &GrantPriceFeederPrivilegeProposal { + title: "test-proposal".to_string(), + description: "test-proposal".to_string(), + base: base.to_string(), + quote: quote.to_string(), + relayers: vec![signer.address()], + }, + &mut buf, + ) + .unwrap(); + + let res = gov + .submit_proposal_v1beta1( + MsgSubmitProposalV1Beta1 { + content: Some(Any { + type_url: "/injective.oracle.v1beta1.GrantPriceFeederPrivilegeProposal".to_string(), + value: buf, + }), + initial_deposit: vec![BaseCoin { + amount: "100000000000000000000".to_string(), + denom: "inj".to_string(), + }], + proposer: validator.address(), + }, + validator, + ) + .unwrap(); + + let proposal_id = res.events.iter().find(|e| e.ty == "submit_proposal").unwrap().attributes[0] + .value + .to_owned(); + + gov.vote( + MsgVote { + proposal_id: u64::from_str(&proposal_id).unwrap(), + voter: validator.address(), + option: 1i32, + metadata: "".to_string(), + }, + validator, + ) + .unwrap(); + + // NOTE: increase the block time in order to move past the voting period + app.increase_time(10u64); + + oracle + .relay_price_feed( + MsgRelayPriceFeedPrice { + sender: signer.address(), + base: vec![base.to_string()], + quote: vec![quote.to_string()], + price: vec![dec_price], // 1.2@18dp + }, + signer, + ) + .unwrap(); +} + +pub fn launch_insurance_fund( + app: &InjectiveTestApp, + signer: &SigningAccount, + ticker: &str, + quote: &str, + oracle_base: &str, + oracle_quote: &str, + oracle_type: OracleType, +) { + let insurance = Insurance::new(app); + + insurance + .create_insurance_fund( + MsgCreateInsuranceFund { + sender: signer.address(), + ticker: ticker.to_string(), + quote_denom: quote.to_string(), + oracle_base: oracle_base.to_string(), + oracle_quote: oracle_quote.to_string(), + oracle_type: oracle_type as i32, + expiry: -1i64, + initial_deposit: Some(BaseCoin { + amount: human_to_dec("1_000", QUOTE_DECIMALS).to_string(), + denom: quote.to_string(), + }), + }, + signer, + ) + .unwrap(); +} From e7c9ab270ea4d00e6a7318d4f32348b43f53702c Mon Sep 17 00:00:00 2001 From: jbernal87 Date: Thu, 22 Feb 2024 16:07:40 +0100 Subject: [PATCH 03/13] More quieries tests --- .../injective-cosmwasm-mock/src/contract.rs | 70 ++ contracts/injective-cosmwasm-mock/src/msg.rs | 90 +- .../src/testing/query_exchange_test.rs | 864 ++++++++++++++++-- .../injective-cosmwasm-mock/src/utils.rs | 238 ++++- packages/injective-cosmwasm/src/querier.rs | 13 +- 5 files changed, 1203 insertions(+), 72 deletions(-) diff --git a/contracts/injective-cosmwasm-mock/src/contract.rs b/contracts/injective-cosmwasm-mock/src/contract.rs index bb2c6964..470b98b1 100644 --- a/contracts/injective-cosmwasm-mock/src/contract.rs +++ b/contracts/injective-cosmwasm-mock/src/contract.rs @@ -41,5 +41,75 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Std QueryMsg::TestSubAccountDepositQuery { subaccount_id, denom } => to_json_binary(&querier.query_subaccount_deposit(&subaccount_id, &denom)?), QueryMsg::TestSpotMarketQuery { market_id } => to_json_binary(&querier.query_spot_market(&market_id)?), QueryMsg::TestDerivativeMarketQuery { market_id } => to_json_binary(&querier.query_derivative_market(&market_id)?), + QueryMsg::TestEffectiveSubaccountPosition { market_id, subaccount_id } => { + to_json_binary(&querier.query_effective_subaccount_position(&market_id, &subaccount_id)?) + } + QueryMsg::TestVanillaSubaccountPosition { market_id, subaccount_id } => { + to_json_binary(&querier.query_vanilla_subaccount_position(&market_id, &subaccount_id)?) + } + QueryMsg::TestTraderDerivativeOrders { market_id, subaccount_id } => { + to_json_binary(&querier.query_trader_derivative_orders(&market_id, &subaccount_id)?) + } + QueryMsg::TestTraderTransientSpotOrders { market_id, subaccount_id } => { + to_json_binary(&querier.query_trader_transient_spot_orders(&market_id, &subaccount_id)?) + } + QueryMsg::TestTraderTransientDerivativeOrders { market_id, subaccount_id } => { + to_json_binary(&querier.query_trader_transient_derivative_orders(&market_id, &subaccount_id)?) + } + QueryMsg::TestTraderSpotOrders { market_id, subaccount_id } => to_json_binary(&querier.query_trader_spot_orders(&market_id, &subaccount_id)?), + QueryMsg::TestSpotOrdersToCancelUpToAmount { + market_id, + subaccount_id, + base_amount, + quote_amount, + strategy, + reference_price, + } => to_json_binary(&querier.query_spot_orders_to_cancel_up_to_amount( + &market_id, + &subaccount_id, + base_amount, + quote_amount, + strategy, + reference_price, + )?), + QueryMsg::TestDerivativeOrdersToCancelUpToAmount { + market_id, + subaccount_id, + quote_amount, + strategy, + reference_price, + } => to_json_binary(&querier.query_derivative_orders_to_cancel_up_to_amount( + &market_id, + &subaccount_id, + quote_amount, + strategy, + reference_price, + )?), + QueryMsg::TestPerpetualMarketInfo { market_id } => to_json_binary(&querier.query_perpetual_market_info(&market_id)?), + QueryMsg::TestPerpetualMarketFunding { market_id } => to_json_binary(&querier.query_perpetual_market_funding(&market_id)?), + QueryMsg::TestMarketVolatility { + market_id, + trade_grouping_sec, + max_age, + include_raw_history, + include_metadata, + } => to_json_binary(&querier.query_market_volatility(&market_id, trade_grouping_sec, max_age, include_raw_history, include_metadata)?), + QueryMsg::TestDerivativeMarketMidPriceAndTob { market_id } => to_json_binary(&querier.query_derivative_market_mid_price_and_tob(&market_id)?), + QueryMsg::TestAggregateMarketVolume { market_id } => to_json_binary(&querier.query_aggregate_market_volume(&market_id)?), + QueryMsg::TestAggregateAccountVolume { account_id } => to_json_binary(&querier.query_aggregate_account_volume(&account_id)?), + QueryMsg::TestSpotMarketMidPriceAndTob { market_id } => to_json_binary(&querier.query_spot_market_mid_price_and_tob(&market_id)?), + QueryMsg::TestSpotMarketOrderbook { + market_id, + side, + limit_cumulative_quantity, + limit_cumulative_notional, + } => to_json_binary(&querier.query_spot_market_orderbook(&market_id, side, limit_cumulative_quantity, limit_cumulative_notional)?), + QueryMsg::TestDerivativeMarketOrderbook { + market_id, + limit_cumulative_notional, + } => to_json_binary(&querier.query_derivative_market_orderbook(&market_id, limit_cumulative_notional)?), + QueryMsg::TestMarketAtomicExecutionFeeMultiplier { market_id } => { + to_json_binary(&querier.query_market_atomic_execution_fee_multiplier(&market_id)?) + } } } diff --git a/contracts/injective-cosmwasm-mock/src/msg.rs b/contracts/injective-cosmwasm-mock/src/msg.rs index 95a690dc..a7378d3e 100644 --- a/contracts/injective-cosmwasm-mock/src/msg.rs +++ b/contracts/injective-cosmwasm-mock/src/msg.rs @@ -16,7 +16,91 @@ pub enum ExecuteMsg { #[serde(rename_all = "snake_case")] pub enum QueryMsg { TestExchangeParamsQuery {}, - TestSpotMarketQuery { market_id: MarketId }, - TestDerivativeMarketQuery { market_id: MarketId }, - TestSubAccountDepositQuery { subaccount_id: SubaccountId, denom: String }, + TestSpotMarketQuery { + market_id: MarketId, + }, + TestDerivativeMarketQuery { + market_id: MarketId, + }, + TestSubAccountDepositQuery { + subaccount_id: SubaccountId, + denom: String, + }, + TestEffectiveSubaccountPosition { + market_id: MarketId, + subaccount_id: SubaccountId, + }, + TestVanillaSubaccountPosition { + market_id: MarketId, + subaccount_id: SubaccountId, + }, + TestTraderDerivativeOrders { + market_id: MarketId, + subaccount_id: SubaccountId, + }, + TestTraderTransientSpotOrders { + market_id: MarketId, + subaccount_id: SubaccountId, + }, + TestTraderTransientDerivativeOrders { + market_id: MarketId, + subaccount_id: SubaccountId, + }, + TestTraderSpotOrders { + market_id: MarketId, + subaccount_id: SubaccountId, + }, + TestSpotOrdersToCancelUpToAmount { + market_id: MarketId, + subaccount_id: SubaccountId, + base_amount: FPDecimal, + quote_amount: FPDecimal, + strategy: CancellationStrategy, + reference_price: Option, + }, + TestDerivativeOrdersToCancelUpToAmount { + market_id: MarketId, + subaccount_id: SubaccountId, + quote_amount: FPDecimal, + strategy: CancellationStrategy, + reference_price: Option, + }, + TestPerpetualMarketInfo { + market_id: MarketId, + }, + TestPerpetualMarketFunding { + market_id: MarketId, + }, + TestMarketVolatility { + market_id: MarketId, + trade_grouping_sec: u64, + max_age: u64, + include_raw_history: bool, + include_metadata: bool, + }, + TestDerivativeMarketMidPriceAndTob { + market_id: MarketId, + }, + TestAggregateMarketVolume { + market_id: MarketId, + }, + TestAggregateAccountVolume { + account_id: String, + }, + TestSpotMarketMidPriceAndTob { + market_id: MarketId, + }, + TestSpotMarketOrderbook { + market_id: MarketId, + side: OrderSide, + limit_cumulative_quantity: Option, + limit_cumulative_notional: Option, + }, + TestDerivativeMarketOrderbook { + market_id: MarketId, + limit_cumulative_notional: FPDecimal, + }, + TestMarketAtomicExecutionFeeMultiplier { + market_id: MarketId, + }, } diff --git a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs index 5801edbd..3ca76e85 100644 --- a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs +++ b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs @@ -1,25 +1,23 @@ use crate::{ msg::{ExecuteMsg, QueryMsg}, - utils::{human_to_dec, human_to_proto, str_coin, Setup, BASE_DECIMALS, BASE_DENOM, QUOTE_DECIMALS, QUOTE_DENOM}, + utils::{ + dec_to_proto, get_spot_market_id, human_to_dec, human_to_proto, str_coin, Setup, BASE_DECIMALS, BASE_DENOM, QUOTE_DECIMALS, QUOTE_DENOM, + }, }; -use cosmwasm_std::Coin; -use injective_cosmwasm::{DerivativeMarketResponse, ExchangeParamsResponse, MarketId, SubaccountDepositResponse}; -use injective_math::{scale::Scaled, FPDecimal}; -use injective_std::types::injective::exchange::v1beta1::{ - Deposit, MsgDeposit, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, QueryDerivativeMarketsRequest, QuerySpotMarketsRequest, - QuerySubaccountDepositsRequest, -}; -use injective_test_tube::{injective_cosmwasm::SpotMarketResponse, Account, Exchange, Module, RunnerResult, Wasm}; - -pub fn dec_to_proto(val: FPDecimal) -> String { - val.scaled(18).to_string() -} +use crate::utils::{add_spot_orders, get_perpetual_market_id, scale_price_quantity_for_spot_market, ExchangeType, HumanOrder, scale_price_quantity_perp_market, add_derivative_orders}; +use cosmwasm_std::{Addr, Coin}; +use injective_cosmwasm::exchange::response::{QueryAggregateVolumeResponse, QueryOrderbookResponse}; +use injective_cosmwasm::{DerivativeMarketResponse, ExchangeParamsResponse, MarketId, MarketMidPriceAndTOBResponse, MarketVolatilityResponse, OrderSide, PerpetualMarketFundingResponse, PerpetualMarketInfoResponse, PriceLevel, QueryMarketAtomicExecutionFeeMultiplierResponse, SpotMarketResponse, SubaccountDepositResponse, SubaccountEffectivePositionInMarketResponse, SubaccountId, SubaccountPositionInMarketResponse, TraderDerivativeOrdersResponse, TraderSpotOrdersResponse, TrimmedDerivativeLimitOrder, TrimmedSpotLimitOrder}; +use injective_math::FPDecimal; +use injective_std::types::injective::exchange::v1beta1::{Deposit, DerivativeOrder, MsgCreateDerivativeLimitOrder, MsgCreateSpotLimitOrder, MsgDeposit, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, OrderInfo, OrderType, QueryAggregateMarketVolumeResponse, QuerySubaccountDepositsRequest, SpotOrder}; +use injective_test_tube::injective_cosmwasm::get_default_subaccount_id_for_checked_address; +use injective_test_tube::{Account, Exchange, Module, RunnerResult, Wasm}; #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_msg_deposit() { - let env = Setup::new(); + let env = Setup::new(ExchangeType::None); let wasm = Wasm::new(&env.app); let user = &env.users[0]; @@ -40,7 +38,7 @@ fn test_msg_deposit() { #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_exchange_params() { - let env = Setup::new(); + let env = Setup::new(ExchangeType::None); let wasm = Wasm::new(&env.app); let res: ExchangeParamsResponse = wasm.query(&env.contract_address, &QueryMsg::TestExchangeParamsQuery {}).unwrap(); @@ -57,7 +55,7 @@ fn test_exchange_params() { #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_subaccount_deposit() { - let env = Setup::new(); + let env = Setup::new(ExchangeType::None); let exchange = Exchange::new(&env.app); let wasm = Wasm::new(&env.app); @@ -133,7 +131,7 @@ fn test_query_subaccount_deposit() { #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_spot_market_no_market_on_exchange() { - let env = Setup::new(); + let env = Setup::new(ExchangeType::None); let wasm = Wasm::new(&env.app); // Query @@ -146,7 +144,7 @@ fn test_query_spot_market_no_market_on_exchange() { #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_spot_market() { - let env = Setup::new(); + let env = Setup::new(ExchangeType::None); let wasm = Wasm::new(&env.app); let exchange = Exchange::new(&env.app); @@ -169,16 +167,7 @@ fn test_query_spot_market() { ) .unwrap(); - let spot_markets = exchange - .query_spot_markets(&QuerySpotMarketsRequest { - status: "Active".to_string(), - market_ids: vec![], - }) - .unwrap() - .markets; - - let market = spot_markets.iter().find(|m| m.ticker == ticker).unwrap(); - let spot_market_id = market.market_id.to_string(); + let spot_market_id = get_spot_market_id(&exchange, ticker.to_owned()); // Query let market_id = MarketId::new(spot_market_id.clone()).unwrap(); @@ -197,20 +186,19 @@ fn test_query_spot_market() { #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_derivative_market() { - let env = Setup::new(); + let env = Setup::new(ExchangeType::None); let wasm = Wasm::new(&env.app); let exchange = Exchange::new(&env.app); let ticker = "INJ/USDT".to_string(); let initial_margin_ratio = FPDecimal::must_from_str("0.195"); let maintenance_margin_ratio = FPDecimal::must_from_str("0.05"); - let min_price_tick_size = FPDecimal::must_from_str("1000000000000000000000"); + let min_price_tick_size = FPDecimal::must_from_str("1000.0"); let min_quantity_tick_size = FPDecimal::must_from_str("1000000000000000"); let quote_denom = QUOTE_DENOM.to_string(); let maker_fee_rate = FPDecimal::ZERO; let taker_fee_rate = FPDecimal::ZERO; - println!("{} {}", initial_margin_ratio, dec_to_proto(initial_margin_ratio)); exchange .instant_perpetual_market_launch( MsgInstantPerpetualMarketLaunch { @@ -232,32 +220,13 @@ fn test_query_derivative_market() { ) .unwrap(); - let derivative_markets = exchange - .query_derivative_markets(&QueryDerivativeMarketsRequest { - status: "Active".to_string(), - market_ids: vec![], - with_mid_price_and_tob: false, - }) - .unwrap() - .markets; - - let market = derivative_markets - .iter() - .filter(|m| m.market.is_some()) - .find(|m| m.market.as_ref().unwrap().ticker == ticker) - .unwrap() - .market - .as_ref() - .unwrap(); - - let derivative_market_id = market.market_id.to_string(); + let derivative_market_id = get_perpetual_market_id(&exchange, ticker.to_owned()); let market_id = MarketId::new(derivative_market_id.clone()).unwrap(); let query_msg = QueryMsg::TestDerivativeMarketQuery { market_id }; let res: DerivativeMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); let response_market = res.market.unwrap().market.unwrap(); - println!("{:?}", response_market); assert_eq!(response_market.market_id.as_str(), derivative_market_id); assert_eq!(response_market.ticker, ticker); assert_eq!(response_market.quote_denom, quote_denom); @@ -267,3 +236,796 @@ fn test_query_derivative_market() { assert_eq!(response_market.taker_fee_rate, taker_fee_rate); assert_eq!(response_market.initial_margin_ratio, initial_margin_ratio); } + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_effective_subaccount_position() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + let market_id = env.market_id.unwrap(); + + let liquidity_orders: Vec = vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "1".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "10.1".to_string(), + quantity: "2".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "1".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.8".to_string(), + quantity: "2".to_string(), + order_type: OrderType::Buy, + }, + ]; + add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); + + let (price, quantity, margin) = + scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); + + let trader = &env.users[1]; + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) + .as_str() + .to_string(); + + exchange + .create_derivative_limit_order( + MsgCreateDerivativeLimitOrder { + sender: trader.account.address(), + order: Some(DerivativeOrder { + market_id: market_id.to_owned(), + order_info: Some(OrderInfo { + subaccount_id: subaccount_id.to_owned(), + fee_recipient: trader.account.address(), + price, + quantity, + }), + margin, + order_type: OrderType::Sell.into(), + trigger_price: "".to_string(), + }), + }, + &trader.account, + ) + .unwrap(); + + let query_msg = QueryMsg::TestEffectiveSubaccountPosition { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id.to_owned()).unwrap(), + }; + let res: SubaccountEffectivePositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert!(res.state.is_some()); + +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_vanilla_subaccount_position() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + let market_id = env.market_id.unwrap(); + + let liquidity_orders: Vec = vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "1".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "10.1".to_string(), + quantity: "2".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "1".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.8".to_string(), + quantity: "2".to_string(), + order_type: OrderType::Buy, + }, + ]; + add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); + + let (price, quantity, margin) = + scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); + + let trader = &env.users[1]; + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) + .as_str() + .to_string(); + + exchange + .create_derivative_limit_order( + MsgCreateDerivativeLimitOrder { + sender: trader.account.address(), + order: Some(DerivativeOrder { + market_id: market_id.to_owned(), + order_info: Some(OrderInfo { + subaccount_id: subaccount_id.to_owned(), + fee_recipient: trader.account.address(), + price, + quantity, + }), + margin, + order_type: OrderType::Sell.into(), + trigger_price: "".to_string(), + }), + }, + &trader.account, + ) + .unwrap(); + + let query_msg = QueryMsg::TestVanillaSubaccountPosition { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id.to_owned()).unwrap(), + }; + let res: SubaccountPositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert!(res.state.is_some()); + + let liquidity_orders: Vec = vec![ + HumanOrder { + price: "9.7".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Sell, + }, + ]; + add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); + + let res: SubaccountPositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + + +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_trader_spot_orders() { + let env = Setup::new(ExchangeType::Spot); + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + let market_id = env.market_id.unwrap(); + + { + let (price, quantity) = scale_price_quantity_for_spot_market("10.01", "5.1", &BASE_DECIMALS, "E_DECIMALS); + let trader = &env.users[0]; + + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) + .as_str() + .to_string(); + + exchange + .create_spot_limit_order( + MsgCreateSpotLimitOrder { + sender: trader.account.address(), + order: Some(SpotOrder { + market_id: market_id.clone(), + order_info: Some(OrderInfo { + subaccount_id: subaccount_id.to_owned(), + fee_recipient: trader.account.address(), + price, + quantity, + }), + order_type: OrderType::Sell.into(), + trigger_price: "".to_string(), + }), + }, + &trader.account, + ) + .unwrap(); + + let query_msg = QueryMsg::TestTraderSpotOrders { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id).unwrap(), + }; + let res: TraderSpotOrdersResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + let orders = res.orders.clone().unwrap(); + + assert_eq!(orders.len(), 1); + let expected_orders = TrimmedSpotLimitOrder { + price: human_to_dec("10.01", QUOTE_DECIMALS - BASE_DECIMALS), + quantity: human_to_dec("5.1", BASE_DECIMALS), + fillable: human_to_dec("5.1", BASE_DECIMALS), + isBuy: false, + order_hash: "".to_string(), + }; + assert_eq!(orders[0].price, expected_orders.price); + assert_eq!(orders[0].quantity, expected_orders.quantity); + assert_eq!(orders[0].fillable, expected_orders.fillable); + assert_eq!(orders[0].isBuy, expected_orders.isBuy); + } + + { + let (price, quantity) = scale_price_quantity_for_spot_market("9.90", "0.5", &BASE_DECIMALS, "E_DECIMALS); + let trader = &env.users[0]; + + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) + .as_str() + .to_string(); + + exchange + .create_spot_limit_order( + MsgCreateSpotLimitOrder { + sender: trader.account.address(), + order: Some(SpotOrder { + market_id: market_id.clone(), + order_info: Some(OrderInfo { + subaccount_id: subaccount_id.to_owned(), + fee_recipient: trader.account.address(), + price, + quantity, + }), + order_type: OrderType::Buy.into(), + trigger_price: "".to_string(), + }), + }, + &trader.account, + ) + .unwrap(); + + let query_msg = QueryMsg::TestTraderSpotOrders { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id).unwrap(), + }; + let res: TraderSpotOrdersResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + let orders = res.orders.clone().unwrap(); + + assert_eq!(orders.len(), 2); + let expected_order = TrimmedSpotLimitOrder { + price: human_to_dec("9.90", QUOTE_DECIMALS - BASE_DECIMALS), + quantity: human_to_dec("0.5", BASE_DECIMALS), + fillable: human_to_dec("0.5", BASE_DECIMALS), + isBuy: true, + order_hash: "".to_string(), + }; + assert_eq!(orders[0].price, expected_order.price); + assert_eq!(orders[0].quantity, expected_order.quantity); + assert_eq!(orders[0].fillable, expected_order.fillable); + assert_eq!(orders[0].isBuy, expected_order.isBuy); + } +} +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_trader_derivative_orders() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + let market_id = env.market_id.unwrap(); + + let (price, quantity, margin) = + scale_price_quantity_perp_market("10.1", "1", "2", "E_DECIMALS); + + let trader = &env.users[0]; + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) + .as_str() + .to_string(); + + exchange + .create_derivative_limit_order( + MsgCreateDerivativeLimitOrder { + sender: trader.account.address(), + order: Some(DerivativeOrder { + market_id: market_id.to_owned(), + order_info: Some(OrderInfo { + subaccount_id: subaccount_id.to_owned(), + fee_recipient: trader.account.address(), + price, + quantity, + }), + margin, + order_type: OrderType::Sell.into(), + trigger_price: "".to_string(), + }), + }, + &trader.account, + ) + .unwrap(); + + let query_msg = QueryMsg::TestTraderDerivativeOrders { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id).unwrap(), + }; + let res: TraderDerivativeOrdersResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert!(res.orders.is_some()); + + let orders = res.orders.clone().unwrap(); + assert_eq!(orders.len(), 1); + let expected_order = TrimmedDerivativeLimitOrder { + price: human_to_dec("10.1", QUOTE_DECIMALS), + quantity: FPDecimal::must_from_str("1"), + margin: human_to_dec("20.2", QUOTE_DECIMALS), + fillable: FPDecimal::must_from_str("1"), + isBuy: false, + order_hash: "".to_string(), + }; + assert_eq!(orders[0].price, expected_order.price); + assert_eq!(orders[0].quantity, expected_order.quantity); + assert_eq!(orders[0].fillable, expected_order.fillable); + assert_eq!(orders[0].isBuy, expected_order.isBuy); + assert_eq!(orders[0].margin, expected_order.margin); + +} + + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_spot_market_mid_price_and_tob() { + let env = Setup::new(ExchangeType::Spot); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + + let liquidity_orders: Vec = vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "10.1".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.8".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Buy, + }, + ]; + + add_spot_orders(&env.app, market_id.clone(), liquidity_orders); + + let query_msg = QueryMsg::TestSpotMarketMidPriceAndTob { + market_id: MarketId::new(market_id.clone()).unwrap(), + }; + + let res: MarketMidPriceAndTOBResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(res.mid_price, Some(human_to_dec("10", QUOTE_DECIMALS - BASE_DECIMALS))); + assert_eq!(res.best_buy_price, Some(human_to_dec("9.9", QUOTE_DECIMALS - BASE_DECIMALS))); + assert_eq!(res.best_sell_price, Some(human_to_dec("10.1", QUOTE_DECIMALS - BASE_DECIMALS))); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_spot_market_orderbook() { + let env = Setup::new(ExchangeType::Spot); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + + let liquidity_orders: Vec = vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "10.1".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.8".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Buy, + }, + ]; + + add_spot_orders(&env.app, market_id.clone(), liquidity_orders.clone()); + + let query_msg = QueryMsg::TestSpotMarketOrderbook { + market_id: MarketId::new(market_id.clone()).unwrap(), + side: OrderSide::Unspecified, + limit_cumulative_quantity: None, + limit_cumulative_notional: None, + }; + + let res: QueryOrderbookResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + let buys_price_level = res.buys_price_level; + let sells_price_level = res.sells_price_level; + assert_eq!(buys_price_level.len(), 2); + assert_eq!(sells_price_level.len(), 2); + assert_eq!( + buys_price_level[0], + PriceLevel { + p: human_to_dec(liquidity_orders[2].price.as_str(), QUOTE_DECIMALS - BASE_DECIMALS), + q: human_to_dec(liquidity_orders[2].quantity.as_str(), BASE_DECIMALS), + } + ); + assert_eq!( + buys_price_level[1], + PriceLevel { + p: human_to_dec(liquidity_orders[3].price.as_str(), QUOTE_DECIMALS - BASE_DECIMALS), + q: human_to_dec(liquidity_orders[3].quantity.as_str(), BASE_DECIMALS), + } + ); + + assert_eq!( + sells_price_level[0], + PriceLevel { + p: human_to_dec(liquidity_orders[1].price.as_str(), QUOTE_DECIMALS - BASE_DECIMALS), + q: human_to_dec(liquidity_orders[1].quantity.as_str(), BASE_DECIMALS), + } + ); + assert_eq!( + sells_price_level[1], + PriceLevel { + p: human_to_dec(liquidity_orders[0].price.as_str(), QUOTE_DECIMALS - BASE_DECIMALS), + q: human_to_dec(liquidity_orders[0].quantity.as_str(), BASE_DECIMALS), + } + ); +} + + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_perpetual_market_info() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + + let ticker = "INJ/USDT".to_string(); + let derivative_market_id = get_perpetual_market_id(&exchange, ticker.to_owned()); + let market_id = MarketId::new(derivative_market_id.clone()).unwrap(); + let query_msg = QueryMsg::TestPerpetualMarketInfo { + market_id: market_id.clone(), + }; + let res: PerpetualMarketInfoResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + + assert!(res.info.is_some()); + let market_info = res.info.clone().unwrap(); + assert_eq!(market_info.market_id, market_id); + assert_eq!(market_info.funding_interval, 3600i64); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_perpetual_market_funding() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + + let ticker = "INJ/USDT".to_string(); + let derivative_market_id = get_perpetual_market_id(&exchange, ticker.to_owned()); + let market_id = MarketId::new(derivative_market_id.clone()).unwrap(); + let query_msg = QueryMsg::TestPerpetualMarketFunding { + market_id: market_id.clone(), + }; + let res: PerpetualMarketFundingResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert!(res.state.is_some()); + let state = res.state.unwrap(); + assert_eq!(state.cumulative_funding, FPDecimal::ZERO); + assert_eq!(state.cumulative_price, FPDecimal::ZERO); + +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_market_volatility() { + let env = Setup::new(ExchangeType::Spot); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + + let liquidity_orders: Vec = vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "10.1".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.8".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Buy, + }, + ]; + + add_spot_orders(&env.app, market_id.clone(), liquidity_orders.clone()); + + let query_msg = QueryMsg::TestMarketVolatility { + market_id: MarketId::new(market_id.clone()).unwrap(), + trade_grouping_sec: 0, + max_age: 0, + include_raw_history: false, + include_metadata: true, + }; + + let res: MarketVolatilityResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(res.volatility, None); + + // consume liquidity + let new_orders: Vec = vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "15".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.0".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Sell, + }, + ]; + + add_spot_orders(&env.app, market_id.clone(), new_orders.clone()); + let res: MarketVolatilityResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(res.volatility, Some(FPDecimal::ZERO)); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_derivative_market_mid_price_and_tob() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + let market_id = env.market_id.unwrap(); + + let liquidity_orders: Vec = vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "1".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "10.1".to_string(), + quantity: "2".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "1".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.8".to_string(), + quantity: "2".to_string(), + order_type: OrderType::Buy, + }, + ]; + add_derivative_orders(&env.app, market_id.clone(), liquidity_orders, None); + + let query_msg = QueryMsg::TestDerivativeMarketMidPriceAndTob { + market_id: MarketId::new(market_id.clone()).unwrap(), + }; + + let res: MarketMidPriceAndTOBResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(res.mid_price, Some(human_to_dec("10", QUOTE_DECIMALS))); + assert_eq!(res.best_buy_price, Some(human_to_dec("9.9", QUOTE_DECIMALS))); + assert_eq!(res.best_sell_price, Some(human_to_dec("10.1", QUOTE_DECIMALS))); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_aggregate_market_volume() { + let env = Setup::new(ExchangeType::Spot); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + + let liquidity_orders: Vec = vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "10.1".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.8".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Buy, + }, + ]; + + add_spot_orders(&env.app, market_id.clone(), liquidity_orders); + + let query_msg = QueryMsg::TestAggregateMarketVolume { + market_id: MarketId::new(market_id.clone()).unwrap(), + }; + + let res: QueryAggregateMarketVolumeResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(res.volume.clone().unwrap().maker_volume, "0"); + assert_eq!(res.volume.clone().unwrap().taker_volume, "0"); + + // consume liquidity + let new_orders: Vec = vec![ + HumanOrder { + price: "10.1".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Sell, + }, + ]; + + add_spot_orders(&env.app, market_id.clone(), new_orders); + let res: QueryAggregateMarketVolumeResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(res.volume.clone().unwrap().maker_volume, "150500000"); + assert_eq!(res.volume.clone().unwrap().taker_volume, "150500000"); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_aggregate_account_volume() { + let env = Setup::new(ExchangeType::Spot); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + + let liquidity_orders: Vec = vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "10.1".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.8".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Buy, + }, + ]; + + add_spot_orders(&env.app, market_id.clone(), liquidity_orders); + + let query_msg = QueryMsg::TestAggregateAccountVolume { + account_id: env.users[0].account.address().to_string(), + }; + + let res: RunnerResult = wasm.query(&env.contract_address, &query_msg); + println!("{:?}", res); + assert_eq!(1,2); +} + + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_derivative_market_orderbook() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + let market_id = env.market_id.unwrap(); + + let liquidity_orders: Vec = vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "1".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "10.1".to_string(), + quantity: "2".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "1".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.8".to_string(), + quantity: "2".to_string(), + order_type: OrderType::Buy, + }, + ]; + add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); + + let query_msg = QueryMsg::TestDerivativeMarketOrderbook { + market_id: MarketId::new(market_id.clone()).unwrap(), + limit_cumulative_notional: FPDecimal::MAX , + }; + + let res: QueryOrderbookResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + let buys_price_level = res.buys_price_level; + let sells_price_level = res.sells_price_level; + assert_eq!(buys_price_level.len(), 2); + assert_eq!(sells_price_level.len(), 2); + assert_eq!( + buys_price_level[0], + PriceLevel { + p: human_to_dec(liquidity_orders[2].price.as_str(), QUOTE_DECIMALS), + q: FPDecimal::must_from_str(liquidity_orders[2].quantity.as_str()), + } + ); + assert_eq!( + buys_price_level[1], + PriceLevel { + p: human_to_dec(liquidity_orders[3].price.as_str(), QUOTE_DECIMALS), + q: FPDecimal::must_from_str(liquidity_orders[3].quantity.as_str()), + } + ); + + assert_eq!( + sells_price_level[0], + PriceLevel { + p: human_to_dec(liquidity_orders[1].price.as_str(), QUOTE_DECIMALS), + q: FPDecimal::must_from_str(liquidity_orders[1].quantity.as_str()), + } + ); + assert_eq!( + sells_price_level[1], + PriceLevel { + p: human_to_dec(liquidity_orders[0].price.as_str(), QUOTE_DECIMALS), + q: FPDecimal::must_from_str(liquidity_orders[0].quantity.as_str()), + } + ); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_market_atomic_execution_fee_multiplier() { + let env = Setup::new(ExchangeType::Spot); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + let query_msg = QueryMsg::TestMarketAtomicExecutionFeeMultiplier { + market_id: MarketId::new(market_id.clone()).unwrap(), + }; + let res: QueryMarketAtomicExecutionFeeMultiplierResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(res.multiplier, human_to_dec("0.0000025", QUOTE_DECIMALS)); +} + + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_spot_orders_to_cancel_up_to_amount() { + +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_derivative_orders_to_cancel_up_to_amount() {} + + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_trader_transient_spot_orders() {} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_trader_transient_derivative_orders() {} \ No newline at end of file diff --git a/contracts/injective-cosmwasm-mock/src/utils.rs b/contracts/injective-cosmwasm-mock/src/utils.rs index d4219ba2..d8a0d1d2 100644 --- a/contracts/injective-cosmwasm-mock/src/utils.rs +++ b/contracts/injective-cosmwasm-mock/src/utils.rs @@ -2,11 +2,12 @@ use crate::msg::InstantiateMsg; use cosmwasm_std::{coin, Addr, Coin}; use injective_cosmwasm::{checked_address_to_subaccount_id, SubaccountId}; use injective_math::{scale::Scaled, FPDecimal}; -use injective_test_tube::{Account, Bank, Gov, InjectiveTestApp, Insurance, Module, Oracle, SigningAccount, Wasm}; +use injective_test_tube::{Account, Bank, Exchange, Gov, InjectiveTestApp, Insurance, Module, Oracle, SigningAccount, Wasm}; use prost::Message; use std::{collections::HashMap, str::FromStr}; +use injective_std::types::injective::exchange::v1beta1::{DerivativeOrder, MsgCreateDerivativeLimitOrder, MsgCreateSpotLimitOrder, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, OrderInfo, OrderType, QueryDerivativeMarketsRequest, QuerySpotMarketsRequest, SpotOrder}; use injective_std::types::injective::insurance::v1beta1::MsgCreateInsuranceFund; use injective_std::types::injective::oracle::v1beta1::OracleType; use injective_std::{ @@ -20,6 +21,7 @@ use injective_std::{ injective::oracle::v1beta1::{GrantPriceFeederPrivilegeProposal, MsgRelayPriceFeedPrice}, }, }; +use injective_test_tube::injective_cosmwasm::get_default_subaccount_id_for_checked_address; pub const EXCHANGE_DECIMALS: i32 = 18i32; pub const BASE_DECIMALS: i32 = 18i32; @@ -43,12 +45,20 @@ pub struct Setup { pub denoms: HashMap, pub contract_address: String, pub code_id: u64, + pub market_id: Option, +} + +pub enum ExchangeType { + Spot, + Derivative, + None, } impl Setup { - pub fn new() -> Self { + pub fn new(exchange_type: ExchangeType) -> Self { let app = InjectiveTestApp::new(); let wasm = Wasm::new(&app); + let mut market_id = None; let mut denoms = HashMap::new(); denoms.insert("atom".to_string(), ATOM_DENOM.to_string()); @@ -118,6 +128,18 @@ impl Setup { human_to_dec("10.01", BASE_DECIMALS).to_string(), ); + match exchange_type { + ExchangeType::Spot => { + let exchange = Exchange::new(&app); + market_id = Some(launch_spot_market(&exchange, &owner, "INJ/USDT".to_string())); + } + ExchangeType::Derivative => { + let exchange = Exchange::new(&app); + market_id = Some(launch_perp_market(&exchange, &owner, "INJ/USDT".to_string())); + } + ExchangeType::None => {} + } + Self { app, owner, @@ -127,13 +149,14 @@ impl Setup { denoms, contract_address, code_id, + market_id, } } } impl Default for Setup { fn default() -> Self { - Self::new() + Self::new(ExchangeType::None) } } @@ -161,14 +184,6 @@ pub fn str_coin(human_amount: &str, denom: &str, decimals: i32) -> Coin { coin(as_int, denom) } -pub fn human_to_proto(raw_number: &str, decimals: i32) -> String { - FPDecimal::must_from_str(&raw_number.replace('_', "")).scaled(18 + decimals).to_string() -} - -pub fn human_to_dec(raw_number: &str, decimals: i32) -> FPDecimal { - FPDecimal::must_from_str(&raw_number.replace('_', "")).scaled(decimals) -} - pub fn send(bank: &Bank, amount: &str, denom: &str, from: &SigningAccount, to: &SigningAccount) { bank.send( MsgSend { @@ -286,3 +301,204 @@ pub fn launch_insurance_fund( ) .unwrap(); } + +pub fn launch_spot_market(exchange: &Exchange, signer: &SigningAccount, ticker: String) -> String { + exchange + .instant_spot_market_launch( + MsgInstantSpotMarketLaunch { + sender: signer.address(), + ticker: ticker.clone(), + base_denom: BASE_DENOM.to_string(), + quote_denom: QUOTE_DENOM.to_string(), + min_price_tick_size: dec_to_proto(FPDecimal::must_from_str("0.000000000000001")), + min_quantity_tick_size: dec_to_proto(FPDecimal::must_from_str("1000000000000000")), + }, + signer, + ) + .unwrap(); + + get_spot_market_id(exchange, ticker) +} + +pub fn get_spot_market_id(exchange: &Exchange, ticker: String) -> String { + let spot_markets = exchange + .query_spot_markets(&QuerySpotMarketsRequest { + status: "Active".to_string(), + market_ids: vec![], + }) + .unwrap() + .markets; + + let market = spot_markets.iter().find(|m| m.ticker == ticker).unwrap(); + market.market_id.to_string() +} + +pub fn launch_perp_market(exchange: &Exchange, signer: &SigningAccount, ticker: String) -> String { + exchange + .instant_perpetual_market_launch( + MsgInstantPerpetualMarketLaunch { + sender: signer.address(), + ticker: ticker.to_owned(), + quote_denom: "usdt".to_string(), + oracle_base: "inj".to_string(), + oracle_quote: "usdt".to_string(), + oracle_scale_factor: 6u32, + oracle_type: 2i32, + maker_fee_rate: "0".to_owned(), + taker_fee_rate: "0".to_owned(), + initial_margin_ratio: "195000000000000000".to_owned(), + maintenance_margin_ratio: "50000000000000000".to_owned(), + min_price_tick_size: "1000000000000000000000".to_owned(), + min_quantity_tick_size: "1000000000000000".to_owned(), + }, + signer, + ) + .unwrap(); + + get_perpetual_market_id(exchange, ticker) +} + +pub fn get_perpetual_market_id(exchange: &Exchange, ticker: String) -> String { + let perpetual_markets = exchange + .query_derivative_markets(&QueryDerivativeMarketsRequest { + status: "Active".to_string(), + market_ids: vec![], + with_mid_price_and_tob: false, + }) + .unwrap() + .markets; + + let market = perpetual_markets + .iter() + .filter(|m| m.market.is_some()) + .find(|m| m.market.as_ref().unwrap().ticker == ticker) + .unwrap() + .market + .as_ref() + .unwrap(); + + market.market_id.to_string() +} + +#[derive(Clone)] +pub struct HumanOrder { + pub price: String, + pub quantity: String, + pub order_type: OrderType, +} +pub fn add_spot_orders(app: &InjectiveTestApp, market_id: String, orders: Vec) { + let trader = app + .init_account(&[ + str_coin("1000000", BASE_DENOM, BASE_DECIMALS), + str_coin("1000000", QUOTE_DENOM, QUOTE_DECIMALS), + ]) + .unwrap(); + + let exchange = Exchange::new(app); + + for order in orders { + let (price, quantity) = scale_price_quantity_for_spot_market(order.price.as_str(), order.quantity.as_str(), &BASE_DECIMALS, "E_DECIMALS); + exchange + .create_spot_limit_order( + MsgCreateSpotLimitOrder { + sender: trader.address(), + order: Some(SpotOrder { + market_id: market_id.to_owned(), + order_info: Some(OrderInfo { + subaccount_id: get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.address())) + .as_str() + .to_string(), + fee_recipient: trader.address(), + price, + quantity, + }), + order_type: order.order_type.into(), + trigger_price: "".to_string(), + }), + }, + &trader, + ) + .unwrap(); + } +} + + +pub fn add_derivative_orders(app: &InjectiveTestApp, market_id: String, orders: Vec, margin:Option) { + + let trader = app + .init_account(&[ + str_coin("1000000", BASE_DENOM, BASE_DECIMALS), + str_coin("1000000", QUOTE_DENOM, QUOTE_DECIMALS), + ]) + .unwrap(); + + let exchange = Exchange::new(app); + let margin = margin.unwrap_or("2".into()); + + for order in orders { + let (price, quantity, order_margin) = scale_price_quantity_perp_market(order.price.as_str(), order.quantity.as_str(), &margin, "E_DECIMALS); + exchange + .create_derivative_limit_order( + MsgCreateDerivativeLimitOrder { + sender: trader.address(), + order: Some(DerivativeOrder { + market_id: market_id.to_owned(), + order_info: Some(OrderInfo { + subaccount_id: get_default_subaccount_id_for_checked_address( + &Addr::unchecked(trader.address()), + ) + .as_str() + .to_string(), + fee_recipient: trader.address(), + price, + quantity, + }), + margin: order_margin, + order_type: order.order_type.into(), + trigger_price: "".to_string(), + }), + }, + &trader, + ) + .unwrap(); + } +} + + +// Human Utils +pub fn human_to_proto(raw_number: &str, decimals: i32) -> String { + FPDecimal::must_from_str(&raw_number.replace('_', "")).scaled(18 + decimals).to_string() +} + +pub fn human_to_dec(raw_number: &str, decimals: i32) -> FPDecimal { + FPDecimal::must_from_str(&raw_number.replace('_', "")).scaled(decimals) +} + +pub fn dec_to_proto(val: FPDecimal) -> String { + val.scaled(18).to_string() +} + + + +pub fn scale_price_quantity_for_spot_market(price: &str, quantity: &str, base_decimals: &i32, quote_decimals: &i32) -> (String, String) { + let price_dec = FPDecimal::must_from_str(price.replace('_', "").as_str()); + let quantity_dec = FPDecimal::must_from_str(quantity.replace('_', "").as_str()); + + let scaled_price = price_dec.scaled(quote_decimals - base_decimals); + let scaled_quantity = quantity_dec.scaled(*base_decimals); + + (dec_to_proto(scaled_price), dec_to_proto(scaled_quantity)) +} + +pub fn scale_price_quantity_perp_market(price: &str, quantity: &str, margin_ratio: &str, quote_decimals: &i32) -> (String, String, String) { + let price_dec = FPDecimal::must_from_str(price.replace('_', "").as_str()); + let quantity_dec = FPDecimal::must_from_str(quantity.replace('_', "").as_str()); + let margin_ratio_dec = FPDecimal::must_from_str(margin_ratio.replace('_', "").as_str()); + + let scaled_price = price_dec.scaled(*quote_decimals); + let scaled_quantity = quantity_dec; + + let scaled_margin = (price_dec * quantity_dec * margin_ratio_dec).scaled(*quote_decimals); + + (dec_to_proto(scaled_price), dec_to_proto(scaled_quantity), dec_to_proto(scaled_margin)) +} diff --git a/packages/injective-cosmwasm/src/querier.rs b/packages/injective-cosmwasm/src/querier.rs index f0f0bd3d..e7af446a 100644 --- a/packages/injective-cosmwasm/src/querier.rs +++ b/packages/injective-cosmwasm/src/querier.rs @@ -9,10 +9,10 @@ use crate::exchange::{ order::OrderSide, response::{ DerivativeMarketResponse, ExchangeParamsResponse, MarketMidPriceAndTOBResponse, MarketVolatilityResponse, OracleVolatilityResponse, - PerpetualMarketFundingResponse, PerpetualMarketInfoResponse, QueryAggregateVolumeResponse, QueryDenomDecimalResponse, - QueryDenomDecimalsResponse, QueryMarketAtomicExecutionFeeMultiplierResponse, QueryOrderbookResponse, SpotMarketResponse, - SubaccountDepositResponse, SubaccountEffectivePositionInMarketResponse, SubaccountPositionInMarketResponse, TraderDerivativeOrdersResponse, - TraderSpotOrdersResponse, + PerpetualMarketFundingResponse, PerpetualMarketInfoResponse, QueryAggregateMarketVolumeResponse, QueryAggregateVolumeResponse, + QueryDenomDecimalResponse, QueryDenomDecimalsResponse, QueryMarketAtomicExecutionFeeMultiplierResponse, QueryOrderbookResponse, + SpotMarketResponse, SubaccountDepositResponse, SubaccountEffectivePositionInMarketResponse, SubaccountPositionInMarketResponse, + TraderDerivativeOrdersResponse, TraderSpotOrdersResponse, }, types::{MarketId, SubaccountId}, }; @@ -340,7 +340,7 @@ impl<'a> InjectiveQuerier<'a> { Ok(res) } - pub fn query_aggregate_market_volume + Clone>(&self, market_id: &'a T) -> StdResult { + pub fn query_aggregate_market_volume + Clone>(&self, market_id: &'a T) -> StdResult { let request = InjectiveQueryWrapper { route: InjectiveRoute::Exchange, query_data: InjectiveQuery::AggregateMarketVolume { @@ -348,7 +348,7 @@ impl<'a> InjectiveQuerier<'a> { }, }; - let res: QueryAggregateVolumeResponse = self.querier.query(&request.into())?; + let res: QueryAggregateMarketVolumeResponse = self.querier.query(&request.into())?; Ok(res) } @@ -359,7 +359,6 @@ impl<'a> InjectiveQuerier<'a> { account: account_id.clone().into(), }, }; - let res: QueryAggregateVolumeResponse = self.querier.query(&request.into())?; Ok(res) } From 088aa5c5a8a01da10040b84fcd968e9ada471a15 Mon Sep 17 00:00:00 2001 From: jbernal87 Date: Fri, 23 Feb 2024 12:15:45 +0100 Subject: [PATCH 04/13] fix missing file commmit --- contracts/injective-cosmwasm-mock/src/msg.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/injective-cosmwasm-mock/src/msg.rs b/contracts/injective-cosmwasm-mock/src/msg.rs index a7378d3e..511f37a6 100644 --- a/contracts/injective-cosmwasm-mock/src/msg.rs +++ b/contracts/injective-cosmwasm-mock/src/msg.rs @@ -1,5 +1,6 @@ use cosmwasm_std::Coin; -use injective_cosmwasm::{MarketId, SubaccountId}; +use injective_cosmwasm::{CancellationStrategy, MarketId, OrderSide, SubaccountId}; +use injective_math::FPDecimal; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; From 1efd426340eca78de162f9e3aa4f38b1635d8362 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Fri, 23 Feb 2024 11:59:59 +0000 Subject: [PATCH 05/13] turned aggregate_volume into an option as the proto is omit if empty --- .../src/testing/query_exchange_test.rs | 62 +++++++++---------- .../src/exchange/response.rs | 2 +- .../src/exchange_mock_querier.rs | 4 +- 3 files changed, 31 insertions(+), 37 deletions(-) diff --git a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs index 3ca76e85..4c4fb0c8 100644 --- a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs +++ b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs @@ -5,12 +5,23 @@ use crate::{ }, }; -use crate::utils::{add_spot_orders, get_perpetual_market_id, scale_price_quantity_for_spot_market, ExchangeType, HumanOrder, scale_price_quantity_perp_market, add_derivative_orders}; +use crate::utils::{ + add_derivative_orders, add_spot_orders, get_perpetual_market_id, scale_price_quantity_for_spot_market, scale_price_quantity_perp_market, + ExchangeType, HumanOrder, +}; use cosmwasm_std::{Addr, Coin}; use injective_cosmwasm::exchange::response::{QueryAggregateVolumeResponse, QueryOrderbookResponse}; -use injective_cosmwasm::{DerivativeMarketResponse, ExchangeParamsResponse, MarketId, MarketMidPriceAndTOBResponse, MarketVolatilityResponse, OrderSide, PerpetualMarketFundingResponse, PerpetualMarketInfoResponse, PriceLevel, QueryMarketAtomicExecutionFeeMultiplierResponse, SpotMarketResponse, SubaccountDepositResponse, SubaccountEffectivePositionInMarketResponse, SubaccountId, SubaccountPositionInMarketResponse, TraderDerivativeOrdersResponse, TraderSpotOrdersResponse, TrimmedDerivativeLimitOrder, TrimmedSpotLimitOrder}; +use injective_cosmwasm::{ + DerivativeMarketResponse, ExchangeParamsResponse, MarketId, MarketMidPriceAndTOBResponse, MarketVolatilityResponse, OrderSide, + PerpetualMarketFundingResponse, PerpetualMarketInfoResponse, PriceLevel, QueryMarketAtomicExecutionFeeMultiplierResponse, SpotMarketResponse, + SubaccountDepositResponse, SubaccountEffectivePositionInMarketResponse, SubaccountId, SubaccountPositionInMarketResponse, + TraderDerivativeOrdersResponse, TraderSpotOrdersResponse, TrimmedDerivativeLimitOrder, TrimmedSpotLimitOrder, +}; use injective_math::FPDecimal; -use injective_std::types::injective::exchange::v1beta1::{Deposit, DerivativeOrder, MsgCreateDerivativeLimitOrder, MsgCreateSpotLimitOrder, MsgDeposit, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, OrderInfo, OrderType, QueryAggregateMarketVolumeResponse, QuerySubaccountDepositsRequest, SpotOrder}; +use injective_std::types::injective::exchange::v1beta1::{ + Deposit, DerivativeOrder, MsgCreateDerivativeLimitOrder, MsgCreateSpotLimitOrder, MsgDeposit, MsgInstantPerpetualMarketLaunch, + MsgInstantSpotMarketLaunch, OrderInfo, OrderType, QueryAggregateMarketVolumeResponse, QuerySubaccountDepositsRequest, SpotOrder, +}; use injective_test_tube::injective_cosmwasm::get_default_subaccount_id_for_checked_address; use injective_test_tube::{Account, Exchange, Module, RunnerResult, Wasm}; @@ -269,8 +280,7 @@ fn test_query_effective_subaccount_position() { ]; add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); - let (price, quantity, margin) = - scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); + let (price, quantity, margin) = scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); let trader = &env.users[1]; let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) @@ -304,7 +314,6 @@ fn test_query_effective_subaccount_position() { }; let res: SubaccountEffectivePositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); assert!(res.state.is_some()); - } #[test] @@ -339,8 +348,7 @@ fn test_query_vanilla_subaccount_position() { ]; add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); - let (price, quantity, margin) = - scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); + let (price, quantity, margin) = scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); let trader = &env.users[1]; let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) @@ -375,18 +383,14 @@ fn test_query_vanilla_subaccount_position() { let res: SubaccountPositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); assert!(res.state.is_some()); - let liquidity_orders: Vec = vec![ - HumanOrder { - price: "9.7".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Sell, - }, - ]; + let liquidity_orders: Vec = vec![HumanOrder { + price: "9.7".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Sell, + }]; add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); let res: SubaccountPositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - - } #[test] @@ -503,8 +507,7 @@ fn test_query_trader_derivative_orders() { let exchange = Exchange::new(&env.app); let market_id = env.market_id.unwrap(); - let (price, quantity, margin) = - scale_price_quantity_perp_market("10.1", "1", "2", "E_DECIMALS); + let (price, quantity, margin) = scale_price_quantity_perp_market("10.1", "1", "2", "E_DECIMALS); let trader = &env.users[0]; let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) @@ -554,10 +557,8 @@ fn test_query_trader_derivative_orders() { assert_eq!(orders[0].fillable, expected_order.fillable); assert_eq!(orders[0].isBuy, expected_order.isBuy); assert_eq!(orders[0].margin, expected_order.margin); - } - #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_spot_market_mid_price_and_tob() { @@ -675,7 +676,6 @@ fn test_query_spot_market_orderbook() { ); } - #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_perpetual_market_info() { @@ -715,7 +715,6 @@ fn test_query_perpetual_market_funding() { let state = res.state.unwrap(); assert_eq!(state.cumulative_funding, FPDecimal::ZERO); assert_eq!(state.cumulative_price, FPDecimal::ZERO); - } #[test] @@ -915,15 +914,14 @@ fn test_query_aggregate_account_volume() { add_spot_orders(&env.app, market_id.clone(), liquidity_orders); let query_msg = QueryMsg::TestAggregateAccountVolume { - account_id: env.users[0].account.address().to_string(), + account_id: env.users[0].subaccount_id.to_string(), }; - let res: RunnerResult = wasm.query(&env.contract_address, &query_msg); + let res: RunnerResult = wasm.query(&env.contract_address, &query_msg); println!("{:?}", res); - assert_eq!(1,2); + assert_eq!(1, 2); } - #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_derivative_market_orderbook() { @@ -958,7 +956,7 @@ fn test_query_derivative_market_orderbook() { let query_msg = QueryMsg::TestDerivativeMarketOrderbook { market_id: MarketId::new(market_id.clone()).unwrap(), - limit_cumulative_notional: FPDecimal::MAX , + limit_cumulative_notional: FPDecimal::MAX, }; let res: QueryOrderbookResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); @@ -1010,22 +1008,18 @@ fn test_query_market_atomic_execution_fee_multiplier() { assert_eq!(res.multiplier, human_to_dec("0.0000025", QUOTE_DECIMALS)); } - #[test] #[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_spot_orders_to_cancel_up_to_amount() { - -} +fn test_query_spot_orders_to_cancel_up_to_amount() {} #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_derivative_orders_to_cancel_up_to_amount() {} - #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_trader_transient_spot_orders() {} #[test] #[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_trader_transient_derivative_orders() {} \ No newline at end of file +fn test_query_trader_transient_derivative_orders() {} diff --git a/packages/injective-cosmwasm/src/exchange/response.rs b/packages/injective-cosmwasm/src/exchange/response.rs index 53af1c15..d1135ea2 100644 --- a/packages/injective-cosmwasm/src/exchange/response.rs +++ b/packages/injective-cosmwasm/src/exchange/response.rs @@ -99,7 +99,7 @@ pub struct QueryOrderbookResponse { /// Response to query for aggregate volumes of a given account/subaccount - divided by markets #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct QueryAggregateVolumeResponse { - pub aggregate_volumes: Vec, + pub aggregate_volumes: Option>, } /// Response to query for aggregate volume for a given market diff --git a/packages/injective-cosmwasm/src/exchange_mock_querier.rs b/packages/injective-cosmwasm/src/exchange_mock_querier.rs index 738ddea6..bc7d5a2b 100644 --- a/packages/injective-cosmwasm/src/exchange_mock_querier.rs +++ b/packages/injective-cosmwasm/src/exchange_mock_querier.rs @@ -191,7 +191,7 @@ fn default_aggregate_market_volume_handler() -> QuerierResult { fn default_aggregate_account_volume_handler() -> QuerierResult { let response = QueryAggregateVolumeResponse { - aggregate_volumes: vec![ + aggregate_volumes: Some(vec![ MarketVolume { market_id: MarketId::unchecked("market_id_1"), volume: VolumeByType { @@ -206,7 +206,7 @@ fn default_aggregate_account_volume_handler() -> QuerierResult { taker_volume: FPDecimal::from(25000000u128), }, }, - ], + ]), }; SystemResult::Ok(ContractResult::from(to_json_binary(&response))) } From a443eba32c1998c2291db26412e69fca63e851c9 Mon Sep 17 00:00:00 2001 From: jbernal87 Date: Fri, 23 Feb 2024 17:49:21 +0100 Subject: [PATCH 06/13] fix volume test errors. Some refactors --- .../src/testing/query_exchange_test.rs | 447 ++++-------------- .../injective-cosmwasm-mock/src/utils.rs | 180 ++++--- packages/injective-protobuf/src/proto/mod.rs | 4 +- 3 files changed, 212 insertions(+), 419 deletions(-) diff --git a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs index 4c4fb0c8..83db3caa 100644 --- a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs +++ b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs @@ -1,26 +1,27 @@ use crate::{ msg::{ExecuteMsg, QueryMsg}, utils::{ - dec_to_proto, get_spot_market_id, human_to_dec, human_to_proto, str_coin, Setup, BASE_DECIMALS, BASE_DENOM, QUOTE_DECIMALS, QUOTE_DENOM, + add_derivative_order_as, add_derivative_orders, add_perp_initial_liquidity, add_spot_initial_liquidity, add_spot_order_as, add_spot_orders, + dec_to_proto, get_initial_liquidity_orders_vector, get_initial_perp_liquidity_orders_vector, get_perpetual_market_id, get_spot_market_id, + human_to_dec, human_to_proto, scale_price_quantity_for_spot_market, scale_price_quantity_perp_market, str_coin, ExchangeType, HumanOrder, + Setup, BASE_DECIMALS, BASE_DENOM, QUOTE_DECIMALS, QUOTE_DENOM, }, }; -use crate::utils::{ - add_derivative_orders, add_spot_orders, get_perpetual_market_id, scale_price_quantity_for_spot_market, scale_price_quantity_perp_market, - ExchangeType, HumanOrder, -}; use cosmwasm_std::{Addr, Coin}; -use injective_cosmwasm::exchange::response::{QueryAggregateVolumeResponse, QueryOrderbookResponse}; +use injective_cosmwasm::exchange::response::QueryOrderbookResponse; +use injective_cosmwasm::exchange::types::VolumeByType; use injective_cosmwasm::{ - DerivativeMarketResponse, ExchangeParamsResponse, MarketId, MarketMidPriceAndTOBResponse, MarketVolatilityResponse, OrderSide, - PerpetualMarketFundingResponse, PerpetualMarketInfoResponse, PriceLevel, QueryMarketAtomicExecutionFeeMultiplierResponse, SpotMarketResponse, - SubaccountDepositResponse, SubaccountEffectivePositionInMarketResponse, SubaccountId, SubaccountPositionInMarketResponse, - TraderDerivativeOrdersResponse, TraderSpotOrdersResponse, TrimmedDerivativeLimitOrder, TrimmedSpotLimitOrder, + checked_address_to_subaccount_id, DerivativeMarketResponse, ExchangeParamsResponse, MarketId, MarketMidPriceAndTOBResponse, + MarketVolatilityResponse, OrderSide, PerpetualMarketFundingResponse, PerpetualMarketInfoResponse, PriceLevel, QueryAggregateVolumeResponse, + QueryMarketAtomicExecutionFeeMultiplierResponse, SpotMarketResponse, SubaccountDepositResponse, SubaccountEffectivePositionInMarketResponse, + SubaccountId, SubaccountPositionInMarketResponse, TraderDerivativeOrdersResponse, TraderSpotOrdersResponse, TrimmedDerivativeLimitOrder, + TrimmedSpotLimitOrder, }; use injective_math::FPDecimal; use injective_std::types::injective::exchange::v1beta1::{ - Deposit, DerivativeOrder, MsgCreateDerivativeLimitOrder, MsgCreateSpotLimitOrder, MsgDeposit, MsgInstantPerpetualMarketLaunch, - MsgInstantSpotMarketLaunch, OrderInfo, OrderType, QueryAggregateMarketVolumeResponse, QuerySubaccountDepositsRequest, SpotOrder, + Deposit, MsgDeposit, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, OrderType, QueryAggregateMarketVolumeResponse, + QuerySubaccountDepositsRequest, }; use injective_test_tube::injective_cosmwasm::get_default_subaccount_id_for_checked_address; use injective_test_tube::{Account, Exchange, Module, RunnerResult, Wasm}; @@ -33,11 +34,12 @@ fn test_msg_deposit() { let wasm = Wasm::new(&env.app); let user = &env.users[0]; + let subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(user.account.address()), 1u32); // Execute contract let res = wasm.execute( &env.contract_address, &ExecuteMsg::TestDepositMsg { - subaccount_id: user.subaccount_id.clone(), + subaccount_id: subaccount_id.clone(), amount: Coin::new(100, "usdt"), }, &[Coin::new(100, "usdt")], @@ -70,12 +72,14 @@ fn test_query_subaccount_deposit() { let exchange = Exchange::new(&env.app); let wasm = Wasm::new(&env.app); + let subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(env.users[0].account.address()), 1u32); + { exchange .deposit( MsgDeposit { sender: env.users[0].account.address(), - subaccount_id: env.users[0].subaccount_id.to_string(), + subaccount_id: subaccount_id.to_string(), amount: Some(injective_std::types::cosmos::base::v1beta1::Coin { amount: "10000000000000000000".to_string(), denom: env.denoms["base"].clone(), @@ -91,7 +95,7 @@ fn test_query_subaccount_deposit() { .deposit( MsgDeposit { sender: env.users[0].account.address(), - subaccount_id: env.users[0].subaccount_id.to_string(), + subaccount_id: subaccount_id.to_string(), amount: Some(injective_std::types::cosmos::base::v1beta1::Coin { amount: "100000000".to_string(), denom: env.denoms["quote"].clone(), @@ -104,7 +108,7 @@ fn test_query_subaccount_deposit() { let response = exchange .query_subaccount_deposits(&QuerySubaccountDepositsRequest { - subaccount_id: env.users[0].subaccount_id.clone().to_string(), + subaccount_id: subaccount_id.to_string(), subaccount: None, }) .unwrap(); @@ -125,14 +129,14 @@ fn test_query_subaccount_deposit() { ); let query_msg = QueryMsg::TestSubAccountDepositQuery { - subaccount_id: env.users[0].subaccount_id.clone(), + subaccount_id: subaccount_id.clone(), denom: BASE_DENOM.to_string(), }; let contract_response: SubaccountDepositResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); assert_eq!(contract_response.deposits.total_balance, human_to_dec("10.0", BASE_DECIMALS)); let query_msg = QueryMsg::TestSubAccountDepositQuery { - subaccount_id: env.users[0].subaccount_id.clone(), + subaccount_id: subaccount_id.clone(), denom: QUOTE_DENOM.to_string(), }; let contract_response: SubaccountDepositResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); @@ -253,60 +257,25 @@ fn test_query_derivative_market() { fn test_query_effective_subaccount_position() { let env = Setup::new(ExchangeType::Derivative); let wasm = Wasm::new(&env.app); - let exchange = Exchange::new(&env.app); let market_id = env.market_id.unwrap(); - let liquidity_orders: Vec = vec![ - HumanOrder { - price: "10.2".to_string(), - quantity: "1".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "10.1".to_string(), - quantity: "2".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "9.9".to_string(), - quantity: "1".to_string(), - order_type: OrderType::Buy, - }, - HumanOrder { - price: "9.8".to_string(), - quantity: "2".to_string(), - order_type: OrderType::Buy, - }, - ]; - add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); + add_perp_initial_liquidity(&env.app, market_id.clone()); let (price, quantity, margin) = scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); - let trader = &env.users[1]; - let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(env.users[1].account.address())) .as_str() .to_string(); - exchange - .create_derivative_limit_order( - MsgCreateDerivativeLimitOrder { - sender: trader.account.address(), - order: Some(DerivativeOrder { - market_id: market_id.to_owned(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.to_owned(), - fee_recipient: trader.account.address(), - price, - quantity, - }), - margin, - order_type: OrderType::Sell.into(), - trigger_price: "".to_string(), - }), - }, - &trader.account, - ) - .unwrap(); + add_derivative_order_as( + &env.app, + market_id.to_owned(), + &env.users[1].account, + price, + quantity, + OrderType::Sell, + margin, + ); let query_msg = QueryMsg::TestEffectiveSubaccountPosition { market_id: MarketId::new(market_id.clone()).unwrap(), @@ -321,32 +290,9 @@ fn test_query_effective_subaccount_position() { fn test_query_vanilla_subaccount_position() { let env = Setup::new(ExchangeType::Derivative); let wasm = Wasm::new(&env.app); - let exchange = Exchange::new(&env.app); let market_id = env.market_id.unwrap(); - let liquidity_orders: Vec = vec![ - HumanOrder { - price: "10.2".to_string(), - quantity: "1".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "10.1".to_string(), - quantity: "2".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "9.9".to_string(), - quantity: "1".to_string(), - order_type: OrderType::Buy, - }, - HumanOrder { - price: "9.8".to_string(), - quantity: "2".to_string(), - order_type: OrderType::Buy, - }, - ]; - add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); + add_perp_initial_liquidity(&env.app, market_id.clone()); let (price, quantity, margin) = scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); @@ -355,26 +301,15 @@ fn test_query_vanilla_subaccount_position() { .as_str() .to_string(); - exchange - .create_derivative_limit_order( - MsgCreateDerivativeLimitOrder { - sender: trader.account.address(), - order: Some(DerivativeOrder { - market_id: market_id.to_owned(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.to_owned(), - fee_recipient: trader.account.address(), - price, - quantity, - }), - margin, - order_type: OrderType::Sell.into(), - trigger_price: "".to_string(), - }), - }, - &trader.account, - ) - .unwrap(); + add_derivative_order_as( + &env.app, + market_id.to_owned(), + &env.users[1].account, + price, + quantity, + OrderType::Sell, + margin, + ); let query_msg = QueryMsg::TestVanillaSubaccountPosition { market_id: MarketId::new(market_id.clone()).unwrap(), @@ -390,7 +325,7 @@ fn test_query_vanilla_subaccount_position() { }]; add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); - let res: SubaccountPositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + let _res: SubaccountPositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); } #[test] @@ -398,41 +333,21 @@ fn test_query_vanilla_subaccount_position() { fn test_query_trader_spot_orders() { let env = Setup::new(ExchangeType::Spot); let wasm = Wasm::new(&env.app); - let exchange = Exchange::new(&env.app); let market_id = env.market_id.unwrap(); - { - let (price, quantity) = scale_price_quantity_for_spot_market("10.01", "5.1", &BASE_DECIMALS, "E_DECIMALS); - let trader = &env.users[0]; + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(env.users[0].account.address())) + .as_str() + .to_string(); - let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) - .as_str() - .to_string(); + let query_msg = QueryMsg::TestTraderSpotOrders { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id).unwrap(), + }; - exchange - .create_spot_limit_order( - MsgCreateSpotLimitOrder { - sender: trader.account.address(), - order: Some(SpotOrder { - market_id: market_id.clone(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.to_owned(), - fee_recipient: trader.account.address(), - price, - quantity, - }), - order_type: OrderType::Sell.into(), - trigger_price: "".to_string(), - }), - }, - &trader.account, - ) - .unwrap(); + { + let (price, quantity) = scale_price_quantity_for_spot_market("10.01", "5.1", &BASE_DECIMALS, "E_DECIMALS); + add_spot_order_as(&env.app, market_id.to_owned(), &env.users[0], price, quantity, OrderType::Sell); - let query_msg = QueryMsg::TestTraderSpotOrders { - market_id: MarketId::new(market_id.clone()).unwrap(), - subaccount_id: SubaccountId::new(subaccount_id).unwrap(), - }; let res: TraderSpotOrdersResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); let orders = res.orders.clone().unwrap(); @@ -452,36 +367,8 @@ fn test_query_trader_spot_orders() { { let (price, quantity) = scale_price_quantity_for_spot_market("9.90", "0.5", &BASE_DECIMALS, "E_DECIMALS); - let trader = &env.users[0]; - - let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) - .as_str() - .to_string(); - - exchange - .create_spot_limit_order( - MsgCreateSpotLimitOrder { - sender: trader.account.address(), - order: Some(SpotOrder { - market_id: market_id.clone(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.to_owned(), - fee_recipient: trader.account.address(), - price, - quantity, - }), - order_type: OrderType::Buy.into(), - trigger_price: "".to_string(), - }), - }, - &trader.account, - ) - .unwrap(); + add_spot_order_as(&env.app, market_id.to_owned(), &env.users[0], price, quantity, OrderType::Buy); - let query_msg = QueryMsg::TestTraderSpotOrders { - market_id: MarketId::new(market_id.clone()).unwrap(), - subaccount_id: SubaccountId::new(subaccount_id).unwrap(), - }; let res: TraderSpotOrdersResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); let orders = res.orders.clone().unwrap(); @@ -504,36 +391,23 @@ fn test_query_trader_spot_orders() { fn test_query_trader_derivative_orders() { let env = Setup::new(ExchangeType::Derivative); let wasm = Wasm::new(&env.app); - let exchange = Exchange::new(&env.app); let market_id = env.market_id.unwrap(); let (price, quantity, margin) = scale_price_quantity_perp_market("10.1", "1", "2", "E_DECIMALS); - let trader = &env.users[0]; - let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(env.users[1].account.address())) .as_str() .to_string(); - exchange - .create_derivative_limit_order( - MsgCreateDerivativeLimitOrder { - sender: trader.account.address(), - order: Some(DerivativeOrder { - market_id: market_id.to_owned(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.to_owned(), - fee_recipient: trader.account.address(), - price, - quantity, - }), - margin, - order_type: OrderType::Sell.into(), - trigger_price: "".to_string(), - }), - }, - &trader.account, - ) - .unwrap(); + add_derivative_order_as( + &env.app, + market_id.to_owned(), + &env.users[1].account, + price, + quantity, + OrderType::Sell, + margin, + ); let query_msg = QueryMsg::TestTraderDerivativeOrders { market_id: MarketId::new(market_id.clone()).unwrap(), @@ -566,30 +440,7 @@ fn test_query_spot_market_mid_price_and_tob() { let wasm = Wasm::new(&env.app); let market_id = env.market_id.unwrap(); - let liquidity_orders: Vec = vec![ - HumanOrder { - price: "10.2".to_string(), - quantity: "5".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "10.1".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "9.9".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Buy, - }, - HumanOrder { - price: "9.8".to_string(), - quantity: "5".to_string(), - order_type: OrderType::Buy, - }, - ]; - - add_spot_orders(&env.app, market_id.clone(), liquidity_orders); + add_spot_initial_liquidity(&env.app, market_id.clone()); let query_msg = QueryMsg::TestSpotMarketMidPriceAndTob { market_id: MarketId::new(market_id.clone()).unwrap(), @@ -608,29 +459,7 @@ fn test_query_spot_market_orderbook() { let wasm = Wasm::new(&env.app); let market_id = env.market_id.unwrap(); - let liquidity_orders: Vec = vec![ - HumanOrder { - price: "10.2".to_string(), - quantity: "5".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "10.1".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "9.9".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Buy, - }, - HumanOrder { - price: "9.8".to_string(), - quantity: "5".to_string(), - order_type: OrderType::Buy, - }, - ]; - + let liquidity_orders = get_initial_liquidity_orders_vector(); add_spot_orders(&env.app, market_id.clone(), liquidity_orders.clone()); let query_msg = QueryMsg::TestSpotMarketOrderbook { @@ -724,30 +553,7 @@ fn test_query_market_volatility() { let wasm = Wasm::new(&env.app); let market_id = env.market_id.unwrap(); - let liquidity_orders: Vec = vec![ - HumanOrder { - price: "10.2".to_string(), - quantity: "5".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "10.1".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "9.9".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Buy, - }, - HumanOrder { - price: "9.8".to_string(), - quantity: "5".to_string(), - order_type: OrderType::Buy, - }, - ]; - - add_spot_orders(&env.app, market_id.clone(), liquidity_orders.clone()); + add_spot_initial_liquidity(&env.app, market_id.clone()); let query_msg = QueryMsg::TestMarketVolatility { market_id: MarketId::new(market_id.clone()).unwrap(), @@ -760,10 +566,9 @@ fn test_query_market_volatility() { let res: MarketVolatilityResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); assert_eq!(res.volatility, None); - // consume liquidity let new_orders: Vec = vec![ HumanOrder { - price: "10.2".to_string(), + price: "10.4".to_string(), quantity: "15".to_string(), order_type: OrderType::Buy, }, @@ -784,32 +589,9 @@ fn test_query_market_volatility() { fn test_query_derivative_market_mid_price_and_tob() { let env = Setup::new(ExchangeType::Derivative); let wasm = Wasm::new(&env.app); - let exchange = Exchange::new(&env.app); let market_id = env.market_id.unwrap(); - let liquidity_orders: Vec = vec![ - HumanOrder { - price: "10.2".to_string(), - quantity: "1".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "10.1".to_string(), - quantity: "2".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "9.9".to_string(), - quantity: "1".to_string(), - order_type: OrderType::Buy, - }, - HumanOrder { - price: "9.8".to_string(), - quantity: "2".to_string(), - order_type: OrderType::Buy, - }, - ]; - add_derivative_orders(&env.app, market_id.clone(), liquidity_orders, None); + add_perp_initial_liquidity(&env.app, market_id.to_owned()); let query_msg = QueryMsg::TestDerivativeMarketMidPriceAndTob { market_id: MarketId::new(market_id.clone()).unwrap(), @@ -828,30 +610,7 @@ fn test_query_aggregate_market_volume() { let wasm = Wasm::new(&env.app); let market_id = env.market_id.unwrap(); - let liquidity_orders: Vec = vec![ - HumanOrder { - price: "10.2".to_string(), - quantity: "5".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "10.1".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "9.9".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Buy, - }, - HumanOrder { - price: "9.8".to_string(), - quantity: "5".to_string(), - order_type: OrderType::Buy, - }, - ]; - - add_spot_orders(&env.app, market_id.clone(), liquidity_orders); + add_spot_initial_liquidity(&env.app, market_id.clone()); let query_msg = QueryMsg::TestAggregateMarketVolume { market_id: MarketId::new(market_id.clone()).unwrap(), @@ -888,38 +647,22 @@ fn test_query_aggregate_account_volume() { let wasm = Wasm::new(&env.app); let market_id = env.market_id.unwrap(); - let liquidity_orders: Vec = vec![ - HumanOrder { - price: "10.2".to_string(), - quantity: "5".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "10.1".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "9.9".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Buy, - }, - HumanOrder { - price: "9.8".to_string(), - quantity: "5".to_string(), - order_type: OrderType::Buy, - }, - ]; - - add_spot_orders(&env.app, market_id.clone(), liquidity_orders); + add_spot_initial_liquidity(&env.app, market_id.clone()); let query_msg = QueryMsg::TestAggregateAccountVolume { - account_id: env.users[0].subaccount_id.to_string(), + account_id: env.users[1].subaccount_id.to_string(), }; - let res: RunnerResult = wasm.query(&env.contract_address, &query_msg); - println!("{:?}", res); - assert_eq!(1, 2); + let res: QueryAggregateVolumeResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert!(res.aggregate_volumes.is_none()); + + let (price, quantity) = scale_price_quantity_for_spot_market("9.9", "1", &BASE_DECIMALS, "E_DECIMALS); + add_spot_order_as(&env.app, market_id.clone(), &env.users[1], price, quantity, OrderType::Sell); + + let res: QueryAggregateVolumeResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + let volume: &VolumeByType = &res.aggregate_volumes.unwrap()[0].volume; + assert_eq!(volume.maker_volume, FPDecimal::ZERO); + assert_eq!(volume.taker_volume, human_to_dec("9.9", QUOTE_DECIMALS)); } #[test] @@ -927,31 +670,9 @@ fn test_query_aggregate_account_volume() { fn test_query_derivative_market_orderbook() { let env = Setup::new(ExchangeType::Derivative); let wasm = Wasm::new(&env.app); - let exchange = Exchange::new(&env.app); let market_id = env.market_id.unwrap(); - let liquidity_orders: Vec = vec![ - HumanOrder { - price: "10.2".to_string(), - quantity: "1".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "10.1".to_string(), - quantity: "2".to_string(), - order_type: OrderType::Sell, - }, - HumanOrder { - price: "9.9".to_string(), - quantity: "1".to_string(), - order_type: OrderType::Buy, - }, - HumanOrder { - price: "9.8".to_string(), - quantity: "2".to_string(), - order_type: OrderType::Buy, - }, - ]; + let liquidity_orders = get_initial_perp_liquidity_orders_vector(); add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); let query_msg = QueryMsg::TestDerivativeMarketOrderbook { diff --git a/contracts/injective-cosmwasm-mock/src/utils.rs b/contracts/injective-cosmwasm-mock/src/utils.rs index d8a0d1d2..0f1f08f4 100644 --- a/contracts/injective-cosmwasm-mock/src/utils.rs +++ b/contracts/injective-cosmwasm-mock/src/utils.rs @@ -7,7 +7,10 @@ use injective_test_tube::{Account, Bank, Exchange, Gov, InjectiveTestApp, Insura use prost::Message; use std::{collections::HashMap, str::FromStr}; -use injective_std::types::injective::exchange::v1beta1::{DerivativeOrder, MsgCreateDerivativeLimitOrder, MsgCreateSpotLimitOrder, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, OrderInfo, OrderType, QueryDerivativeMarketsRequest, QuerySpotMarketsRequest, SpotOrder}; +use injective_std::types::injective::exchange::v1beta1::{ + DerivativeOrder, MsgCreateDerivativeLimitOrder, MsgCreateSpotLimitOrder, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, OrderInfo, + OrderType, QueryDerivativeMarketsRequest, QuerySpotMarketsRequest, SpotOrder, +}; use injective_std::types::injective::insurance::v1beta1::MsgCreateInsuranceFund; use injective_std::types::injective::oracle::v1beta1::OracleType; use injective_std::{ @@ -87,7 +90,7 @@ impl Setup { ]) .unwrap(); - let user_subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(user.address()), 1u32); + let user_subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(user.address()), 0u32); users.push(UserInfo { account: user, @@ -386,45 +389,136 @@ pub struct HumanOrder { pub quantity: String, pub order_type: OrderType, } +pub fn add_spot_order_as(app: &InjectiveTestApp, market_id: String, trader: &UserInfo, price: String, quantity: String, order_type: OrderType) { + let exchange = Exchange::new(app); + exchange + .create_spot_limit_order( + MsgCreateSpotLimitOrder { + sender: trader.account.address().clone(), + order: Some(SpotOrder { + market_id: market_id.to_owned(), + order_info: Some(OrderInfo { + subaccount_id: trader.subaccount_id.to_string(), + fee_recipient: trader.account.address(), + price, + quantity, + }), + order_type: order_type.into(), + trigger_price: "".to_string(), + }), + }, + &trader.account, + ) + .unwrap(); +} + pub fn add_spot_orders(app: &InjectiveTestApp, market_id: String, orders: Vec) { - let trader = app + let account = app .init_account(&[ str_coin("1000000", BASE_DENOM, BASE_DECIMALS), str_coin("1000000", QUOTE_DENOM, QUOTE_DECIMALS), ]) .unwrap(); - let exchange = Exchange::new(app); + let subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(account.address()), 0u32); + + let trader = UserInfo { account, subaccount_id }; for order in orders { let (price, quantity) = scale_price_quantity_for_spot_market(order.price.as_str(), order.quantity.as_str(), &BASE_DECIMALS, "E_DECIMALS); - exchange - .create_spot_limit_order( - MsgCreateSpotLimitOrder { - sender: trader.address(), - order: Some(SpotOrder { - market_id: market_id.to_owned(), - order_info: Some(OrderInfo { - subaccount_id: get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.address())) - .as_str() - .to_string(), - fee_recipient: trader.address(), - price, - quantity, - }), - order_type: order.order_type.into(), - trigger_price: "".to_string(), - }), - }, - &trader, - ) - .unwrap(); + add_spot_order_as(app, market_id.to_owned(), &trader, price, quantity, order.order_type); } } +pub fn get_initial_liquidity_orders_vector() -> Vec { + vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "10.1".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.8".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Buy, + }, + ] +} + +pub fn add_spot_initial_liquidity(app: &InjectiveTestApp, market_id: String) { + add_spot_orders(app, market_id, get_initial_liquidity_orders_vector()); +} + +pub fn get_initial_perp_liquidity_orders_vector() -> Vec { + vec![ + HumanOrder { + price: "10.2".to_string(), + quantity: "2".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "10.1".to_string(), + quantity: "1".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "9.9".to_string(), + quantity: "1".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "9.8".to_string(), + quantity: "2".to_string(), + order_type: OrderType::Buy, + }, + ] +} -pub fn add_derivative_orders(app: &InjectiveTestApp, market_id: String, orders: Vec, margin:Option) { +pub fn add_derivative_order_as( + app: &InjectiveTestApp, + market_id: String, + trader: &SigningAccount, + price: String, + quantity: String, + order_type: OrderType, + margin: String, +) { + let exchange = Exchange::new(app); + exchange + .create_derivative_limit_order( + MsgCreateDerivativeLimitOrder { + sender: trader.address(), + order: Some(DerivativeOrder { + market_id: market_id.to_owned(), + order_info: Some(OrderInfo { + subaccount_id: get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.address())) + .as_str() + .to_string(), + fee_recipient: trader.address(), + price, + quantity, + }), + margin, + order_type: order_type.into(), + trigger_price: "".to_string(), + }), + }, + trader, + ) + .unwrap(); +} +pub fn add_derivative_orders(app: &InjectiveTestApp, market_id: String, orders: Vec, margin: Option) { let trader = app .init_account(&[ str_coin("1000000", BASE_DENOM, BASE_DECIMALS), @@ -432,38 +526,18 @@ pub fn add_derivative_orders(app: &InjectiveTestApp, market_id: String, orders: ]) .unwrap(); - let exchange = Exchange::new(app); let margin = margin.unwrap_or("2".into()); for order in orders { - let (price, quantity, order_margin) = scale_price_quantity_perp_market(order.price.as_str(), order.quantity.as_str(), &margin, "E_DECIMALS); - exchange - .create_derivative_limit_order( - MsgCreateDerivativeLimitOrder { - sender: trader.address(), - order: Some(DerivativeOrder { - market_id: market_id.to_owned(), - order_info: Some(OrderInfo { - subaccount_id: get_default_subaccount_id_for_checked_address( - &Addr::unchecked(trader.address()), - ) - .as_str() - .to_string(), - fee_recipient: trader.address(), - price, - quantity, - }), - margin: order_margin, - order_type: order.order_type.into(), - trigger_price: "".to_string(), - }), - }, - &trader, - ) - .unwrap(); + let (price, quantity, order_margin) = + scale_price_quantity_perp_market(order.price.as_str(), order.quantity.as_str(), &margin, "E_DECIMALS); + add_derivative_order_as(app, market_id.to_owned(), &trader, price, quantity, order.order_type, order_margin); } } +pub fn add_perp_initial_liquidity(app: &InjectiveTestApp, market_id: String) { + add_derivative_orders(app, market_id, get_initial_perp_liquidity_orders_vector(), None); +} // Human Utils pub fn human_to_proto(raw_number: &str, decimals: i32) -> String { @@ -478,8 +552,6 @@ pub fn dec_to_proto(val: FPDecimal) -> String { val.scaled(18).to_string() } - - pub fn scale_price_quantity_for_spot_market(price: &str, quantity: &str, base_decimals: &i32, quote_decimals: &i32) -> (String, String) { let price_dec = FPDecimal::must_from_str(price.replace('_', "").as_str()); let quantity_dec = FPDecimal::must_from_str(quantity.replace('_', "").as_str()); diff --git a/packages/injective-protobuf/src/proto/mod.rs b/packages/injective-protobuf/src/proto/mod.rs index de6005c4..de0fb666 100644 --- a/packages/injective-protobuf/src/proto/mod.rs +++ b/packages/injective-protobuf/src/proto/mod.rs @@ -1,9 +1,9 @@ // @generated +pub mod account; pub mod auth; pub mod coin; pub mod distribution; pub mod exchange; -pub mod tx; pub mod oracle; -pub mod account; +pub mod tx; From cfb63df8bae113c13f7fefc6507a5bfa40690393 Mon Sep 17 00:00:00 2001 From: jbernal87 Date: Fri, 23 Feb 2024 18:22:40 +0100 Subject: [PATCH 07/13] Check github actions --- .github/workflows/Basic.yml | 10 +++++----- packages/injective-protobuf/src/proto/mod.rs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/Basic.yml b/.github/workflows/Basic.yml index c573b186..97bbec7e 100644 --- a/.github/workflows/Basic.yml +++ b/.github/workflows/Basic.yml @@ -24,7 +24,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.72.0 + toolchain: 1.73.0 target: wasm32-unknown-unknown override: true @@ -41,7 +41,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: unit-test - toolchain: 1.72.0 + toolchain: 1.73.0 args: --locked env: RUST_BACKTRACE: 1 @@ -65,7 +65,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.72.0 + toolchain: 1.73.0 override: true components: rustfmt, clippy @@ -73,12 +73,12 @@ jobs: uses: actions-rs/cargo@v1 with: command: fmt - toolchain: 1.72.0 + toolchain: 1.73.0 args: --all -- --check - name: Run cargo clippy uses: actions-rs/cargo@v1 with: command: clippy - toolchain: 1.72.0 + toolchain: 1.73.0 args: -- -D warnings diff --git a/packages/injective-protobuf/src/proto/mod.rs b/packages/injective-protobuf/src/proto/mod.rs index de0fb666..de6005c4 100644 --- a/packages/injective-protobuf/src/proto/mod.rs +++ b/packages/injective-protobuf/src/proto/mod.rs @@ -1,9 +1,9 @@ // @generated -pub mod account; pub mod auth; pub mod coin; pub mod distribution; pub mod exchange; -pub mod oracle; pub mod tx; +pub mod oracle; +pub mod account; From be67c713c33bc09d62022fe5ac181be7cc1a0579 Mon Sep 17 00:00:00 2001 From: jbernal87 Date: Wed, 28 Feb 2024 17:53:09 +0100 Subject: [PATCH 08/13] message fail --- Cargo.lock | 1 + contracts/injective-cosmwasm-mock/Cargo.toml | 1 + .../injective-cosmwasm-mock/src/contract.rs | 39 +++++++++++++++---- contracts/injective-cosmwasm-mock/src/msg.rs | 16 ++++---- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bea96f65..853d1e5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1562,6 +1562,7 @@ dependencies = [ "cw2 0.16.0", "injective-cosmwasm 0.2.21", "injective-math 0.2.4", + "injective-protobuf", "injective-std 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "injective-test-tube", "prost 0.11.9", diff --git a/contracts/injective-cosmwasm-mock/Cargo.toml b/contracts/injective-cosmwasm-mock/Cargo.toml index 71c3868a..b33b0eab 100644 --- a/contracts/injective-cosmwasm-mock/Cargo.toml +++ b/contracts/injective-cosmwasm-mock/Cargo.toml @@ -40,6 +40,7 @@ serde = { version = "1.0.196", default-features = false, features = thiserror = { version = "1.0.56" } protobuf = "3.3.0" prost = "0.11.9" +injective-protobuf = { path = "../../packages/injective-protobuf" } [dev-dependencies] injective-test-tube = "1.1.7" diff --git a/contracts/injective-cosmwasm-mock/src/contract.rs b/contracts/injective-cosmwasm-mock/src/contract.rs index 470b98b1..f828a503 100644 --- a/contracts/injective-cosmwasm-mock/src/contract.rs +++ b/contracts/injective-cosmwasm-mock/src/contract.rs @@ -2,16 +2,20 @@ use crate::{ error::ContractError, msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, }; -use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, SubMsg}; use cw2::set_contract_version; use injective_cosmwasm::{create_deposit_msg, InjectiveMsgWrapper, InjectiveQuerier, InjectiveQueryWrapper}; + #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; +use injective_std::types::injective::exchange::v1beta1::MsgCreateSpotLimitOrder; const CONTRACT_NAME: &str = "crates.io:injective:dummy"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +pub const CREATE_SPOT_ORDER_REPLY_ID: u64 = 0u64; + #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate(deps: DepsMut, _env: Env, _info: MessageInfo, _msg: InstantiateMsg) -> Result { set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; @@ -22,13 +26,38 @@ pub fn instantiate(deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Instantia pub fn execute( _deps: DepsMut, env: Env, - _info: MessageInfo, + info: MessageInfo, msg: ExecuteMsg, ) -> Result, ContractError> { match msg { ExecuteMsg::TestDepositMsg { subaccount_id, amount } => { Ok(Response::new().add_message(create_deposit_msg(env.contract.address, subaccount_id, amount))) } + ExecuteMsg::TestTraderTransientSpotOrders { market_id, subaccount_id } => { + Ok(Response::new().add_submessage( SubMsg::reply_on_success { + id: CREATE_SPOT_ORDER_REPLY_ID, + msg: + MsgCreateSpotLimitOrder { + sender: info.sender.to_string(), + order: Some(injective_std::types::injective::exchange::v1beta1::SpotOrder { + market_id: market_id.into(), + order_info: Some(injective_std::types::injective::exchange::v1beta1::OrderInfo { + subaccount_id: subaccount_id.to_string(), + fee_recipient: info.sender.to_string(), + price: "10".to_string(), + quantity: "10".to_string(), + }), + order_type: 1, + trigger_price: "".to_string(), + }), + }, + })) + + } + ExecuteMsg::TestTraderTransientDerivativeOrders { market_id, subaccount_id } => { + // to_json_binary(&querier.query_trader_transient_derivative_orders(&market_id, &subaccount_id)?) + Ok(Default::default()) + } } } @@ -50,12 +79,6 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Std QueryMsg::TestTraderDerivativeOrders { market_id, subaccount_id } => { to_json_binary(&querier.query_trader_derivative_orders(&market_id, &subaccount_id)?) } - QueryMsg::TestTraderTransientSpotOrders { market_id, subaccount_id } => { - to_json_binary(&querier.query_trader_transient_spot_orders(&market_id, &subaccount_id)?) - } - QueryMsg::TestTraderTransientDerivativeOrders { market_id, subaccount_id } => { - to_json_binary(&querier.query_trader_transient_derivative_orders(&market_id, &subaccount_id)?) - } QueryMsg::TestTraderSpotOrders { market_id, subaccount_id } => to_json_binary(&querier.query_trader_spot_orders(&market_id, &subaccount_id)?), QueryMsg::TestSpotOrdersToCancelUpToAmount { market_id, diff --git a/contracts/injective-cosmwasm-mock/src/msg.rs b/contracts/injective-cosmwasm-mock/src/msg.rs index 511f37a6..56c1e0f4 100644 --- a/contracts/injective-cosmwasm-mock/src/msg.rs +++ b/contracts/injective-cosmwasm-mock/src/msg.rs @@ -11,6 +11,14 @@ pub struct InstantiateMsg {} #[serde(rename_all = "snake_case")] pub enum ExecuteMsg { TestDepositMsg { subaccount_id: SubaccountId, amount: Coin }, + TestTraderTransientSpotOrders { + market_id: MarketId, + subaccount_id: SubaccountId, + }, + TestTraderTransientDerivativeOrders { + market_id: MarketId, + subaccount_id: SubaccountId, + }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] @@ -39,14 +47,6 @@ pub enum QueryMsg { market_id: MarketId, subaccount_id: SubaccountId, }, - TestTraderTransientSpotOrders { - market_id: MarketId, - subaccount_id: SubaccountId, - }, - TestTraderTransientDerivativeOrders { - market_id: MarketId, - subaccount_id: SubaccountId, - }, TestTraderSpotOrders { market_id: MarketId, subaccount_id: SubaccountId, From 21a8bc7c23685f36d08f88bb443be96b0d33942f Mon Sep 17 00:00:00 2001 From: jbernal87 Date: Thu, 29 Feb 2024 17:33:26 +0100 Subject: [PATCH 09/13] auth check --- Cargo.lock | 1 - contracts/injective-cosmwasm-mock/Cargo.toml | 2 +- .../injective-cosmwasm-mock/src/contract.rs | 61 ++++++--- .../injective-cosmwasm-mock/src/error.rs | 2 + .../src/testing/query_exchange_test.rs | 30 ++++- .../injective-cosmwasm-mock/src/utils.rs | 123 +++++++++++++++++- 6 files changed, 194 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 853d1e5b..bea96f65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1562,7 +1562,6 @@ dependencies = [ "cw2 0.16.0", "injective-cosmwasm 0.2.21", "injective-math 0.2.4", - "injective-protobuf", "injective-std 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "injective-test-tube", "prost 0.11.9", diff --git a/contracts/injective-cosmwasm-mock/Cargo.toml b/contracts/injective-cosmwasm-mock/Cargo.toml index b33b0eab..4752b9fb 100644 --- a/contracts/injective-cosmwasm-mock/Cargo.toml +++ b/contracts/injective-cosmwasm-mock/Cargo.toml @@ -40,7 +40,7 @@ serde = { version = "1.0.196", default-features = false, features = thiserror = { version = "1.0.56" } protobuf = "3.3.0" prost = "0.11.9" -injective-protobuf = { path = "../../packages/injective-protobuf" } +injective-std = { version = "0.1.5" } [dev-dependencies] injective-test-tube = "1.1.7" diff --git a/contracts/injective-cosmwasm-mock/src/contract.rs b/contracts/injective-cosmwasm-mock/src/contract.rs index f828a503..4796c8b0 100644 --- a/contracts/injective-cosmwasm-mock/src/contract.rs +++ b/contracts/injective-cosmwasm-mock/src/contract.rs @@ -2,14 +2,14 @@ use crate::{ error::ContractError, msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, }; -use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, SubMsg}; +use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, SubMsg, ReplyOn, Reply}; use cw2::set_contract_version; -use injective_cosmwasm::{create_deposit_msg, InjectiveMsgWrapper, InjectiveQuerier, InjectiveQueryWrapper}; +use injective_cosmwasm::{create_deposit_msg, create_spot_market_order_msg, InjectiveMsgWrapper, InjectiveQuerier, InjectiveQueryWrapper, OrderInfo, OrderType, SpotOrder}; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use injective_std::types::injective::exchange::v1beta1::MsgCreateSpotLimitOrder; +use injective_math::FPDecimal; const CONTRACT_NAME: &str = "crates.io:injective:dummy"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -34,25 +34,28 @@ pub fn execute( Ok(Response::new().add_message(create_deposit_msg(env.contract.address, subaccount_id, amount))) } ExecuteMsg::TestTraderTransientSpotOrders { market_id, subaccount_id } => { - Ok(Response::new().add_submessage( SubMsg::reply_on_success { + let order_info = OrderInfo{ + subaccount_id, + fee_recipient: None, + price: FPDecimal::must_from_str("1"), + quantity: FPDecimal::must_from_str("1"), + cid: None, + }; + let spot_order = SpotOrder{ + market_id, + order_info, + order_type: OrderType::Buy, + trigger_price: None + }; + let spot_order_message = create_spot_market_order_msg(info.sender, spot_order); + + let spot_order_message = SubMsg{ id: CREATE_SPOT_ORDER_REPLY_ID, - msg: - MsgCreateSpotLimitOrder { - sender: info.sender.to_string(), - order: Some(injective_std::types::injective::exchange::v1beta1::SpotOrder { - market_id: market_id.into(), - order_info: Some(injective_std::types::injective::exchange::v1beta1::OrderInfo { - subaccount_id: subaccount_id.to_string(), - fee_recipient: info.sender.to_string(), - price: "10".to_string(), - quantity: "10".to_string(), - }), - order_type: 1, - trigger_price: "".to_string(), - }), - }, - })) - + msg: spot_order_message, + gas_limit: None, + reply_on: ReplyOn::Success, + }; + Ok(Response::new().add_submessage(spot_order_message)) } ExecuteMsg::TestTraderTransientDerivativeOrders { market_id, subaccount_id } => { // to_json_binary(&querier.query_trader_transient_derivative_orders(&market_id, &subaccount_id)?) @@ -136,3 +139,19 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Std } } } + + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn reply( + deps: DepsMut, + env: Env, + msg: Reply, +) -> Result { + match msg.id { + CREATE_SPOT_ORDER_REPLY_ID => { + deps.api.debug("I am here"); + Ok(Default::default()) + }, + _ => Err(ContractError::UnrecognizedReply(msg.id)), + } +} diff --git a/contracts/injective-cosmwasm-mock/src/error.rs b/contracts/injective-cosmwasm-mock/src/error.rs index 40dab9ff..877d5c9f 100644 --- a/contracts/injective-cosmwasm-mock/src/error.rs +++ b/contracts/injective-cosmwasm-mock/src/error.rs @@ -5,4 +5,6 @@ use thiserror::Error; pub enum ContractError { #[error("{0}")] Std(#[from] StdError), + #[error("Unrecognized reply id: {0}")] + UnrecognizedReply(u64), } diff --git a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs index 83db3caa..ed7f29c5 100644 --- a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs +++ b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs @@ -25,6 +25,7 @@ use injective_std::types::injective::exchange::v1beta1::{ }; use injective_test_tube::injective_cosmwasm::get_default_subaccount_id_for_checked_address; use injective_test_tube::{Account, Exchange, Module, RunnerResult, Wasm}; +use crate::utils::execute_all_authorizations; #[test] #[cfg_attr(not(feature = "integration"), ignore)] @@ -739,7 +740,34 @@ fn test_query_derivative_orders_to_cancel_up_to_amount() {} #[test] #[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_trader_transient_spot_orders() {} +fn test_query_trader_transient_spot_orders() { + let env = Setup::new(ExchangeType::Spot); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + + let subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(env.users[0].account.address()), 0u32); + + execute_all_authorizations( + &env.app, + &env.users[0].account, + env.contract_address.clone(), + ); + + let res = wasm.execute( + &env.contract_address, + &ExecuteMsg::TestTraderTransientSpotOrders { + market_id: MarketId::new(market_id).unwrap(), + subaccount_id: subaccount_id.clone(), + + }, + &[], + &env.users[0].account, + ); + + println!("{:?}", res); + assert_eq!(1,2); + +} #[test] #[cfg_attr(not(feature = "integration"), ignore)] diff --git a/contracts/injective-cosmwasm-mock/src/utils.rs b/contracts/injective-cosmwasm-mock/src/utils.rs index 0f1f08f4..c6305109 100644 --- a/contracts/injective-cosmwasm-mock/src/utils.rs +++ b/contracts/injective-cosmwasm-mock/src/utils.rs @@ -2,7 +2,7 @@ use crate::msg::InstantiateMsg; use cosmwasm_std::{coin, Addr, Coin}; use injective_cosmwasm::{checked_address_to_subaccount_id, SubaccountId}; use injective_math::{scale::Scaled, FPDecimal}; -use injective_test_tube::{Account, Bank, Exchange, Gov, InjectiveTestApp, Insurance, Module, Oracle, SigningAccount, Wasm}; +use injective_test_tube::{Account, Authz, Bank, Exchange, ExecuteResponse, Gov, InjectiveTestApp, Insurance, Module, Oracle, Runner, SigningAccount, Wasm}; use prost::Message; use std::{collections::HashMap, str::FromStr}; @@ -24,6 +24,9 @@ use injective_std::{ injective::oracle::v1beta1::{GrantPriceFeederPrivilegeProposal, MsgRelayPriceFeedPrice}, }, }; +use injective_std::shim::Timestamp; +use injective_std::types::cosmos::authz::v1beta1::{GenericAuthorization, Grant, MsgGrant, MsgRevoke, MsgRevokeResponse}; +use injective_std::types::cosmos::bank::v1beta1::SendAuthorization; use injective_test_tube::injective_cosmwasm::get_default_subaccount_id_for_checked_address; pub const EXCHANGE_DECIMALS: i32 = 18i32; @@ -539,6 +542,124 @@ pub fn add_perp_initial_liquidity(app: &InjectiveTestApp, market_id: String) { add_derivative_orders(app, market_id, get_initial_perp_liquidity_orders_vector(), None); } +pub fn revoke_authorization( + app: &InjectiveTestApp, + granter: &SigningAccount, + grantee: String, + msg_type_url: String, +) { + let _res: ExecuteResponse = app + .execute_multiple( + &[( + MsgRevoke { + granter: granter.address(), + grantee, + msg_type_url, + }, + MsgRevoke::TYPE_URL, + )], + granter, + ) + .unwrap(); +} + +pub fn create_generic_authorization( + app: &InjectiveTestApp, + granter: &SigningAccount, + grantee: String, + msg: String, + expiration: Option, +) { + let authz = Authz::new(app); + + let mut buf = vec![]; + GenericAuthorization::encode(&GenericAuthorization { msg }, &mut buf).unwrap(); + + authz + .grant( + MsgGrant { + granter: granter.address(), + grantee, + grant: Some(Grant { + authorization: Some(Any { + type_url: "/cosmos.authz.v1beta1.GenericAuthorization".to_string(), + value: buf.clone(), + }), + expiration, + }), + }, + granter, + ) + .unwrap(); +} + +pub fn create_send_authorization( + app: &InjectiveTestApp, + granter: &SigningAccount, + grantee: String, + amount: BaseCoin, + expiration: Option, +) { + let authz = Authz::new(app); + + let mut buf = vec![]; + SendAuthorization::encode( + &SendAuthorization { + spend_limit: vec![amount], + allow_list: vec![], + }, + &mut buf, + ) + .unwrap(); + + authz + .grant( + MsgGrant { + granter: granter.address(), + grantee, + grant: Some(Grant { + authorization: Some(Any { + type_url: "/cosmos.bank.v1beta1.SendAuthorization".to_string(), + value: buf.clone(), + }), + expiration, + }), + }, + granter, + ) + .unwrap(); +} + +pub fn execute_all_authorizations( + app: &InjectiveTestApp, + granter: &SigningAccount, + grantee: String, +) { + create_generic_authorization( + app, + granter, + grantee.clone(), + "/injective.exchange.v1beta1.MsgCreateSpotMarketOrder".to_string(), + None, + ); + + create_generic_authorization( + app, + granter, + grantee.clone(), + "/injective.exchange.v1beta1.MsgCreateDerivativeMarketOrder".to_string(), + None, + ); + + create_generic_authorization( + app, + granter, + grantee, + "/injective.exchange.v1beta1.MsgWithdraw".to_string(), + None, + ); +} + // Human Utils pub fn human_to_proto(raw_number: &str, decimals: i32) -> String { FPDecimal::must_from_str(&raw_number.replace('_', "")).scaled(18 + decimals).to_string() From ed4cef19113d8195540a16f88b380e4b9f344468 Mon Sep 17 00:00:00 2001 From: jbernal87 Date: Mon, 4 Mar 2024 11:11:59 +0100 Subject: [PATCH 10/13] more auth check --- .../injective-cosmwasm-mock/src/contract.rs | 69 +++++++------ contracts/injective-cosmwasm-mock/src/lib.rs | 2 + contracts/injective-cosmwasm-mock/src/msg.rs | 13 +-- .../src/order_management.rs | 36 +++++++ .../src/testing/query_exchange_test.rs | 13 +-- .../injective-cosmwasm-mock/src/types.rs | 97 +++++++++++++++++++ .../injective-cosmwasm-mock/src/utils.rs | 54 +++++------ 7 files changed, 199 insertions(+), 85 deletions(-) create mode 100644 contracts/injective-cosmwasm-mock/src/order_management.rs create mode 100644 contracts/injective-cosmwasm-mock/src/types.rs diff --git a/contracts/injective-cosmwasm-mock/src/contract.rs b/contracts/injective-cosmwasm-mock/src/contract.rs index 4796c8b0..64c329cd 100644 --- a/contracts/injective-cosmwasm-mock/src/contract.rs +++ b/contracts/injective-cosmwasm-mock/src/contract.rs @@ -1,15 +1,16 @@ -use crate::{ - error::ContractError, - msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, -}; -use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, SubMsg, ReplyOn, Reply}; +use crate::{error::ContractError, msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, types}; +use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, ReplyOn, Response, StdResult, SubMsg}; use cw2::set_contract_version; -use injective_cosmwasm::{create_deposit_msg, create_spot_market_order_msg, InjectiveMsgWrapper, InjectiveQuerier, InjectiveQueryWrapper, OrderInfo, OrderType, SpotOrder}; - +use injective_cosmwasm::{ + create_deposit_msg, InjectiveMsgWrapper, InjectiveQuerier, InjectiveQueryWrapper, OrderType +}; +use prost::Message; +use crate::order_management::{create_spot_market_order, create_stargate_msg}; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use injective_math::FPDecimal; +use crate::msg::MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT; const CONTRACT_NAME: &str = "crates.io:injective:dummy"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -24,7 +25,7 @@ pub fn instantiate(deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Instantia #[cfg_attr(not(feature = "library"), entry_point)] pub fn execute( - _deps: DepsMut, + deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg, @@ -34,28 +35,29 @@ pub fn execute( Ok(Response::new().add_message(create_deposit_msg(env.contract.address, subaccount_id, amount))) } ExecuteMsg::TestTraderTransientSpotOrders { market_id, subaccount_id } => { - let order_info = OrderInfo{ - subaccount_id, - fee_recipient: None, - price: FPDecimal::must_from_str("1"), - quantity: FPDecimal::must_from_str("1"), - cid: None, - }; - let spot_order = SpotOrder{ - market_id, - order_info, - order_type: OrderType::Buy, - trigger_price: None - }; - let spot_order_message = create_spot_market_order_msg(info.sender, spot_order); + let querier: InjectiveQuerier = InjectiveQuerier::new(&deps.querier); + let spot_market = querier.query_spot_market(&market_id).unwrap().market.unwrap(); + + deps.api.debug(&info.sender.as_str()); + let order_msg = create_spot_market_order( + FPDecimal::must_from_str("1"), + FPDecimal::must_from_str("1"), + OrderType::Buy, + &info.sender.as_str(), + subaccount_id.as_str(), + &spot_market, + ); + + let mut order_bytes = vec![]; + types::MsgCreateSpotMarketOrder::encode(&order_msg, &mut order_bytes).unwrap(); + + let order_submessage = SubMsg::reply_on_success( + create_stargate_msg(MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT, order_bytes).unwrap(), + CREATE_SPOT_ORDER_REPLY_ID, + ); + + Ok(Response::new().add_submessage(order_submessage)) - let spot_order_message = SubMsg{ - id: CREATE_SPOT_ORDER_REPLY_ID, - msg: spot_order_message, - gas_limit: None, - reply_on: ReplyOn::Success, - }; - Ok(Response::new().add_submessage(spot_order_message)) } ExecuteMsg::TestTraderTransientDerivativeOrders { market_id, subaccount_id } => { // to_json_binary(&querier.query_trader_transient_derivative_orders(&market_id, &subaccount_id)?) @@ -140,18 +142,13 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Std } } - #[cfg_attr(not(feature = "library"), entry_point)] -pub fn reply( - deps: DepsMut, - env: Env, - msg: Reply, -) -> Result { +pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result { match msg.id { CREATE_SPOT_ORDER_REPLY_ID => { deps.api.debug("I am here"); Ok(Default::default()) - }, + } _ => Err(ContractError::UnrecognizedReply(msg.id)), } } diff --git a/contracts/injective-cosmwasm-mock/src/lib.rs b/contracts/injective-cosmwasm-mock/src/lib.rs index 213e21b9..8e4615c5 100644 --- a/contracts/injective-cosmwasm-mock/src/lib.rs +++ b/contracts/injective-cosmwasm-mock/src/lib.rs @@ -4,6 +4,8 @@ pub mod msg; #[cfg(test)] mod testing; +mod order_management; +mod types; #[cfg(test)] pub mod utils; diff --git a/contracts/injective-cosmwasm-mock/src/msg.rs b/contracts/injective-cosmwasm-mock/src/msg.rs index 56c1e0f4..d02db8a3 100644 --- a/contracts/injective-cosmwasm-mock/src/msg.rs +++ b/contracts/injective-cosmwasm-mock/src/msg.rs @@ -4,6 +4,9 @@ use injective_math::FPDecimal; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +pub const MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT: &str = + "/injective.exchange.v1beta1.MsgCreateSpotMarketOrder"; + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct InstantiateMsg {} @@ -11,14 +14,8 @@ pub struct InstantiateMsg {} #[serde(rename_all = "snake_case")] pub enum ExecuteMsg { TestDepositMsg { subaccount_id: SubaccountId, amount: Coin }, - TestTraderTransientSpotOrders { - market_id: MarketId, - subaccount_id: SubaccountId, - }, - TestTraderTransientDerivativeOrders { - market_id: MarketId, - subaccount_id: SubaccountId, - }, + TestTraderTransientSpotOrders { market_id: MarketId, subaccount_id: SubaccountId }, + TestTraderTransientDerivativeOrders { market_id: MarketId, subaccount_id: SubaccountId }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] diff --git a/contracts/injective-cosmwasm-mock/src/order_management.rs b/contracts/injective-cosmwasm-mock/src/order_management.rs new file mode 100644 index 00000000..d991a3cc --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/order_management.rs @@ -0,0 +1,36 @@ +use crate::types; +use cosmwasm_std::{to_json_binary, Coin, CosmosMsg, StdResult, SubMsg, Uint128, WasmMsg}; +use injective_cosmwasm::{InjectiveMsgWrapper, OrderType, SpotMarket}; +use injective_math::FPDecimal; + + +pub fn create_stargate_msg(type_url: &str, value: Vec) -> StdResult> { + Ok(CosmosMsg::Stargate { + type_url: type_url.to_string(), + value: value.into(), + }) +} + +pub fn create_spot_market_order( + price: FPDecimal, + quantity: FPDecimal, + order_type: OrderType, + sender: &str, + subaccount_id: &str, + market: &SpotMarket, +) -> types::MsgCreateSpotMarketOrder { + types::MsgCreateSpotMarketOrder { + sender: sender.to_string(), + order: Some(types::SpotOrder { + market_id: market.market_id.as_str().into(), + order_info: Some(types::OrderInfo { + subaccount_id: subaccount_id.to_string(), + fee_recipient: sender.to_string(), + price: price.to_string(), + quantity: quantity.to_string(), + }), + order_type: order_type as i32, + trigger_price: "".to_string(), + }), + } +} diff --git a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs index ed7f29c5..00d4e925 100644 --- a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs +++ b/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs @@ -8,6 +8,7 @@ use crate::{ }, }; +use crate::utils::execute_all_authorizations; use cosmwasm_std::{Addr, Coin}; use injective_cosmwasm::exchange::response::QueryOrderbookResponse; use injective_cosmwasm::exchange::types::VolumeByType; @@ -25,7 +26,6 @@ use injective_std::types::injective::exchange::v1beta1::{ }; use injective_test_tube::injective_cosmwasm::get_default_subaccount_id_for_checked_address; use injective_test_tube::{Account, Exchange, Module, RunnerResult, Wasm}; -use crate::utils::execute_all_authorizations; #[test] #[cfg_attr(not(feature = "integration"), ignore)] @@ -747,26 +747,21 @@ fn test_query_trader_transient_spot_orders() { let subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(env.users[0].account.address()), 0u32); - execute_all_authorizations( - &env.app, - &env.users[0].account, - env.contract_address.clone(), - ); + execute_all_authorizations(&env.app, &env.users[0].account, env.contract_address.clone()); + println!("{}", &env.users[0].account.address()); let res = wasm.execute( &env.contract_address, &ExecuteMsg::TestTraderTransientSpotOrders { market_id: MarketId::new(market_id).unwrap(), subaccount_id: subaccount_id.clone(), - }, &[], &env.users[0].account, ); println!("{:?}", res); - assert_eq!(1,2); - + assert_eq!(1, 2); } #[test] diff --git a/contracts/injective-cosmwasm-mock/src/types.rs b/contracts/injective-cosmwasm-mock/src/types.rs new file mode 100644 index 00000000..e83690bd --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/types.rs @@ -0,0 +1,97 @@ +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + // CosmwasmExt, +)] +// #[proto_message(type_url = "/injective.exchange.v1beta1.OrderInfo")] +pub struct OrderInfo { + /// bytes32 subaccount ID that created the order + #[prost(string, tag = "1")] + #[serde(alias = "subaccountID")] + pub subaccount_id: ::prost::alloc::string::String, + /// address fee_recipient address that will receive fees for the order + #[prost(string, tag = "2")] + pub fee_recipient: ::prost::alloc::string::String, + /// price of the order + #[prost(string, tag = "3")] + pub price: ::prost::alloc::string::String, + /// quantity of the order + #[prost(string, tag = "4")] + pub quantity: ::prost::alloc::string::String, +} + +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + // CosmwasmExt, +)] +// #[proto_message(type_url = "/injective.exchange.v1beta1.SpotOrder")] +pub struct SpotOrder { + /// market_id represents the unique ID of the market + #[prost(string, tag = "1")] + #[serde(alias = "marketID")] + pub market_id: ::prost::alloc::string::String, + /// order_info contains the information of the order + #[prost(message, optional, tag = "2")] + pub order_info: ::core::option::Option, + /// order types + #[prost(enumeration = "OrderType", tag = "3")] + // #[serde( + // serialize_with = "crate::serde::as_str::serialize", + // deserialize_with = "crate::serde::as_str::deserialize" + // )] + pub order_type: i32, + /// trigger_price is the trigger price used by stop/take orders + #[prost(string, tag = "4")] + pub trigger_price: ::prost::alloc::string::String, +} + +/// MsgCreateSpotMarketOrder defines a SDK message for creating a new spot market +/// order. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( +Clone, +PartialEq, +Eq, +::prost::Message, +::serde::Serialize, +::serde::Deserialize, +::schemars::JsonSchema, +// CosmwasmExt, +)] +// #[proto_message(type_url = "/injective.exchange.v1beta1.MsgCreateSpotMarketOrder")] +pub struct MsgCreateSpotMarketOrder { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub order: ::core::option::Option, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +#[derive(::serde::Serialize, ::serde::Deserialize, ::schemars::JsonSchema)] +pub enum OrderType { + Unspecified = 0, + Buy = 1, + Sell = 2, + StopBuy = 3, + StopSell = 4, + TakeBuy = 5, + TakeSell = 6, + BuyPo = 7, + SellPo = 8, + BuyAtomic = 9, + SellAtomic = 10, +} diff --git a/contracts/injective-cosmwasm-mock/src/utils.rs b/contracts/injective-cosmwasm-mock/src/utils.rs index c6305109..d044d400 100644 --- a/contracts/injective-cosmwasm-mock/src/utils.rs +++ b/contracts/injective-cosmwasm-mock/src/utils.rs @@ -1,12 +1,17 @@ -use crate::msg::InstantiateMsg; +use crate::msg::{InstantiateMsg, MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT}; use cosmwasm_std::{coin, Addr, Coin}; use injective_cosmwasm::{checked_address_to_subaccount_id, SubaccountId}; use injective_math::{scale::Scaled, FPDecimal}; -use injective_test_tube::{Account, Authz, Bank, Exchange, ExecuteResponse, Gov, InjectiveTestApp, Insurance, Module, Oracle, Runner, SigningAccount, Wasm}; +use injective_test_tube::{ + Account, Authz, Bank, Exchange, ExecuteResponse, Gov, InjectiveTestApp, Insurance, Module, Oracle, Runner, SigningAccount, Wasm, +}; use prost::Message; use std::{collections::HashMap, str::FromStr}; +use injective_std::shim::Timestamp; +use injective_std::types::cosmos::authz::v1beta1::{GenericAuthorization, Grant, MsgGrant, MsgRevoke, MsgRevokeResponse}; +use injective_std::types::cosmos::bank::v1beta1::SendAuthorization; use injective_std::types::injective::exchange::v1beta1::{ DerivativeOrder, MsgCreateDerivativeLimitOrder, MsgCreateSpotLimitOrder, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, OrderInfo, OrderType, QueryDerivativeMarketsRequest, QuerySpotMarketsRequest, SpotOrder, @@ -24,9 +29,6 @@ use injective_std::{ injective::oracle::v1beta1::{GrantPriceFeederPrivilegeProposal, MsgRelayPriceFeedPrice}, }, }; -use injective_std::shim::Timestamp; -use injective_std::types::cosmos::authz::v1beta1::{GenericAuthorization, Grant, MsgGrant, MsgRevoke, MsgRevokeResponse}; -use injective_std::types::cosmos::bank::v1beta1::SendAuthorization; use injective_test_tube::injective_cosmwasm::get_default_subaccount_id_for_checked_address; pub const EXCHANGE_DECIMALS: i32 = 18i32; @@ -542,12 +544,7 @@ pub fn add_perp_initial_liquidity(app: &InjectiveTestApp, market_id: String) { add_derivative_orders(app, market_id, get_initial_perp_liquidity_orders_vector(), None); } -pub fn revoke_authorization( - app: &InjectiveTestApp, - granter: &SigningAccount, - grantee: String, - msg_type_url: String, -) { +pub fn revoke_authorization(app: &InjectiveTestApp, granter: &SigningAccount, grantee: String, msg_type_url: String) { let _res: ExecuteResponse = app .execute_multiple( &[( @@ -563,13 +560,7 @@ pub fn revoke_authorization( .unwrap(); } -pub fn create_generic_authorization( - app: &InjectiveTestApp, - granter: &SigningAccount, - grantee: String, - msg: String, - expiration: Option, -) { +pub fn create_generic_authorization(app: &InjectiveTestApp, granter: &SigningAccount, grantee: String, msg: String, expiration: Option) { let authz = Authz::new(app); let mut buf = vec![]; @@ -593,13 +584,7 @@ pub fn create_generic_authorization( .unwrap(); } -pub fn create_send_authorization( - app: &InjectiveTestApp, - granter: &SigningAccount, - grantee: String, - amount: BaseCoin, - expiration: Option, -) { +pub fn create_send_authorization(app: &InjectiveTestApp, granter: &SigningAccount, grantee: String, amount: BaseCoin, expiration: Option) { let authz = Authz::new(app); let mut buf = vec![]; @@ -610,7 +595,7 @@ pub fn create_send_authorization( }, &mut buf, ) - .unwrap(); + .unwrap(); authz .grant( @@ -630,16 +615,12 @@ pub fn create_send_authorization( .unwrap(); } -pub fn execute_all_authorizations( - app: &InjectiveTestApp, - granter: &SigningAccount, - grantee: String, -) { +pub fn execute_all_authorizations(app: &InjectiveTestApp, granter: &SigningAccount, grantee: String) { create_generic_authorization( app, granter, grantee.clone(), - "/injective.exchange.v1beta1.MsgCreateSpotMarketOrder".to_string(), + MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT.to_string(), None, ); @@ -651,6 +632,15 @@ pub fn execute_all_authorizations( None, ); + + create_generic_authorization( + app, + granter, + grantee.clone(), + "/injective.exchange.v1beta1.MsgBatchUpdateOrders".to_string(), + None, + ); + create_generic_authorization( app, granter, From f57ad5bcc70029fdd783b23d45c189c2c0718d90 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Mon, 4 Mar 2024 10:30:08 +0000 Subject: [PATCH 11/13] fixed authz needs proto added --- .../injective-cosmwasm-mock/src/contract.rs | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/contracts/injective-cosmwasm-mock/src/contract.rs b/contracts/injective-cosmwasm-mock/src/contract.rs index 64c329cd..207ea3f9 100644 --- a/contracts/injective-cosmwasm-mock/src/contract.rs +++ b/contracts/injective-cosmwasm-mock/src/contract.rs @@ -1,22 +1,25 @@ -use crate::{error::ContractError, msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, types}; -use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, ReplyOn, Response, StdResult, SubMsg}; -use cw2::set_contract_version; -use injective_cosmwasm::{ - create_deposit_msg, InjectiveMsgWrapper, InjectiveQuerier, InjectiveQueryWrapper, OrderType +use crate::msg::MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT; +use crate::order_management::{create_spot_market_order, create_stargate_msg}; +use crate::{ + error::ContractError, + msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, + types, }; -use prost::Message; -use crate::order_management::{create_spot_market_order, create_stargate_msg}; -#[cfg(not(feature = "library"))] -use cosmwasm_std::entry_point; +use cosmos_sdk_proto::{cosmos::authz::v1beta1::MsgExec, traits::Message, Any}; +use cosmwasm_std::{entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, ReplyOn, Response, StdResult, SubMsg}; +use cw2::set_contract_version; +use injective_cosmwasm::{create_deposit_msg, InjectiveMsgWrapper, InjectiveQuerier, InjectiveQueryWrapper, OrderType}; use injective_math::FPDecimal; -use crate::msg::MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT; +use prost::Message; const CONTRACT_NAME: &str = "crates.io:injective:dummy"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub const CREATE_SPOT_ORDER_REPLY_ID: u64 = 0u64; +pub const MSG_EXEC: &str = "/cosmos.authz.v1beta1.MsgExec"; + #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate(deps: DepsMut, _env: Env, _info: MessageInfo, _msg: InstantiateMsg) -> Result { set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; @@ -51,13 +54,20 @@ pub fn execute( let mut order_bytes = vec![]; types::MsgCreateSpotMarketOrder::encode(&order_msg, &mut order_bytes).unwrap(); + let msg_exec = MsgExec { + grantee: env.contract.address.to_string(), + msgs: vec![Any { + type_url: MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT.to_string(), + value: order_bytes, + }], + }; + let order_submessage = SubMsg::reply_on_success( - create_stargate_msg(MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT, order_bytes).unwrap(), + create_stargate_msg(MSG_EXEC, msg_exec.encode_to_vec().into()).unwrap(), CREATE_SPOT_ORDER_REPLY_ID, ); Ok(Response::new().add_submessage(order_submessage)) - } ExecuteMsg::TestTraderTransientDerivativeOrders { market_id, subaccount_id } => { // to_json_binary(&querier.query_trader_transient_derivative_orders(&market_id, &subaccount_id)?) From e921edc90af6d90140797ab63ea53f9a3d0a5fe9 Mon Sep 17 00:00:00 2001 From: jbernal87 Date: Mon, 4 Mar 2024 15:40:55 +0100 Subject: [PATCH 12/13] removing auth queries and base_decimal,oracle, transient orders, token factory, wasmx and staking tests. add changelog --- CHANGELOG.md | 25 + Cargo.lock | 103 +++- contracts/injective-cosmwasm-mock/Cargo.toml | 20 +- .../injective-cosmwasm-mock/src/contract.rs | 154 +++--- .../injective-cosmwasm-mock/src/error.rs | 4 + .../injective-cosmwasm-mock/src/handle.rs | 112 +++++ contracts/injective-cosmwasm-mock/src/lib.rs | 8 +- contracts/injective-cosmwasm-mock/src/msg.rs | 53 +- .../src/order_management.rs | 46 +- .../injective-cosmwasm-mock/src/query.rs | 161 ++++++ .../injective-cosmwasm-mock/src/reply.rs | 39 ++ .../injective-cosmwasm-mock/src/state.rs | 11 + .../src/testing/mod.rs | 7 +- ...uery_exchange_test.rs => test_exchange.rs} | 460 ++++-------------- .../src/testing/test_exchange_derivative.rs | 396 +++++++++++++++ .../src/testing/test_oracle.rs | 105 ++++ .../src/testing/test_staking.rs | 38 ++ .../src/testing/test_token_factory.rs | 36 ++ .../src/testing/test_wasmx.rs | 18 + .../injective-cosmwasm-mock/src/types.rs | 89 +++- .../injective-cosmwasm-mock/src/utils.rs | 214 ++++++-- .../src/exchange_mock_querier.rs | 31 +- packages/injective-cosmwasm/src/querier.rs | 77 +-- packages/injective-cosmwasm/src/query.rs | 21 - packages/injective-protobuf/src/proto/mod.rs | 4 +- 25 files changed, 1595 insertions(+), 637 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 contracts/injective-cosmwasm-mock/src/handle.rs create mode 100644 contracts/injective-cosmwasm-mock/src/query.rs create mode 100644 contracts/injective-cosmwasm-mock/src/reply.rs create mode 100644 contracts/injective-cosmwasm-mock/src/state.rs rename contracts/injective-cosmwasm-mock/src/testing/{query_exchange_test.rs => test_exchange.rs} (52%) create mode 100644 contracts/injective-cosmwasm-mock/src/testing/test_exchange_derivative.rs create mode 100644 contracts/injective-cosmwasm-mock/src/testing/test_oracle.rs create mode 100644 contracts/injective-cosmwasm-mock/src/testing/test_staking.rs create mode 100644 contracts/injective-cosmwasm-mock/src/testing/test_token_factory.rs create mode 100644 contracts/injective-cosmwasm-mock/src/testing/test_wasmx.rs diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..00fb444b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# Change Log + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] - yyyy-mm-dd + +### Added + +### Changed + + +## [Unreleased] - 2024-03-18 + +### Added +- Tests queries (injective-cosmwasm-mock) covering functionality of querier.rs + +### Fixed + - Exchange aggregate volume query to use the correct parsing. + +### Removed +- Grants related queries. +- Exchange denom decimal query. \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index bea96f65..e7c01f7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -385,8 +385,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73c9d2043a9e617b0d602fbc0a0ecd621568edbf3a9774890a6d562389bd8e1c" dependencies = [ "prost 0.11.9", - "prost-types", - "tendermint-proto", + "prost-types 0.11.9", + "tendermint-proto 0.32.2", +] + +[[package]] +name = "cosmos-sdk-proto" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" +dependencies = [ + "prost 0.12.3", + "prost-types 0.12.3", + "tendermint-proto 0.34.1", ] [[package]] @@ -396,7 +407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af13955d6f356272e6def9ff5e2450a7650df536d8934f47052a20c76513d2f6" dependencies = [ "bip32", - "cosmos-sdk-proto", + "cosmos-sdk-proto 0.19.0", "ecdsa 0.16.9", "eyre", "getrandom", @@ -1557,13 +1568,17 @@ dependencies = [ name = "injective-cosmwasm-mock" version = "1.0.0" dependencies = [ + "cosmos-sdk-proto 0.20.0", + "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", "cw2 0.16.0", "injective-cosmwasm 0.2.21", "injective-math 0.2.4", + "injective-protobuf", "injective-std 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "injective-test-tube", + "injective-testing 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "prost 0.11.9", "protobuf 3.3.0", "schemars", @@ -1621,7 +1636,7 @@ dependencies = [ "cosmwasm-std", "osmosis-std-derive", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "schemars", "serde 1.0.196", "serde-cw-value", @@ -1637,7 +1652,7 @@ dependencies = [ "cosmwasm-std", "osmosis-std-derive", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "schemars", "serde 1.0.196", "serde-cw-value", @@ -1679,6 +1694,24 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "injective-testing" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49dc1d881d0b7726745ed776a87d1e6f93e877d2d5ebd0fe8be759f5424a091a" +dependencies = [ + "anyhow", + "base64 0.13.1", + "cosmwasm-std", + "cw-multi-test", + "injective-cosmwasm 0.2.18", + "injective-math 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6", + "secp256k1", + "serde 1.0.196", + "tiny-keccak", +] + [[package]] name = "itertools" version = "0.10.5" @@ -2171,6 +2204,16 @@ dependencies = [ "prost-derive 0.11.9", ] +[[package]] +name = "prost" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +dependencies = [ + "bytes", + "prost-derive 0.12.3", +] + [[package]] name = "prost-derive" version = "0.9.0" @@ -2197,6 +2240,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "prost-derive" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "prost-types" version = "0.11.9" @@ -2206,6 +2262,15 @@ dependencies = [ "prost 0.11.9", ] +[[package]] +name = "prost-types" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +dependencies = [ + "prost 0.12.3", +] + [[package]] name = "protobuf" version = "2.28.0" @@ -2914,7 +2979,7 @@ dependencies = [ "num-traits", "once_cell", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "ripemd", "serde 1.0.196", "serde_bytes", @@ -2924,7 +2989,7 @@ dependencies = [ "signature 2.2.0", "subtle", "subtle-encoding", - "tendermint-proto", + "tendermint-proto 0.32.2", "time", "zeroize", ] @@ -2954,7 +3019,25 @@ dependencies = [ "num-derive", "num-traits", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", + "serde 1.0.196", + "serde_bytes", + "subtle-encoding", + "time", +] + +[[package]] +name = "tendermint-proto" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b797dd3d2beaaee91d2f065e7bdf239dc8d80bba4a183a288bc1279dd5a69a1e" +dependencies = [ + "bytes", + "flex-error", + "num-derive", + "num-traits", + "prost 0.12.3", + "prost-types 0.12.3", "serde 1.0.196", "serde_bytes", "subtle-encoding", @@ -2986,7 +3069,7 @@ dependencies = [ "subtle-encoding", "tendermint", "tendermint-config", - "tendermint-proto", + "tendermint-proto 0.32.2", "thiserror", "time", "tokio", @@ -3017,7 +3100,7 @@ dependencies = [ "prost 0.11.9", "serde 1.0.196", "serde_json 1.0.111", - "tendermint-proto", + "tendermint-proto 0.32.2", "thiserror", ] diff --git a/contracts/injective-cosmwasm-mock/Cargo.toml b/contracts/injective-cosmwasm-mock/Cargo.toml index 4752b9fb..9b9a55ad 100644 --- a/contracts/injective-cosmwasm-mock/Cargo.toml +++ b/contracts/injective-cosmwasm-mock/Cargo.toml @@ -31,17 +31,23 @@ optimize = """docker run --rm -v "$(pwd)":/code \ [dependencies] cosmwasm-std = { version = "1.5.0", features = [ "abort", "cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4", "iterator", "stargate" ] } -cw-storage-plus = "1.2.0" -cw2 = "0.16.0" +cw-storage-plus = { version = "1.2.0" } +cw2 = { version = "0.16.0" } injective-cosmwasm = { path = "../../packages/injective-cosmwasm" } injective-math = { path = "../../packages/injective-math" } -schemars = { version ="0.8.16"} +injective-protobuf = { path = "../../packages/injective-protobuf"} +schemars = { version ="0.8.16"} serde = { version = "1.0.196", default-features = false, features = [ "derive" ] } thiserror = { version = "1.0.56" } -protobuf = "3.3.0" -prost = "0.11.9" +protobuf = { version = "3.3.0" } +prost = { version = "0.11.9" } injective-std = { version = "0.1.5" } +cosmos-sdk-proto = { version = "0.20.0", default-features = false } +cosmwasm-schema = { version = "1.5.0" } + + [dev-dependencies] -injective-test-tube = "1.1.7" -injective-std = { version = "0.1.5" } +injective-test-tube = { version = "1.1.7" } +injective-std = { version = "0.1.5" } +injective-testing = { version = "0.1.6" } diff --git a/contracts/injective-cosmwasm-mock/src/contract.rs b/contracts/injective-cosmwasm-mock/src/contract.rs index 207ea3f9..40ddcba7 100644 --- a/contracts/injective-cosmwasm-mock/src/contract.rs +++ b/contracts/injective-cosmwasm-mock/src/contract.rs @@ -1,23 +1,28 @@ -use crate::msg::MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT; -use crate::order_management::{create_spot_market_order, create_stargate_msg}; use crate::{ error::ContractError, + handle::{handle_test_transient_derivative_order, handle_test_transient_spot_order}, msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, - types, + query::{ + handle_aggregate_account_volume_query, handle_aggregate_market_volume_query, handle_contract_registration_info_query, + handle_derivative_market_mid_price_and_tob_query, handle_derivative_market_orderbook_query, handle_derivative_market_query, + handle_derivative_orders_to_cancel_up_to_amount_query, handle_effective_subaccount_position_query, handle_exchange_params_query, + handle_market_atomic_execution_fee_multiplier_query, handle_market_volatility_query, handle_oracle_price_query, + handle_oracle_volatility_query, handle_perpetual_market_funding_query, handle_perpetual_market_info_query, handle_pyth_price_query, + handle_spot_market_mid_price_and_tob_query, handle_spot_market_orderbook_query, handle_spot_market_query, + handle_spot_orders_to_cancel_up_to_amount_query, handle_staked_amount_query, handle_subaccount_deposit_query, + handle_token_factory_creation_fee, handle_token_factory_denom_total_supply, handle_trader_derivative_orders_query, + handle_trader_spot_orders_query, handle_vanilla_subaccount_position_query, + }, + reply::{handle_create_derivative_order_reply, handle_create_order_reply}, }; - -use cosmos_sdk_proto::{cosmos::authz::v1beta1::MsgExec, traits::Message, Any}; -use cosmwasm_std::{entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, ReplyOn, Response, StdResult, SubMsg}; +use cosmwasm_std::{entry_point, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdResult}; use cw2::set_contract_version; -use injective_cosmwasm::{create_deposit_msg, InjectiveMsgWrapper, InjectiveQuerier, InjectiveQueryWrapper, OrderType}; -use injective_math::FPDecimal; -use prost::Message; +use injective_cosmwasm::{create_deposit_msg, InjectiveMsgWrapper, InjectiveQuerier, InjectiveQueryWrapper}; const CONTRACT_NAME: &str = "crates.io:injective:dummy"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); - pub const CREATE_SPOT_ORDER_REPLY_ID: u64 = 0u64; - +pub const CREATE_DERIVATIVE_ORDER_REPLY_ID: u64 = 1u64; pub const MSG_EXEC: &str = "/cosmos.authz.v1beta1.MsgExec"; #[cfg_attr(not(feature = "library"), entry_point)] @@ -37,64 +42,40 @@ pub fn execute( ExecuteMsg::TestDepositMsg { subaccount_id, amount } => { Ok(Response::new().add_message(create_deposit_msg(env.contract.address, subaccount_id, amount))) } - ExecuteMsg::TestTraderTransientSpotOrders { market_id, subaccount_id } => { - let querier: InjectiveQuerier = InjectiveQuerier::new(&deps.querier); - let spot_market = querier.query_spot_market(&market_id).unwrap().market.unwrap(); - - deps.api.debug(&info.sender.as_str()); - let order_msg = create_spot_market_order( - FPDecimal::must_from_str("1"), - FPDecimal::must_from_str("1"), - OrderType::Buy, - &info.sender.as_str(), - subaccount_id.as_str(), - &spot_market, - ); - - let mut order_bytes = vec![]; - types::MsgCreateSpotMarketOrder::encode(&order_msg, &mut order_bytes).unwrap(); - - let msg_exec = MsgExec { - grantee: env.contract.address.to_string(), - msgs: vec![Any { - type_url: MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT.to_string(), - value: order_bytes, - }], - }; - - let order_submessage = SubMsg::reply_on_success( - create_stargate_msg(MSG_EXEC, msg_exec.encode_to_vec().into()).unwrap(), - CREATE_SPOT_ORDER_REPLY_ID, - ); - - Ok(Response::new().add_submessage(order_submessage)) - } - ExecuteMsg::TestTraderTransientDerivativeOrders { market_id, subaccount_id } => { - // to_json_binary(&querier.query_trader_transient_derivative_orders(&market_id, &subaccount_id)?) - Ok(Default::default()) - } + ExecuteMsg::TestTraderTransientSpotOrders { + market_id, + subaccount_id, + price, + quantity, + } => handle_test_transient_spot_order(deps, env, &info, market_id, subaccount_id, price, quantity), + ExecuteMsg::TestTraderTransientDerivativeOrders { + market_id, + subaccount_id, + price, + quantity, + margin, + } => handle_test_transient_derivative_order(deps, env, &info, market_id, subaccount_id, price, quantity, margin), } } #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { - let querier: InjectiveQuerier = InjectiveQuerier::new(&deps.querier); - + let querier = InjectiveQuerier::new(&deps.querier); match msg { - QueryMsg::TestExchangeParamsQuery {} => to_json_binary(&querier.query_exchange_params()?), - QueryMsg::TestSubAccountDepositQuery { subaccount_id, denom } => to_json_binary(&querier.query_subaccount_deposit(&subaccount_id, &denom)?), - QueryMsg::TestSpotMarketQuery { market_id } => to_json_binary(&querier.query_spot_market(&market_id)?), - QueryMsg::TestDerivativeMarketQuery { market_id } => to_json_binary(&querier.query_derivative_market(&market_id)?), + QueryMsg::TestExchangeParamsQuery {} => handle_exchange_params_query(&querier), + QueryMsg::TestSubAccountDepositQuery { subaccount_id, denom } => handle_subaccount_deposit_query(&querier, &subaccount_id, denom), + QueryMsg::TestSpotMarketQuery { market_id } => handle_spot_market_query(&querier, &market_id), + QueryMsg::TestDerivativeMarketQuery { market_id } => handle_derivative_market_query(&querier, &market_id), QueryMsg::TestEffectiveSubaccountPosition { market_id, subaccount_id } => { - to_json_binary(&querier.query_effective_subaccount_position(&market_id, &subaccount_id)?) + handle_effective_subaccount_position_query(&querier, &market_id, &subaccount_id) } QueryMsg::TestVanillaSubaccountPosition { market_id, subaccount_id } => { - to_json_binary(&querier.query_vanilla_subaccount_position(&market_id, &subaccount_id)?) + handle_vanilla_subaccount_position_query(&querier, &market_id, &subaccount_id) } QueryMsg::TestTraderDerivativeOrders { market_id, subaccount_id } => { - to_json_binary(&querier.query_trader_derivative_orders(&market_id, &subaccount_id)?) + handle_trader_derivative_orders_query(&querier, &market_id, &subaccount_id) } - QueryMsg::TestTraderSpotOrders { market_id, subaccount_id } => to_json_binary(&querier.query_trader_spot_orders(&market_id, &subaccount_id)?), + QueryMsg::TestTraderSpotOrders { market_id, subaccount_id } => handle_trader_spot_orders_query(&querier, &market_id, &subaccount_id), QueryMsg::TestSpotOrdersToCancelUpToAmount { market_id, subaccount_id, @@ -102,63 +83,70 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Std quote_amount, strategy, reference_price, - } => to_json_binary(&querier.query_spot_orders_to_cancel_up_to_amount( + } => handle_spot_orders_to_cancel_up_to_amount_query( + &querier, &market_id, &subaccount_id, base_amount, quote_amount, strategy, reference_price, - )?), + ), QueryMsg::TestDerivativeOrdersToCancelUpToAmount { market_id, subaccount_id, quote_amount, strategy, reference_price, - } => to_json_binary(&querier.query_derivative_orders_to_cancel_up_to_amount( - &market_id, - &subaccount_id, - quote_amount, - strategy, - reference_price, - )?), - QueryMsg::TestPerpetualMarketInfo { market_id } => to_json_binary(&querier.query_perpetual_market_info(&market_id)?), - QueryMsg::TestPerpetualMarketFunding { market_id } => to_json_binary(&querier.query_perpetual_market_funding(&market_id)?), + } => handle_derivative_orders_to_cancel_up_to_amount_query(&querier, &market_id, &subaccount_id, quote_amount, strategy, reference_price), + QueryMsg::TestPerpetualMarketInfo { market_id } => handle_perpetual_market_info_query(&querier, &market_id), + QueryMsg::TestPerpetualMarketFunding { market_id } => handle_perpetual_market_funding_query(&querier, &market_id), QueryMsg::TestMarketVolatility { market_id, trade_grouping_sec, max_age, include_raw_history, include_metadata, - } => to_json_binary(&querier.query_market_volatility(&market_id, trade_grouping_sec, max_age, include_raw_history, include_metadata)?), - QueryMsg::TestDerivativeMarketMidPriceAndTob { market_id } => to_json_binary(&querier.query_derivative_market_mid_price_and_tob(&market_id)?), - QueryMsg::TestAggregateMarketVolume { market_id } => to_json_binary(&querier.query_aggregate_market_volume(&market_id)?), - QueryMsg::TestAggregateAccountVolume { account_id } => to_json_binary(&querier.query_aggregate_account_volume(&account_id)?), - QueryMsg::TestSpotMarketMidPriceAndTob { market_id } => to_json_binary(&querier.query_spot_market_mid_price_and_tob(&market_id)?), + } => handle_market_volatility_query(&querier, &market_id, trade_grouping_sec, max_age, include_raw_history, include_metadata), + QueryMsg::TestDerivativeMarketMidPriceAndTob { market_id } => handle_derivative_market_mid_price_and_tob_query(&querier, &market_id), + QueryMsg::TestAggregateMarketVolume { market_id } => handle_aggregate_market_volume_query(&querier, &market_id), + QueryMsg::TestAggregateAccountVolume { account_id } => handle_aggregate_account_volume_query(&querier, account_id), + QueryMsg::TestSpotMarketMidPriceAndTob { market_id } => handle_spot_market_mid_price_and_tob_query(&querier, &market_id), QueryMsg::TestSpotMarketOrderbook { market_id, side, limit_cumulative_quantity, limit_cumulative_notional, - } => to_json_binary(&querier.query_spot_market_orderbook(&market_id, side, limit_cumulative_quantity, limit_cumulative_notional)?), + } => handle_spot_market_orderbook_query(&querier, &market_id, side, limit_cumulative_quantity, limit_cumulative_notional), QueryMsg::TestDerivativeMarketOrderbook { market_id, limit_cumulative_notional, - } => to_json_binary(&querier.query_derivative_market_orderbook(&market_id, limit_cumulative_notional)?), - QueryMsg::TestMarketAtomicExecutionFeeMultiplier { market_id } => { - to_json_binary(&querier.query_market_atomic_execution_fee_multiplier(&market_id)?) - } + } => handle_derivative_market_orderbook_query(&querier, &market_id, limit_cumulative_notional), + QueryMsg::TestMarketAtomicExecutionFeeMultiplier { market_id } => handle_market_atomic_execution_fee_multiplier_query(&querier, &market_id), + QueryMsg::TestQueryOracleVolatility { + base_info, + quote_info, + max_age, + include_raw_history, + include_metadata, + } => handle_oracle_volatility_query(&querier, base_info, quote_info, max_age, include_raw_history, include_metadata), + QueryMsg::TestQueryOraclePrice { oracle_type, base, quote } => handle_oracle_price_query(&querier, &oracle_type, base, quote), + QueryMsg::TestQueryPythPrice { price_id } => handle_pyth_price_query(&querier, price_id), + QueryMsg::TestQueryStakedAmount { + delegator_address, + max_delegations, + } => handle_staked_amount_query(&querier, deps.api.addr_validate(delegator_address.as_str())?, max_delegations), + QueryMsg::TestQueryTokenFactoryDenomTotalSupply { denom } => handle_token_factory_denom_total_supply(&querier, denom), + QueryMsg::TestQueryTokenFactoryCreationFee {} => handle_token_factory_creation_fee(&querier), + QueryMsg::TestQueryContractRegistrationInfo { contract_address } => handle_contract_registration_info_query(&querier, contract_address), } } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result { +pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result { match msg.id { - CREATE_SPOT_ORDER_REPLY_ID => { - deps.api.debug("I am here"); - Ok(Default::default()) - } + CREATE_SPOT_ORDER_REPLY_ID => handle_create_order_reply(deps, &msg), + CREATE_DERIVATIVE_ORDER_REPLY_ID => handle_create_derivative_order_reply(deps, &msg), _ => Err(ContractError::UnrecognizedReply(msg.id)), } } diff --git a/contracts/injective-cosmwasm-mock/src/error.rs b/contracts/injective-cosmwasm-mock/src/error.rs index 877d5c9f..54dea889 100644 --- a/contracts/injective-cosmwasm-mock/src/error.rs +++ b/contracts/injective-cosmwasm-mock/src/error.rs @@ -7,4 +7,8 @@ pub enum ContractError { Std(#[from] StdError), #[error("Unrecognized reply id: {0}")] UnrecognizedReply(u64), + #[error("Invalid reply from sub-message {id}, {err}")] + ReplyParseFailure { id: u64, err: String }, + #[error("Failure response from submsg: {0}")] + SubMsgFailure(String), } diff --git a/contracts/injective-cosmwasm-mock/src/handle.rs b/contracts/injective-cosmwasm-mock/src/handle.rs new file mode 100644 index 00000000..39f6e40d --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/handle.rs @@ -0,0 +1,112 @@ +use crate::{ + contract::{CREATE_DERIVATIVE_ORDER_REPLY_ID, CREATE_SPOT_ORDER_REPLY_ID, MSG_EXEC}, + msg::{MSG_CREATE_DERIVATIVE_LIMIT_ORDER_ENDPOINT, MSG_CREATE_SPOT_LIMIT_ORDER_ENDPOINT}, + order_management::{create_derivative_limit_order, create_spot_limit_order, create_stargate_msg, encode_bytes_message}, + state::{CacheOrderInfo, ORDER_CALL_CACHE}, + ContractError, +}; +use cosmos_sdk_proto::{cosmos::authz::v1beta1::MsgExec, traits::Message, Any}; +use cosmwasm_std::{DepsMut, Env, MessageInfo, Response, SubMsg}; +use injective_cosmwasm::{InjectiveMsgWrapper, InjectiveQuerier, InjectiveQueryWrapper, MarketId, OrderType, SubaccountId}; +use injective_math::{scale::Scaled, FPDecimal}; + +pub fn handle_test_transient_spot_order( + deps: DepsMut, + env: Env, + info: &MessageInfo, + market_id: MarketId, + subaccount_id: SubaccountId, + price: String, + quantity: String, +) -> Result, ContractError> { + let querier = InjectiveQuerier::new(&deps.querier); + let spot_market = querier.query_spot_market(&market_id).unwrap().market.unwrap(); + + let order_msg = create_spot_limit_order( + FPDecimal::must_from_str(price.as_str()).scaled(18i32), + FPDecimal::must_from_str(quantity.as_str()).scaled(18i32), + OrderType::Sell, + info.sender.as_str(), + subaccount_id.as_str(), + &spot_market, + ); + + let order_bytes = encode_bytes_message(&order_msg).unwrap(); + + let msg_exec = MsgExec { + grantee: env.contract.address.to_string(), + msgs: vec![Any { + type_url: MSG_CREATE_SPOT_LIMIT_ORDER_ENDPOINT.to_string(), + value: order_bytes, + }], + }; + + let order_submessage = SubMsg::reply_on_success( + create_stargate_msg(MSG_EXEC, msg_exec.encode_to_vec()).unwrap(), + CREATE_SPOT_ORDER_REPLY_ID, + ); + + save_cache_info(deps, market_id, subaccount_id)?; + + Ok(Response::new().add_submessage(order_submessage)) +} + +pub fn handle_test_transient_derivative_order( + deps: DepsMut, + env: Env, + info: &MessageInfo, + market_id: MarketId, + subaccount_id: SubaccountId, + price: String, + quantity: String, + margin: String, +) -> Result, ContractError> { + let querier: InjectiveQuerier = InjectiveQuerier::new(&deps.querier); + let market = querier.query_derivative_market(&market_id).unwrap().market.unwrap(); + + let order_msg = create_derivative_limit_order( + FPDecimal::must_from_str(price.as_str()).scaled(18i32), + FPDecimal::must_from_str(quantity.as_str()).scaled(18i32), + FPDecimal::must_from_str(margin.as_str()).scaled(18i32), + OrderType::Buy, + info.sender.as_str(), + subaccount_id.as_str(), + &market, + ); + + let order_bytes = encode_bytes_message(&order_msg).unwrap(); + + let msg_exec = MsgExec { + grantee: env.contract.address.to_string(), + msgs: vec![Any { + type_url: MSG_CREATE_DERIVATIVE_LIMIT_ORDER_ENDPOINT.to_string(), + value: order_bytes, + }], + }; + + let order_submessage = SubMsg::reply_on_success( + create_stargate_msg(MSG_EXEC, msg_exec.encode_to_vec()).unwrap(), + CREATE_DERIVATIVE_ORDER_REPLY_ID, + ); + + save_cache_info(deps, market_id, subaccount_id)?; + + Ok(Response::new().add_submessage(order_submessage)) +} + +fn save_cache_info(deps: DepsMut, market_id: MarketId, subaccount_id: SubaccountId) -> Result<(), ContractError> { + let cache_order_info = CacheOrderInfo { + subaccount: subaccount_id, + market_id, + }; + + let mut order_cache = match ORDER_CALL_CACHE.may_load(deps.storage)? { + Some(order_cache) => order_cache, + None => vec![], + }; + + order_cache.push(cache_order_info); + + ORDER_CALL_CACHE.save(deps.storage, &order_cache)?; + Ok(()) +} diff --git a/contracts/injective-cosmwasm-mock/src/lib.rs b/contracts/injective-cosmwasm-mock/src/lib.rs index 8e4615c5..9a4726e1 100644 --- a/contracts/injective-cosmwasm-mock/src/lib.rs +++ b/contracts/injective-cosmwasm-mock/src/lib.rs @@ -1,12 +1,14 @@ pub mod contract; mod error; +mod handle; pub mod msg; +mod order_management; +mod query; +mod reply; +mod state; #[cfg(test)] mod testing; - -mod order_management; mod types; #[cfg(test)] pub mod utils; - pub use crate::error::ContractError; diff --git a/contracts/injective-cosmwasm-mock/src/msg.rs b/contracts/injective-cosmwasm-mock/src/msg.rs index d02db8a3..ae2a95ad 100644 --- a/contracts/injective-cosmwasm-mock/src/msg.rs +++ b/contracts/injective-cosmwasm-mock/src/msg.rs @@ -1,11 +1,10 @@ use cosmwasm_std::Coin; -use injective_cosmwasm::{CancellationStrategy, MarketId, OrderSide, SubaccountId}; +use injective_cosmwasm::{CancellationStrategy, MarketId, OracleInfo, OracleType, OrderSide, SubaccountId}; use injective_math::FPDecimal; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; - -pub const MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT: &str = - "/injective.exchange.v1beta1.MsgCreateSpotMarketOrder"; +pub const MSG_CREATE_SPOT_LIMIT_ORDER_ENDPOINT: &str = "/injective.exchange.v1beta1.MsgCreateSpotLimitOrder"; +pub const MSG_CREATE_DERIVATIVE_LIMIT_ORDER_ENDPOINT: &str = "/injective.exchange.v1beta1.MsgCreateDerivativeLimitOrder"; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct InstantiateMsg {} @@ -13,9 +12,23 @@ pub struct InstantiateMsg {} #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum ExecuteMsg { - TestDepositMsg { subaccount_id: SubaccountId, amount: Coin }, - TestTraderTransientSpotOrders { market_id: MarketId, subaccount_id: SubaccountId }, - TestTraderTransientDerivativeOrders { market_id: MarketId, subaccount_id: SubaccountId }, + TestDepositMsg { + subaccount_id: SubaccountId, + amount: Coin, + }, + TestTraderTransientSpotOrders { + market_id: MarketId, + subaccount_id: SubaccountId, + price: String, + quantity: String, + }, + TestTraderTransientDerivativeOrders { + market_id: MarketId, + subaccount_id: SubaccountId, + price: String, + quantity: String, + margin: String, + }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] @@ -101,4 +114,30 @@ pub enum QueryMsg { TestMarketAtomicExecutionFeeMultiplier { market_id: MarketId, }, + TestQueryOracleVolatility { + base_info: Option, + quote_info: Option, + max_age: u64, + include_raw_history: bool, + include_metadata: bool, + }, + TestQueryOraclePrice { + oracle_type: OracleType, + base: String, + quote: String, + }, + TestQueryPythPrice { + price_id: String, + }, + TestQueryStakedAmount { + delegator_address: String, + max_delegations: u16, + }, + TestQueryTokenFactoryDenomTotalSupply { + denom: String, + }, + TestQueryTokenFactoryCreationFee {}, + TestQueryContractRegistrationInfo { + contract_address: String, + }, } diff --git a/contracts/injective-cosmwasm-mock/src/order_management.rs b/contracts/injective-cosmwasm-mock/src/order_management.rs index d991a3cc..158f5bd5 100644 --- a/contracts/injective-cosmwasm-mock/src/order_management.rs +++ b/contracts/injective-cosmwasm-mock/src/order_management.rs @@ -1,8 +1,8 @@ use crate::types; -use cosmwasm_std::{to_json_binary, Coin, CosmosMsg, StdResult, SubMsg, Uint128, WasmMsg}; -use injective_cosmwasm::{InjectiveMsgWrapper, OrderType, SpotMarket}; +use cosmwasm_std::{CosmosMsg, StdResult}; +use injective_cosmwasm::{FullDerivativeMarket, InjectiveMsgWrapper, OrderType, SpotMarket}; use injective_math::FPDecimal; - +use prost::Message; pub fn create_stargate_msg(type_url: &str, value: Vec) -> StdResult> { Ok(CosmosMsg::Stargate { @@ -11,15 +11,15 @@ pub fn create_stargate_msg(type_url: &str, value: Vec) -> StdResult types::MsgCreateSpotMarketOrder { - types::MsgCreateSpotMarketOrder { +) -> types::MsgCreateSpotLimitOrder { + types::MsgCreateSpotLimitOrder { sender: sender.to_string(), order: Some(types::SpotOrder { market_id: market.market_id.as_str().into(), @@ -34,3 +34,37 @@ pub fn create_spot_market_order( }), } } + +pub fn create_derivative_limit_order( + price: FPDecimal, + quantity: FPDecimal, + margin: FPDecimal, + order_type: OrderType, + sender: &str, + subaccount_id: &str, + market: &FullDerivativeMarket, +) -> types::MsgCreateDerivativeLimitOrder { + let market_id = market.market.as_ref().unwrap().market_id.as_str().to_string(); + + types::MsgCreateDerivativeLimitOrder { + sender: sender.to_string(), + order: Some(types::DerivativeOrder { + market_id, + order_info: Some(types::OrderInfo { + subaccount_id: subaccount_id.to_string(), + fee_recipient: sender.to_string(), + price: price.to_string(), + quantity: quantity.to_string(), + }), + order_type: order_type as i32, + margin: margin.to_string(), + trigger_price: "".to_string(), + }), + } +} + +pub(crate) fn encode_bytes_message(order_msg: &T) -> Result, prost::EncodeError> { + let mut buffer = Vec::new(); + order_msg.encode(&mut buffer)?; // Encode the message using prost + Ok(buffer) +} diff --git a/contracts/injective-cosmwasm-mock/src/query.rs b/contracts/injective-cosmwasm-mock/src/query.rs new file mode 100644 index 00000000..17d3c120 --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/query.rs @@ -0,0 +1,161 @@ +use cosmwasm_std::{to_json_binary, Addr, Binary, StdResult}; +use injective_cosmwasm::{CancellationStrategy, InjectiveQuerier, MarketId, OracleInfo, OracleType, OrderSide, SubaccountId}; +use injective_math::FPDecimal; + +pub fn handle_exchange_params_query(querier: &InjectiveQuerier) -> StdResult { + to_json_binary(&querier.query_exchange_params()?) +} + +pub fn handle_subaccount_deposit_query(querier: &InjectiveQuerier, subaccount_id: &SubaccountId, denom: String) -> StdResult { + to_json_binary(&querier.query_subaccount_deposit(subaccount_id, &denom)?) +} + +pub fn handle_spot_market_query(querier: &InjectiveQuerier, market_id: &MarketId) -> StdResult { + to_json_binary(&querier.query_spot_market(market_id)?) +} + +pub fn handle_derivative_market_query(querier: &InjectiveQuerier, market_id: &MarketId) -> StdResult { + to_json_binary(&querier.query_derivative_market(market_id)?) +} + +pub fn handle_effective_subaccount_position_query( + querier: &InjectiveQuerier, + market_id: &MarketId, + subaccount_id: &SubaccountId, +) -> StdResult { + to_json_binary(&querier.query_effective_subaccount_position(market_id, subaccount_id)?) +} + +pub fn handle_vanilla_subaccount_position_query(querier: &InjectiveQuerier, market_id: &MarketId, subaccount_id: &SubaccountId) -> StdResult { + to_json_binary(&querier.query_vanilla_subaccount_position(market_id, subaccount_id)?) +} + +pub fn handle_trader_derivative_orders_query(querier: &InjectiveQuerier, market_id: &MarketId, subaccount_id: &SubaccountId) -> StdResult { + to_json_binary(&querier.query_trader_derivative_orders(market_id, subaccount_id)?) +} + +pub fn handle_trader_spot_orders_query(querier: &InjectiveQuerier, market_id: &MarketId, subaccount_id: &SubaccountId) -> StdResult { + to_json_binary(&querier.query_trader_spot_orders(market_id, subaccount_id)?) +} + +pub fn handle_spot_orders_to_cancel_up_to_amount_query( + querier: &InjectiveQuerier, + market_id: &MarketId, + subaccount_id: &SubaccountId, + base_amount: FPDecimal, + quote_amount: FPDecimal, + strategy: CancellationStrategy, + reference_price: Option, +) -> StdResult { + to_json_binary(&querier.query_spot_orders_to_cancel_up_to_amount( + market_id, + subaccount_id, + base_amount, + quote_amount, + strategy, + reference_price, + )?) +} + +pub fn handle_derivative_orders_to_cancel_up_to_amount_query( + querier: &InjectiveQuerier, + market_id: &MarketId, + subaccount_id: &SubaccountId, + quote_amount: FPDecimal, + strategy: CancellationStrategy, + reference_price: Option, +) -> StdResult { + to_json_binary(&querier.query_derivative_orders_to_cancel_up_to_amount(market_id, subaccount_id, quote_amount, strategy, reference_price)?) +} + +pub fn handle_perpetual_market_info_query(querier: &InjectiveQuerier, market_id: &MarketId) -> StdResult { + to_json_binary(&querier.query_perpetual_market_info(market_id)?) +} + +pub fn handle_perpetual_market_funding_query(querier: &InjectiveQuerier, market_id: &MarketId) -> StdResult { + to_json_binary(&querier.query_perpetual_market_funding(market_id)?) +} + +pub fn handle_market_volatility_query( + querier: &InjectiveQuerier, + market_id: &MarketId, + trade_grouping_sec: u64, + max_age: u64, + include_raw_history: bool, + include_metadata: bool, +) -> StdResult { + to_json_binary(&querier.query_market_volatility(market_id, trade_grouping_sec, max_age, include_raw_history, include_metadata)?) +} + +pub fn handle_derivative_market_mid_price_and_tob_query(querier: &InjectiveQuerier, market_id: &MarketId) -> StdResult { + to_json_binary(&querier.query_derivative_market_mid_price_and_tob(market_id)?) +} + +pub fn handle_aggregate_market_volume_query(querier: &InjectiveQuerier, market_id: &MarketId) -> StdResult { + to_json_binary(&querier.query_aggregate_market_volume(market_id)?) +} + +pub fn handle_aggregate_account_volume_query(querier: &InjectiveQuerier, account_id: String) -> StdResult { + to_json_binary(&querier.query_aggregate_account_volume(&account_id)?) +} + +pub fn handle_spot_market_mid_price_and_tob_query(querier: &InjectiveQuerier, market_id: &MarketId) -> StdResult { + to_json_binary(&querier.query_spot_market_mid_price_and_tob(market_id)?) +} + +pub fn handle_spot_market_orderbook_query( + querier: &InjectiveQuerier, + market_id: &MarketId, + side: OrderSide, + limit_cumulative_quantity: Option, + limit_cumulative_notional: Option, +) -> StdResult { + to_json_binary(&querier.query_spot_market_orderbook(market_id, side, limit_cumulative_quantity, limit_cumulative_notional)?) +} + +pub fn handle_derivative_market_orderbook_query( + querier: &InjectiveQuerier, + market_id: &MarketId, + limit_cumulative_notional: FPDecimal, +) -> StdResult { + to_json_binary(&querier.query_derivative_market_orderbook(market_id, limit_cumulative_notional)?) +} + +pub fn handle_market_atomic_execution_fee_multiplier_query(querier: &InjectiveQuerier, market_id: &MarketId) -> StdResult { + to_json_binary(&querier.query_market_atomic_execution_fee_multiplier(market_id)?) +} + +pub fn handle_oracle_volatility_query( + querier: &InjectiveQuerier, + base_info: Option, + quote_info: Option, + max_age: u64, + include_raw_history: bool, + include_metadata: bool, +) -> StdResult { + to_json_binary(&querier.query_oracle_volatility(&base_info, "e_info, max_age, include_raw_history, include_metadata)?) +} + +pub fn handle_oracle_price_query(querier: &InjectiveQuerier, oracle_type: &OracleType, base: String, quote: String) -> StdResult { + to_json_binary(&querier.query_oracle_price(oracle_type, &base, "e)?) +} + +pub fn handle_pyth_price_query(querier: &InjectiveQuerier, price_id: String) -> StdResult { + to_json_binary(&querier.query_pyth_price(price_id.as_str())?) +} + +pub fn handle_token_factory_denom_total_supply(querier: &InjectiveQuerier, denom: String) -> StdResult { + to_json_binary(&querier.query_token_factory_denom_total_supply(&denom)?) +} + +pub fn handle_token_factory_creation_fee(querier: &InjectiveQuerier) -> StdResult { + to_json_binary(&querier.query_token_factory_creation_fee()?) +} + +pub fn handle_staked_amount_query(querier: &InjectiveQuerier, delegator_address: Addr, max_delegations: u16) -> StdResult { + to_json_binary(&querier.query_staked_amount(delegator_address, max_delegations)?) +} + +pub fn handle_contract_registration_info_query(querier: &InjectiveQuerier, contract_address: String) -> StdResult { + to_json_binary(&querier.query_contract_registration_info(&contract_address)?) +} diff --git a/contracts/injective-cosmwasm-mock/src/reply.rs b/contracts/injective-cosmwasm-mock/src/reply.rs new file mode 100644 index 00000000..78fe2c70 --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/reply.rs @@ -0,0 +1,39 @@ +use crate::state::ORDER_CALL_CACHE; +use crate::ContractError; +use cosmwasm_std::{DepsMut, Event, Reply, Response}; +use injective_cosmwasm::{InjectiveQuerier, InjectiveQueryWrapper}; + +pub fn handle_create_order_reply(deps: DepsMut, _msg: &Reply) -> Result { + let mut response_str = "Something went wrong".to_string(); + + let querier: InjectiveQuerier = InjectiveQuerier::new(&deps.querier); + + if let Some(mut cache) = ORDER_CALL_CACHE.may_load(deps.storage)? { + if !cache.is_empty() { + let order_info = &cache[0]; + let response = querier.query_trader_transient_spot_orders(&order_info.market_id, &order_info.subaccount); + response_str = format!("{:?}", &response); + cache.clear(); + ORDER_CALL_CACHE.save(deps.storage, &cache)?; + } + }; + + Ok(Response::new().add_event(Event::new("transient_order").add_attributes([("query_str", response_str)]))) +} + +pub fn handle_create_derivative_order_reply(deps: DepsMut, _msg: &Reply) -> Result { + let mut response_str = "Something went wrong".to_string(); + let querier: InjectiveQuerier = InjectiveQuerier::new(&deps.querier); + + if let Some(mut cache) = ORDER_CALL_CACHE.may_load(deps.storage)? { + if !cache.is_empty() { + let order_info = &cache[0]; + let response = querier.query_trader_transient_derivative_orders(&order_info.market_id, &order_info.subaccount); + response_str = format!("{:?}", &response); + cache.clear(); + ORDER_CALL_CACHE.save(deps.storage, &cache)?; + } + }; + + Ok(Response::new().add_event(Event::new("transient_derivative_order").add_attributes([("query_str", response_str)]))) +} diff --git a/contracts/injective-cosmwasm-mock/src/state.rs b/contracts/injective-cosmwasm-mock/src/state.rs new file mode 100644 index 00000000..4f4d8280 --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/state.rs @@ -0,0 +1,11 @@ +use cosmwasm_schema::cw_serde; +use cw_storage_plus::Item; +use injective_cosmwasm::{MarketId, SubaccountId}; + +pub const ORDER_CALL_CACHE: Item> = Item::new("order_call_cache"); + +#[cw_serde] +pub struct CacheOrderInfo { + pub subaccount: SubaccountId, + pub market_id: MarketId, +} diff --git a/contracts/injective-cosmwasm-mock/src/testing/mod.rs b/contracts/injective-cosmwasm-mock/src/testing/mod.rs index fb694d0c..c26da455 100644 --- a/contracts/injective-cosmwasm-mock/src/testing/mod.rs +++ b/contracts/injective-cosmwasm-mock/src/testing/mod.rs @@ -1 +1,6 @@ -mod query_exchange_test; +mod test_exchange; +mod test_exchange_derivative; +mod test_oracle; +mod test_staking; +mod test_token_factory; +mod test_wasmx; diff --git a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs b/contracts/injective-cosmwasm-mock/src/testing/test_exchange.rs similarity index 52% rename from contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs rename to contracts/injective-cosmwasm-mock/src/testing/test_exchange.rs index 00d4e925..9db7b659 100644 --- a/contracts/injective-cosmwasm-mock/src/testing/query_exchange_test.rs +++ b/contracts/injective-cosmwasm-mock/src/testing/test_exchange.rs @@ -1,31 +1,24 @@ use crate::{ msg::{ExecuteMsg, QueryMsg}, utils::{ - add_derivative_order_as, add_derivative_orders, add_perp_initial_liquidity, add_spot_initial_liquidity, add_spot_order_as, add_spot_orders, - dec_to_proto, get_initial_liquidity_orders_vector, get_initial_perp_liquidity_orders_vector, get_perpetual_market_id, get_spot_market_id, - human_to_dec, human_to_proto, scale_price_quantity_for_spot_market, scale_price_quantity_perp_market, str_coin, ExchangeType, HumanOrder, - Setup, BASE_DECIMALS, BASE_DENOM, QUOTE_DECIMALS, QUOTE_DENOM, + add_spot_initial_liquidity, add_spot_order_as, add_spot_orders, dec_to_proto, execute_all_authorizations, + get_initial_liquidity_orders_vector, get_spot_market_id, human_to_dec, human_to_proto, scale_price_quantity_for_spot_market, + scale_price_quantity_for_spot_market_dec, str_coin, ExchangeType, HumanOrder, Setup, BASE_DECIMALS, BASE_DENOM, QUOTE_DECIMALS, QUOTE_DENOM, }, }; - -use crate::utils::execute_all_authorizations; use cosmwasm_std::{Addr, Coin}; -use injective_cosmwasm::exchange::response::QueryOrderbookResponse; -use injective_cosmwasm::exchange::types::VolumeByType; use injective_cosmwasm::{ - checked_address_to_subaccount_id, DerivativeMarketResponse, ExchangeParamsResponse, MarketId, MarketMidPriceAndTOBResponse, - MarketVolatilityResponse, OrderSide, PerpetualMarketFundingResponse, PerpetualMarketInfoResponse, PriceLevel, QueryAggregateVolumeResponse, - QueryMarketAtomicExecutionFeeMultiplierResponse, SpotMarketResponse, SubaccountDepositResponse, SubaccountEffectivePositionInMarketResponse, - SubaccountId, SubaccountPositionInMarketResponse, TraderDerivativeOrdersResponse, TraderSpotOrdersResponse, TrimmedDerivativeLimitOrder, - TrimmedSpotLimitOrder, + checked_address_to_subaccount_id, + exchange::{response::QueryOrderbookResponse, types::VolumeByType}, + CancellationStrategy, ExchangeParamsResponse, MarketId, MarketMidPriceAndTOBResponse, MarketVolatilityResponse, OrderSide, PriceLevel, + QueryAggregateVolumeResponse, QueryMarketAtomicExecutionFeeMultiplierResponse, SpotMarketResponse, SubaccountDepositResponse, SubaccountId, + TraderSpotOrdersResponse, TrimmedSpotLimitOrder, }; use injective_math::FPDecimal; use injective_std::types::injective::exchange::v1beta1::{ - Deposit, MsgDeposit, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, OrderType, QueryAggregateMarketVolumeResponse, - QuerySubaccountDepositsRequest, + Deposit, MsgDeposit, MsgInstantSpotMarketLaunch, OrderType, QueryAggregateMarketVolumeResponse, QuerySubaccountDepositsRequest, }; -use injective_test_tube::injective_cosmwasm::get_default_subaccount_id_for_checked_address; -use injective_test_tube::{Account, Exchange, Module, RunnerResult, Wasm}; +use injective_test_tube::{injective_cosmwasm::get_default_subaccount_id_for_checked_address, Account, Exchange, Module, RunnerResult, Wasm}; #[test] #[cfg_attr(not(feature = "integration"), ignore)] @@ -75,37 +68,24 @@ fn test_query_subaccount_deposit() { let subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(env.users[0].account.address()), 1u32); - { + let make_deposit = |amount: &str, denom_key: &str| { exchange .deposit( MsgDeposit { sender: env.users[0].account.address(), subaccount_id: subaccount_id.to_string(), amount: Some(injective_std::types::cosmos::base::v1beta1::Coin { - amount: "10000000000000000000".to_string(), - denom: env.denoms["base"].clone(), + amount: amount.to_string(), + denom: env.denoms[denom_key].clone(), }), }, &env.users[0].account, ) .unwrap(); - } + }; - { - exchange - .deposit( - MsgDeposit { - sender: env.users[0].account.address(), - subaccount_id: subaccount_id.to_string(), - amount: Some(injective_std::types::cosmos::base::v1beta1::Coin { - amount: "100000000".to_string(), - denom: env.denoms["quote"].clone(), - }), - }, - &env.users[0].account, - ) - .unwrap(); - } + make_deposit("10000000000000000000", "base"); + make_deposit("100000000", "quote"); let response = exchange .query_subaccount_deposits(&QuerySubaccountDepositsRequest { @@ -199,136 +179,6 @@ fn test_query_spot_market() { assert_eq!(response_market.min_quantity_tick_size.to_string(), min_quantity_tick_size.to_string()); } -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_derivative_market() { - let env = Setup::new(ExchangeType::None); - let wasm = Wasm::new(&env.app); - let exchange = Exchange::new(&env.app); - - let ticker = "INJ/USDT".to_string(); - let initial_margin_ratio = FPDecimal::must_from_str("0.195"); - let maintenance_margin_ratio = FPDecimal::must_from_str("0.05"); - let min_price_tick_size = FPDecimal::must_from_str("1000.0"); - let min_quantity_tick_size = FPDecimal::must_from_str("1000000000000000"); - let quote_denom = QUOTE_DENOM.to_string(); - let maker_fee_rate = FPDecimal::ZERO; - let taker_fee_rate = FPDecimal::ZERO; - - exchange - .instant_perpetual_market_launch( - MsgInstantPerpetualMarketLaunch { - sender: env.signer.address(), - ticker: ticker.to_owned(), - quote_denom: quote_denom.to_owned(), - oracle_base: BASE_DENOM.to_owned(), - oracle_quote: quote_denom.to_owned(), - oracle_scale_factor: 6u32, - oracle_type: 2i32, - maker_fee_rate: dec_to_proto(maker_fee_rate).to_string(), - taker_fee_rate: dec_to_proto(taker_fee_rate), - initial_margin_ratio: dec_to_proto(initial_margin_ratio), - maintenance_margin_ratio: dec_to_proto(maintenance_margin_ratio), - min_price_tick_size: dec_to_proto(min_price_tick_size), - min_quantity_tick_size: dec_to_proto(min_quantity_tick_size), - }, - &env.signer, - ) - .unwrap(); - - let derivative_market_id = get_perpetual_market_id(&exchange, ticker.to_owned()); - - let market_id = MarketId::new(derivative_market_id.clone()).unwrap(); - let query_msg = QueryMsg::TestDerivativeMarketQuery { market_id }; - let res: DerivativeMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - - let response_market = res.market.unwrap().market.unwrap(); - assert_eq!(response_market.market_id.as_str(), derivative_market_id); - assert_eq!(response_market.ticker, ticker); - assert_eq!(response_market.quote_denom, quote_denom); - assert_eq!(response_market.min_price_tick_size, min_price_tick_size); - assert_eq!(response_market.min_quantity_tick_size, min_quantity_tick_size); - assert_eq!(response_market.maker_fee_rate, maker_fee_rate); - assert_eq!(response_market.taker_fee_rate, taker_fee_rate); - assert_eq!(response_market.initial_margin_ratio, initial_margin_ratio); -} - -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_effective_subaccount_position() { - let env = Setup::new(ExchangeType::Derivative); - let wasm = Wasm::new(&env.app); - let market_id = env.market_id.unwrap(); - - add_perp_initial_liquidity(&env.app, market_id.clone()); - - let (price, quantity, margin) = scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); - - let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(env.users[1].account.address())) - .as_str() - .to_string(); - - add_derivative_order_as( - &env.app, - market_id.to_owned(), - &env.users[1].account, - price, - quantity, - OrderType::Sell, - margin, - ); - - let query_msg = QueryMsg::TestEffectiveSubaccountPosition { - market_id: MarketId::new(market_id.clone()).unwrap(), - subaccount_id: SubaccountId::new(subaccount_id.to_owned()).unwrap(), - }; - let res: SubaccountEffectivePositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - assert!(res.state.is_some()); -} - -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_vanilla_subaccount_position() { - let env = Setup::new(ExchangeType::Derivative); - let wasm = Wasm::new(&env.app); - let market_id = env.market_id.unwrap(); - - add_perp_initial_liquidity(&env.app, market_id.clone()); - - let (price, quantity, margin) = scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); - - let trader = &env.users[1]; - let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) - .as_str() - .to_string(); - - add_derivative_order_as( - &env.app, - market_id.to_owned(), - &env.users[1].account, - price, - quantity, - OrderType::Sell, - margin, - ); - - let query_msg = QueryMsg::TestVanillaSubaccountPosition { - market_id: MarketId::new(market_id.clone()).unwrap(), - subaccount_id: SubaccountId::new(subaccount_id.to_owned()).unwrap(), - }; - let res: SubaccountPositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - assert!(res.state.is_some()); - - let liquidity_orders: Vec = vec![HumanOrder { - price: "9.7".to_string(), - quantity: "10".to_string(), - order_type: OrderType::Sell, - }]; - add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); - - let _res: SubaccountPositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); -} - #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_trader_spot_orders() { @@ -352,7 +202,7 @@ fn test_query_trader_spot_orders() { let res: TraderSpotOrdersResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); let orders = res.orders.clone().unwrap(); - assert_eq!(orders.len(), 1); + assert_eq!(orders.len(), 1, "Expected exactly one order in the response"); let expected_orders = TrimmedSpotLimitOrder { price: human_to_dec("10.01", QUOTE_DECIMALS - BASE_DECIMALS), quantity: human_to_dec("5.1", BASE_DECIMALS), @@ -387,52 +237,6 @@ fn test_query_trader_spot_orders() { assert_eq!(orders[0].isBuy, expected_order.isBuy); } } -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_trader_derivative_orders() { - let env = Setup::new(ExchangeType::Derivative); - let wasm = Wasm::new(&env.app); - let market_id = env.market_id.unwrap(); - - let (price, quantity, margin) = scale_price_quantity_perp_market("10.1", "1", "2", "E_DECIMALS); - - let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(env.users[1].account.address())) - .as_str() - .to_string(); - - add_derivative_order_as( - &env.app, - market_id.to_owned(), - &env.users[1].account, - price, - quantity, - OrderType::Sell, - margin, - ); - - let query_msg = QueryMsg::TestTraderDerivativeOrders { - market_id: MarketId::new(market_id.clone()).unwrap(), - subaccount_id: SubaccountId::new(subaccount_id).unwrap(), - }; - let res: TraderDerivativeOrdersResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - assert!(res.orders.is_some()); - - let orders = res.orders.clone().unwrap(); - assert_eq!(orders.len(), 1); - let expected_order = TrimmedDerivativeLimitOrder { - price: human_to_dec("10.1", QUOTE_DECIMALS), - quantity: FPDecimal::must_from_str("1"), - margin: human_to_dec("20.2", QUOTE_DECIMALS), - fillable: FPDecimal::must_from_str("1"), - isBuy: false, - order_hash: "".to_string(), - }; - assert_eq!(orders[0].price, expected_order.price); - assert_eq!(orders[0].quantity, expected_order.quantity); - assert_eq!(orders[0].fillable, expected_order.fillable); - assert_eq!(orders[0].isBuy, expected_order.isBuy); - assert_eq!(orders[0].margin, expected_order.margin); -} #[test] #[cfg_attr(not(feature = "integration"), ignore)] @@ -473,80 +277,48 @@ fn test_query_spot_market_orderbook() { let res: QueryOrderbookResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); let buys_price_level = res.buys_price_level; let sells_price_level = res.sells_price_level; - assert_eq!(buys_price_level.len(), 2); - assert_eq!(sells_price_level.len(), 2); + assert_eq!(buys_price_level.len(), 4); + assert_eq!(sells_price_level.len(), 4); assert_eq!( buys_price_level[0], PriceLevel { - p: human_to_dec(liquidity_orders[2].price.as_str(), QUOTE_DECIMALS - BASE_DECIMALS), - q: human_to_dec(liquidity_orders[2].quantity.as_str(), BASE_DECIMALS), + p: human_to_dec(liquidity_orders[sells_price_level.len()].price.as_str(), QUOTE_DECIMALS - BASE_DECIMALS), + q: human_to_dec(liquidity_orders[sells_price_level.len()].quantity.as_str(), BASE_DECIMALS), } ); assert_eq!( buys_price_level[1], PriceLevel { - p: human_to_dec(liquidity_orders[3].price.as_str(), QUOTE_DECIMALS - BASE_DECIMALS), - q: human_to_dec(liquidity_orders[3].quantity.as_str(), BASE_DECIMALS), + p: human_to_dec( + liquidity_orders[sells_price_level.len() + 1].price.as_str(), + QUOTE_DECIMALS - BASE_DECIMALS + ), + q: human_to_dec(liquidity_orders[sells_price_level.len() + 1].quantity.as_str(), BASE_DECIMALS), } ); assert_eq!( sells_price_level[0], PriceLevel { - p: human_to_dec(liquidity_orders[1].price.as_str(), QUOTE_DECIMALS - BASE_DECIMALS), - q: human_to_dec(liquidity_orders[1].quantity.as_str(), BASE_DECIMALS), + p: human_to_dec( + liquidity_orders[sells_price_level.len() - 1].price.as_str(), + QUOTE_DECIMALS - BASE_DECIMALS + ), + q: human_to_dec(liquidity_orders[sells_price_level.len() - 1].quantity.as_str(), BASE_DECIMALS), } ); assert_eq!( sells_price_level[1], PriceLevel { - p: human_to_dec(liquidity_orders[0].price.as_str(), QUOTE_DECIMALS - BASE_DECIMALS), - q: human_to_dec(liquidity_orders[0].quantity.as_str(), BASE_DECIMALS), + p: human_to_dec( + liquidity_orders[sells_price_level.len() - 2].price.as_str(), + QUOTE_DECIMALS - BASE_DECIMALS + ), + q: human_to_dec(liquidity_orders[sells_price_level.len() - 2].quantity.as_str(), BASE_DECIMALS), } ); } -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_perpetual_market_info() { - let env = Setup::new(ExchangeType::Derivative); - let wasm = Wasm::new(&env.app); - let exchange = Exchange::new(&env.app); - - let ticker = "INJ/USDT".to_string(); - let derivative_market_id = get_perpetual_market_id(&exchange, ticker.to_owned()); - let market_id = MarketId::new(derivative_market_id.clone()).unwrap(); - let query_msg = QueryMsg::TestPerpetualMarketInfo { - market_id: market_id.clone(), - }; - let res: PerpetualMarketInfoResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - - assert!(res.info.is_some()); - let market_info = res.info.clone().unwrap(); - assert_eq!(market_info.market_id, market_id); - assert_eq!(market_info.funding_interval, 3600i64); -} - -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_perpetual_market_funding() { - let env = Setup::new(ExchangeType::Derivative); - let wasm = Wasm::new(&env.app); - let exchange = Exchange::new(&env.app); - - let ticker = "INJ/USDT".to_string(); - let derivative_market_id = get_perpetual_market_id(&exchange, ticker.to_owned()); - let market_id = MarketId::new(derivative_market_id.clone()).unwrap(); - let query_msg = QueryMsg::TestPerpetualMarketFunding { - market_id: market_id.clone(), - }; - let res: PerpetualMarketFundingResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - assert!(res.state.is_some()); - let state = res.state.unwrap(); - assert_eq!(state.cumulative_funding, FPDecimal::ZERO); - assert_eq!(state.cumulative_price, FPDecimal::ZERO); -} - #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_market_volatility() { @@ -585,25 +357,6 @@ fn test_query_market_volatility() { assert_eq!(res.volatility, Some(FPDecimal::ZERO)); } -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_derivative_market_mid_price_and_tob() { - let env = Setup::new(ExchangeType::Derivative); - let wasm = Wasm::new(&env.app); - let market_id = env.market_id.unwrap(); - - add_perp_initial_liquidity(&env.app, market_id.to_owned()); - - let query_msg = QueryMsg::TestDerivativeMarketMidPriceAndTob { - market_id: MarketId::new(market_id.clone()).unwrap(), - }; - - let res: MarketMidPriceAndTOBResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - assert_eq!(res.mid_price, Some(human_to_dec("10", QUOTE_DECIMALS))); - assert_eq!(res.best_buy_price, Some(human_to_dec("9.9", QUOTE_DECIMALS))); - assert_eq!(res.best_sell_price, Some(human_to_dec("10.1", QUOTE_DECIMALS))); -} - #[test] #[cfg_attr(not(feature = "integration"), ignore)] fn test_query_aggregate_market_volume() { @@ -668,75 +421,67 @@ fn test_query_aggregate_account_volume() { #[test] #[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_derivative_market_orderbook() { - let env = Setup::new(ExchangeType::Derivative); +fn test_query_market_atomic_execution_fee_multiplier() { + let env = Setup::new(ExchangeType::Spot); let wasm = Wasm::new(&env.app); let market_id = env.market_id.unwrap(); - - let liquidity_orders = get_initial_perp_liquidity_orders_vector(); - add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); - - let query_msg = QueryMsg::TestDerivativeMarketOrderbook { + let query_msg = QueryMsg::TestMarketAtomicExecutionFeeMultiplier { market_id: MarketId::new(market_id.clone()).unwrap(), - limit_cumulative_notional: FPDecimal::MAX, }; - - let res: QueryOrderbookResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - let buys_price_level = res.buys_price_level; - let sells_price_level = res.sells_price_level; - assert_eq!(buys_price_level.len(), 2); - assert_eq!(sells_price_level.len(), 2); - assert_eq!( - buys_price_level[0], - PriceLevel { - p: human_to_dec(liquidity_orders[2].price.as_str(), QUOTE_DECIMALS), - q: FPDecimal::must_from_str(liquidity_orders[2].quantity.as_str()), - } - ); - assert_eq!( - buys_price_level[1], - PriceLevel { - p: human_to_dec(liquidity_orders[3].price.as_str(), QUOTE_DECIMALS), - q: FPDecimal::must_from_str(liquidity_orders[3].quantity.as_str()), - } - ); - - assert_eq!( - sells_price_level[0], - PriceLevel { - p: human_to_dec(liquidity_orders[1].price.as_str(), QUOTE_DECIMALS), - q: FPDecimal::must_from_str(liquidity_orders[1].quantity.as_str()), - } - ); - assert_eq!( - sells_price_level[1], - PriceLevel { - p: human_to_dec(liquidity_orders[0].price.as_str(), QUOTE_DECIMALS), - q: FPDecimal::must_from_str(liquidity_orders[0].quantity.as_str()), - } - ); + let res: QueryMarketAtomicExecutionFeeMultiplierResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(res.multiplier, human_to_dec("0.0000025", QUOTE_DECIMALS)); } #[test] #[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_market_atomic_execution_fee_multiplier() { +fn test_query_spot_orders_to_cancel_up_to_amount() { let env = Setup::new(ExchangeType::Spot); let wasm = Wasm::new(&env.app); let market_id = env.market_id.unwrap(); - let query_msg = QueryMsg::TestMarketAtomicExecutionFeeMultiplier { + + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(env.users[0].account.address())) + .as_str() + .to_string(); + + let query_spot_msg = QueryMsg::TestTraderSpotOrders { market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id.to_owned()).unwrap(), }; - let res: QueryMarketAtomicExecutionFeeMultiplierResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); - assert_eq!(res.multiplier, human_to_dec("0.0000025", QUOTE_DECIMALS)); -} -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_spot_orders_to_cancel_up_to_amount() {} + { + let (price, quantity) = scale_price_quantity_for_spot_market("9.90", "1", &BASE_DECIMALS, "E_DECIMALS); + add_spot_order_as(&env.app, market_id.to_owned(), &env.users[0], price, quantity, OrderType::Buy); -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_derivative_orders_to_cancel_up_to_amount() {} + let res: TraderSpotOrdersResponse = wasm.query(&env.contract_address, &query_spot_msg).unwrap(); + let orders = res.orders.clone().unwrap(); + + let expected_order = TrimmedSpotLimitOrder { + price: human_to_dec("9.90", QUOTE_DECIMALS - BASE_DECIMALS), + quantity: human_to_dec("1", BASE_DECIMALS), + fillable: human_to_dec("1", BASE_DECIMALS), + isBuy: true, + order_hash: "".to_string(), + }; + assert_eq!(orders[0].price, expected_order.price); + assert_eq!(orders[0].quantity, expected_order.quantity); + assert_eq!(orders[0].fillable, expected_order.fillable); + assert_eq!(orders[0].isBuy, expected_order.isBuy); + } + + { + let query_spot_cancel_msg = QueryMsg::TestSpotOrdersToCancelUpToAmount { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id).unwrap(), + base_amount: human_to_dec("0", BASE_DECIMALS), + quote_amount: human_to_dec("0.2", QUOTE_DECIMALS), + strategy: CancellationStrategy::UnspecifiedOrder, + reference_price: None, + }; + let res: TraderSpotOrdersResponse = wasm.query(&env.contract_address, &query_spot_cancel_msg).unwrap(); + let orders = res.orders.clone().unwrap(); + assert_eq!(orders.len(), 1); + } +} #[test] #[cfg_attr(not(feature = "integration"), ignore)] @@ -748,22 +493,31 @@ fn test_query_trader_transient_spot_orders() { let subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(env.users[0].account.address()), 0u32); execute_all_authorizations(&env.app, &env.users[0].account, env.contract_address.clone()); - println!("{}", &env.users[0].account.address()); + add_spot_initial_liquidity(&env.app, market_id.clone()); - let res = wasm.execute( - &env.contract_address, - &ExecuteMsg::TestTraderTransientSpotOrders { - market_id: MarketId::new(market_id).unwrap(), - subaccount_id: subaccount_id.clone(), - }, - &[], - &env.users[0].account, - ); + let (scale_price, scale_quantity) = scale_price_quantity_for_spot_market_dec("9.8", "1", &BASE_DECIMALS, "E_DECIMALS); - println!("{:?}", res); - assert_eq!(1, 2); -} + let res = wasm + .execute( + &env.contract_address, + &ExecuteMsg::TestTraderTransientSpotOrders { + market_id: MarketId::new(market_id).unwrap(), + subaccount_id: subaccount_id.clone(), + price: scale_price.to_string(), + quantity: scale_quantity.to_string(), + }, + &[], + &env.users[0].account, + ) + .unwrap(); -#[test] -#[cfg_attr(not(feature = "integration"), ignore)] -fn test_query_trader_transient_derivative_orders() {} + let transient_query = res + .events + .iter() + .find(|e| e.ty == "wasm-transient_order") + .and_then(|event| event.attributes.iter().find(|a| a.key == "query_str")); + + assert!(transient_query.is_some()); + let expected_order_info = "TraderSpotOrdersResponse { orders: Some([TrimmedSpotLimitOrder { price: FPDecimal { num: 9800000, sign: 1 }, quantity: FPDecimal { num: 1000000000000000000000000000000000000, sign: 1 }"; + assert!(transient_query.unwrap().value.contains(expected_order_info)); +} diff --git a/contracts/injective-cosmwasm-mock/src/testing/test_exchange_derivative.rs b/contracts/injective-cosmwasm-mock/src/testing/test_exchange_derivative.rs new file mode 100644 index 00000000..f5f42516 --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/testing/test_exchange_derivative.rs @@ -0,0 +1,396 @@ +use crate::{ + msg::{ExecuteMsg, QueryMsg}, + utils::{ + add_derivative_order_as, add_derivative_orders, add_perp_initial_liquidity, dec_to_proto, execute_all_authorizations, + get_initial_perp_liquidity_orders_vector, get_perpetual_market_id, human_to_dec, scale_price_quantity_perp_market, + scale_price_quantity_perp_market_dec, ExchangeType, HumanOrder, Setup, BASE_DENOM, QUOTE_DECIMALS, QUOTE_DENOM, + }, +}; +use cosmwasm_std::Addr; +use injective_cosmwasm::{ + checked_address_to_subaccount_id, exchange::response::QueryOrderbookResponse, CancellationStrategy, DerivativeMarketResponse, MarketId, + MarketMidPriceAndTOBResponse, PerpetualMarketFundingResponse, PerpetualMarketInfoResponse, PriceLevel, + SubaccountEffectivePositionInMarketResponse, SubaccountId, SubaccountPositionInMarketResponse, TraderDerivativeOrdersResponse, + TrimmedDerivativeLimitOrder, +}; +use injective_math::FPDecimal; +use injective_std::types::injective::exchange::v1beta1::{MsgInstantPerpetualMarketLaunch, OrderType}; +use injective_test_tube::{injective_cosmwasm::get_default_subaccount_id_for_checked_address, Account, Exchange, Module, Wasm}; + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_perpetual_market_info() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + + let ticker = "INJ/USDT".to_string(); + let derivative_market_id = get_perpetual_market_id(&exchange, ticker.to_owned()); + let market_id = MarketId::new(derivative_market_id.clone()).unwrap(); + let query_msg = QueryMsg::TestPerpetualMarketInfo { + market_id: market_id.clone(), + }; + let res: PerpetualMarketInfoResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + + assert!(res.info.is_some()); + let market_info = res.info.clone().unwrap(); + assert_eq!(market_info.market_id, market_id); + assert_eq!(market_info.funding_interval, 3600i64); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_derivative_market() { + let env = Setup::new(ExchangeType::None); + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + let ticker = "INJ/USDT".to_string(); + let initial_margin_ratio = FPDecimal::must_from_str("0.195"); + let maintenance_margin_ratio = FPDecimal::must_from_str("0.05"); + let min_price_tick_size = FPDecimal::must_from_str("1000.0"); + let min_quantity_tick_size = FPDecimal::must_from_str("1000000000000000"); + let quote_denom = QUOTE_DENOM.to_string(); + let maker_fee_rate = FPDecimal::ZERO; + let taker_fee_rate = FPDecimal::ZERO; + + exchange + .instant_perpetual_market_launch( + MsgInstantPerpetualMarketLaunch { + sender: env.signer.address(), + ticker: ticker.to_owned(), + quote_denom: quote_denom.to_owned(), + oracle_base: BASE_DENOM.to_owned(), + oracle_quote: quote_denom.to_owned(), + oracle_scale_factor: 6u32, + oracle_type: 2i32, + maker_fee_rate: dec_to_proto(maker_fee_rate).to_string(), + taker_fee_rate: dec_to_proto(taker_fee_rate), + initial_margin_ratio: dec_to_proto(initial_margin_ratio), + maintenance_margin_ratio: dec_to_proto(maintenance_margin_ratio), + min_price_tick_size: dec_to_proto(min_price_tick_size), + min_quantity_tick_size: dec_to_proto(min_quantity_tick_size), + }, + &env.signer, + ) + .unwrap(); + + let derivative_market_id = get_perpetual_market_id(&exchange, ticker.to_owned()); + + let market_id = MarketId::new(derivative_market_id.clone()).unwrap(); + let query_msg = QueryMsg::TestDerivativeMarketQuery { market_id }; + let res: DerivativeMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + + let response_market = res.market.unwrap().market.unwrap(); + assert_eq!(response_market.market_id.as_str(), derivative_market_id); + assert_eq!(response_market.ticker, ticker); + assert_eq!(response_market.quote_denom, quote_denom); + assert_eq!(response_market.min_price_tick_size, min_price_tick_size); + assert_eq!(response_market.min_quantity_tick_size, min_quantity_tick_size); + assert_eq!(response_market.maker_fee_rate, maker_fee_rate); + assert_eq!(response_market.taker_fee_rate, taker_fee_rate); + assert_eq!(response_market.initial_margin_ratio, initial_margin_ratio); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_effective_subaccount_position() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + + add_perp_initial_liquidity(&env.app, market_id.clone()); + + let (price, quantity, margin) = scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); + + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(env.users[1].account.address())) + .as_str() + .to_string(); + + add_derivative_order_as( + &env.app, + market_id.to_owned(), + &env.users[1].account, + price, + quantity, + OrderType::Sell, + margin, + ); + + let query_msg = QueryMsg::TestEffectiveSubaccountPosition { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id.to_owned()).unwrap(), + }; + let res: SubaccountEffectivePositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert!(res.state.is_some()); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_vanilla_subaccount_position() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + + add_perp_initial_liquidity(&env.app, market_id.clone()); + + let (price, quantity, margin) = scale_price_quantity_perp_market("9.7", "1", "2", "E_DECIMALS); + let trader = &env.users[1]; + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(trader.account.address())) + .as_str() + .to_string(); + + add_derivative_order_as( + &env.app, + market_id.to_owned(), + &env.users[1].account, + price, + quantity, + OrderType::Sell, + margin, + ); + + let query_msg = QueryMsg::TestVanillaSubaccountPosition { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id.to_owned()).unwrap(), + }; + let res: SubaccountPositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert!(res.state.is_some()); + + let liquidity_orders: Vec = vec![HumanOrder { + price: "9.7".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Sell, + }]; + add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); + + let _res: SubaccountPositionInMarketResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_trader_derivative_orders() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + + let (price, quantity, margin) = scale_price_quantity_perp_market("10.1", "1", "2", "E_DECIMALS); + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(env.users[1].account.address())) + .as_str() + .to_string(); + + add_derivative_order_as( + &env.app, + market_id.to_owned(), + &env.users[1].account, + price, + quantity, + OrderType::Sell, + margin, + ); + + let query_msg = QueryMsg::TestTraderDerivativeOrders { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id).unwrap(), + }; + let res: TraderDerivativeOrdersResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert!(res.orders.is_some()); + let orders = res.orders.clone().unwrap(); + assert_eq!(orders.len(), 1); + let expected_order = TrimmedDerivativeLimitOrder { + price: human_to_dec("10.1", QUOTE_DECIMALS), + quantity: FPDecimal::must_from_str("1"), + margin: human_to_dec("20.2", QUOTE_DECIMALS), + fillable: FPDecimal::must_from_str("1"), + isBuy: false, + order_hash: "".to_string(), + }; + assert_eq!(orders[0].price, expected_order.price); + assert_eq!(orders[0].quantity, expected_order.quantity); + assert_eq!(orders[0].fillable, expected_order.fillable); + assert_eq!(orders[0].isBuy, expected_order.isBuy); + assert_eq!(orders[0].margin, expected_order.margin); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_derivative_orders_to_cancel_up_to_amount() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + let subaccount_id = get_default_subaccount_id_for_checked_address(&Addr::unchecked(env.users[1].account.address())) + .as_str() + .to_string(); + + let (price, quantity, margin) = scale_price_quantity_perp_market("10.1", "1", "2", "E_DECIMALS); + add_derivative_order_as( + &env.app, + market_id.to_owned(), + &env.users[1].account, + price, + quantity, + OrderType::Sell, + margin, + ); + let (price, quantity, margin) = scale_price_quantity_perp_market("12", "1", "2", "E_DECIMALS); + add_derivative_order_as( + &env.app, + market_id.to_owned(), + &env.users[1].account, + price, + quantity, + OrderType::Sell, + margin, + ); + let query_msg_derivative = QueryMsg::TestTraderDerivativeOrders { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id.to_owned()).unwrap(), + }; + let res: TraderDerivativeOrdersResponse = wasm.query(&env.contract_address, &query_msg_derivative).unwrap(); + assert!(res.orders.is_some()); + let orders = res.orders.clone().unwrap(); + assert_eq!(orders.len(), 2); + let query_derivative_order_cancel_msg = QueryMsg::TestDerivativeOrdersToCancelUpToAmount { + market_id: MarketId::new(market_id.clone()).unwrap(), + subaccount_id: SubaccountId::new(subaccount_id).unwrap(), + quote_amount: human_to_dec("0.2", QUOTE_DECIMALS), + strategy: CancellationStrategy::UnspecifiedOrder, + reference_price: None, + }; + let res: TraderDerivativeOrdersResponse = wasm.query(&env.contract_address, &query_derivative_order_cancel_msg).unwrap(); + assert!(res.orders.is_some()); + let orders = res.orders.clone().unwrap(); + assert_eq!(orders.len(), 1); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_perpetual_market_funding() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let exchange = Exchange::new(&env.app); + let ticker = "INJ/USDT".to_string(); + let derivative_market_id = get_perpetual_market_id(&exchange, ticker.to_owned()); + let market_id = MarketId::new(derivative_market_id.clone()).unwrap(); + let query_msg = QueryMsg::TestPerpetualMarketFunding { + market_id: market_id.clone(), + }; + let res: PerpetualMarketFundingResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert!(res.state.is_some()); + let state = res.state.unwrap(); + assert_eq!(state.cumulative_funding, FPDecimal::ZERO); + assert_eq!(state.cumulative_price, FPDecimal::ZERO); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_derivative_market_mid_price_and_tob() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + + add_perp_initial_liquidity(&env.app, market_id.to_owned()); + + let query_msg = QueryMsg::TestDerivativeMarketMidPriceAndTob { + market_id: MarketId::new(market_id.clone()).unwrap(), + }; + + let res: MarketMidPriceAndTOBResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(res.mid_price, Some(human_to_dec("10", QUOTE_DECIMALS))); + assert_eq!(res.best_buy_price, Some(human_to_dec("9.9", QUOTE_DECIMALS))); + assert_eq!(res.best_sell_price, Some(human_to_dec("10.1", QUOTE_DECIMALS))); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_derivative_market_orderbook() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + + let liquidity_orders = get_initial_perp_liquidity_orders_vector(); + add_derivative_orders(&env.app, market_id.clone(), liquidity_orders.to_owned(), None); + + let query_msg = QueryMsg::TestDerivativeMarketOrderbook { + market_id: MarketId::new(market_id.clone()).unwrap(), + limit_cumulative_notional: FPDecimal::MAX, + }; + let res: QueryOrderbookResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + let buys_price_level = res.buys_price_level; + let sells_price_level = res.sells_price_level; + assert_eq!(buys_price_level.len(), 2); + assert_eq!(sells_price_level.len(), 2); + assert_eq!( + buys_price_level[0], + PriceLevel { + p: human_to_dec(liquidity_orders[2].price.as_str(), QUOTE_DECIMALS), + q: FPDecimal::must_from_str(liquidity_orders[2].quantity.as_str()), + } + ); + assert_eq!( + buys_price_level[1], + PriceLevel { + p: human_to_dec(liquidity_orders[3].price.as_str(), QUOTE_DECIMALS), + q: FPDecimal::must_from_str(liquidity_orders[3].quantity.as_str()), + } + ); + assert_eq!( + sells_price_level[0], + PriceLevel { + p: human_to_dec(liquidity_orders[1].price.as_str(), QUOTE_DECIMALS), + q: FPDecimal::must_from_str(liquidity_orders[1].quantity.as_str()), + } + ); + assert_eq!( + sells_price_level[1], + PriceLevel { + p: human_to_dec(liquidity_orders[0].price.as_str(), QUOTE_DECIMALS), + q: FPDecimal::must_from_str(liquidity_orders[0].quantity.as_str()), + } + ); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_trader_transient_derivative_orders() { + let env = Setup::new(ExchangeType::Derivative); + let wasm = Wasm::new(&env.app); + let market_id = env.market_id.unwrap(); + let subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(env.users[0].account.address()), 0u32); + execute_all_authorizations(&env.app, &env.users[0].account, env.contract_address.clone()); + add_perp_initial_liquidity(&env.app, market_id.clone()); + let (price, quantity, margin) = scale_price_quantity_perp_market("9.7", "0.5", "2", "E_DECIMALS); + add_derivative_order_as( + &env.app, + market_id.to_owned(), + &env.users[0].account, + price, + quantity, + OrderType::Sell, + margin, + ); + let (scale_price, scale_quantity, scaled_margin) = scale_price_quantity_perp_market_dec("9.7", "0.1", "2", "E_DECIMALS); + let res = wasm + .execute( + &env.contract_address, + &ExecuteMsg::TestTraderTransientDerivativeOrders { + market_id: MarketId::new(market_id).unwrap(), + subaccount_id: subaccount_id.clone(), + price: scale_price.to_string(), + quantity: scale_quantity.to_string(), + margin: scaled_margin.to_string(), + }, + &[], + &env.users[0].account, + ) + .unwrap(); + + let transient_query = res + .events + .iter() + .find(|e| e.ty == "wasm-transient_derivative_order") + .and_then(|event| event.attributes.iter().find(|a| a.key == "query_str")); + + assert!(transient_query.is_some()); + let expected_order_info = "Ok(TraderDerivativeOrdersResponse { orders: Some([TrimmedDerivativeLimitOrder { price: FPDecimal { num: 9700000000000000000000000, sign: 1 }, quantity: FPDecimal { num: 100000000000000000, sign: 1 }, margin: FPDecimal { num: 1940000000000000000000000, sign: 1 }, fillable: FPDecimal { num: 100000000000000000, sign: 1 }, isBuy: true"; + assert!(transient_query.unwrap().value.contains(expected_order_info)); +} diff --git a/contracts/injective-cosmwasm-mock/src/testing/test_oracle.rs b/contracts/injective-cosmwasm-mock/src/testing/test_oracle.rs new file mode 100644 index 00000000..17175525 --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/testing/test_oracle.rs @@ -0,0 +1,105 @@ +use crate::msg::QueryMsg; +use crate::utils::{ + create_some_inj_price_attestation, relay_pyth_price, set_address_of_pyth_contract, str_coin, ExchangeType, Setup, BASE_DECIMALS, BASE_DENOM, + INJ_PYTH_PRICE_ID, +}; +use injective_cosmwasm::{OracleInfo, OraclePriceResponse, OracleType, OracleVolatilityResponse, PythPriceResponse}; +use injective_math::scale::Scaled; +use injective_math::FPDecimal; +use injective_std::types::injective::oracle::v1beta1::{QueryOraclePriceRequest, QueryPythPriceRequest}; +use injective_test_tube::{Module, Oracle, RunnerResult, Wasm}; + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_oracle_price() { + let env = Setup::new(ExchangeType::None); + let wasm = Wasm::new(&env.app); + let oracle = Oracle::new(&env.app); + + let query_msg = QueryMsg::TestQueryOraclePrice { + oracle_type: OracleType::PriceFeed, + base: env.denoms["base"].to_owned(), + quote: env.denoms["quote"].to_owned(), + }; + + let query_oracle_price_request = QueryOraclePriceRequest { + oracle_type: 2i32, + base: env.denoms["base"].to_owned(), + quote: env.denoms["quote"].to_owned(), + }; + + let oracle_response = oracle.query_oracle_price(&query_oracle_price_request); + let contract_response: RunnerResult = wasm.query(&env.contract_address, &query_msg); + + let oracle_response_pair_state = oracle_response.unwrap().price_pair_state; + let contract_response_pair_state = contract_response.unwrap().price_pair_state; + + assert!(contract_response_pair_state.is_some()); + assert!(oracle_response_pair_state.is_some()); + let oracle_response_pair_state = oracle_response_pair_state.unwrap(); + let contract_response_pair_state = contract_response_pair_state.unwrap(); + let oracle_response_pair_price = FPDecimal::must_from_str(oracle_response_pair_state.pair_price.as_str()); + assert_eq!(contract_response_pair_state.pair_price.scaled(18), oracle_response_pair_price); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_oracle_volatility() { + let env = Setup::new(ExchangeType::None); + let wasm = Wasm::new(&env.app); + + let base_oracle_info = Some(OracleInfo { + symbol: env.denoms["base"].to_owned(), + oracle_type: OracleType::PriceFeed, + scale_factor: 6u32, + }); + + let quote_oracle_info = Some(OracleInfo { + symbol: env.denoms["quote"].to_owned(), + oracle_type: OracleType::PriceFeed, + scale_factor: 6u32, + }); + + let query_msg = QueryMsg::TestQueryOracleVolatility { + base_info: base_oracle_info, + quote_info: quote_oracle_info, + max_age: 60u64, + include_raw_history: true, + include_metadata: false, + }; + let res: OracleVolatilityResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert!(res.volatility.is_none()); + assert!(res.raw_history.is_none()); +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_pyth_oracle_price() { + let env = Setup::new(ExchangeType::None); + let wasm = Wasm::new(&env.app); + let oracle = Oracle::new(&env.app); + + let validator = env.app.get_first_validator_signing_account(BASE_DENOM.to_string(), 1.2f64).unwrap(); + let pyth_contract = env.app.init_account(&[str_coin("1000000", BASE_DENOM, BASE_DECIMALS)]).unwrap(); + + set_address_of_pyth_contract(&env.app, &validator, &pyth_contract); + let price_attestations = vec![create_some_inj_price_attestation("7", 5, env.app.get_block_time_seconds())]; + relay_pyth_price(&oracle, price_attestations, &pyth_contract); + + let price_pyth_oracle_response = oracle + .query_pyth_price(&QueryPythPriceRequest { + price_id: INJ_PYTH_PRICE_ID.to_string(), + }) + .unwrap(); + let price_pyth_oracle_response = FPDecimal::must_from_str(price_pyth_oracle_response.price_state.unwrap().ema_price.as_str()); + + let query_msg = QueryMsg::TestQueryPythPrice { + price_id: INJ_PYTH_PRICE_ID.to_string(), + }; + + let contract_response: PythPriceResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!( + contract_response.price_state.unwrap().ema_price.scaled(BASE_DECIMALS), + price_pyth_oracle_response + ); +} diff --git a/contracts/injective-cosmwasm-mock/src/testing/test_staking.rs b/contracts/injective-cosmwasm-mock/src/testing/test_staking.rs new file mode 100644 index 00000000..6157a539 --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/testing/test_staking.rs @@ -0,0 +1,38 @@ +use crate::msg::QueryMsg; +use crate::utils::{ExchangeType, Setup, BASE_DENOM}; +use cosmwasm_std::Uint128; +use injective_cosmwasm::exchange::response::StakedAmountResponse; +use injective_std::types::cosmos::base::v1beta1::Coin; +use injective_std::types::cosmos::staking::v1beta1::MsgDelegate; +use injective_test_tube::{Account, Module, Staking, Wasm}; + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_staked_amount() { + let env = Setup::new(ExchangeType::None); + let wasm = Wasm::new(&env.app); + let staking = Staking::new(&env.app); + let validator_address = env.app.get_first_validator_address().unwrap(); + + staking + .delegate( + MsgDelegate { + delegator_address: env.owner.address(), + validator_address, + amount: Some(Coin { + amount: "10".to_string(), + denom: BASE_DENOM.to_string(), + }), + }, + &env.owner, + ) + .unwrap(); + + let query_msg = QueryMsg::TestQueryStakedAmount { + delegator_address: env.owner.address(), + max_delegations: 100, + }; + + let response: StakedAmountResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(response.staked_amount, Uint128::new(10)); +} diff --git a/contracts/injective-cosmwasm-mock/src/testing/test_token_factory.rs b/contracts/injective-cosmwasm-mock/src/testing/test_token_factory.rs new file mode 100644 index 00000000..69d253d8 --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/testing/test_token_factory.rs @@ -0,0 +1,36 @@ +use crate::msg::QueryMsg; +use crate::utils::{str_coin, ExchangeType, Setup, BASE_DECIMALS, BASE_DENOM}; +use cosmwasm_std::Uint128; +use injective_cosmwasm::tokenfactory::response::{TokenFactoryCreateDenomFeeResponse, TokenFactoryDenomSupplyResponse}; +use injective_std::types::injective::tokenfactory::v1beta1::MsgCreateDenom; +use injective_test_tube::{Account, Module, TokenFactory, Wasm}; + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_token_factory_denom_total_supply() { + let env = Setup::new(ExchangeType::None); + let wasm = Wasm::new(&env.app); + let factory = TokenFactory::new(&env.app); + + let test_denom = format!("factory/{}/test", env.owner.address()); + let msg_create_denom = MsgCreateDenom { + sender: env.owner.address(), + subdenom: "test".to_string(), + }; + + factory.create_denom(msg_create_denom, &env.owner).unwrap(); + let query_msg = QueryMsg::TestQueryTokenFactoryDenomTotalSupply { denom: test_denom }; + + let response: TokenFactoryDenomSupplyResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert_eq!(response.total_supply, Uint128::zero()) +} + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_token_factory_creation_fee() { + let env = Setup::new(ExchangeType::None); + let wasm = Wasm::new(&env.app); + + let response: TokenFactoryCreateDenomFeeResponse = wasm.query(&env.contract_address, &QueryMsg::TestQueryTokenFactoryCreationFee {}).unwrap(); + assert_eq!(response.fee, vec![str_coin("10", BASE_DENOM, BASE_DECIMALS)]) +} diff --git a/contracts/injective-cosmwasm-mock/src/testing/test_wasmx.rs b/contracts/injective-cosmwasm-mock/src/testing/test_wasmx.rs new file mode 100644 index 00000000..2aa3f67a --- /dev/null +++ b/contracts/injective-cosmwasm-mock/src/testing/test_wasmx.rs @@ -0,0 +1,18 @@ +use crate::msg::QueryMsg; +use crate::utils::{ExchangeType, Setup}; +use injective_cosmwasm::wasmx::response::QueryContractRegistrationInfoResponse; +use injective_test_tube::{Module, Wasm}; + +#[test] +#[cfg_attr(not(feature = "integration"), ignore)] +fn test_query_contract_registration_info() { + let env = Setup::new(ExchangeType::None); + let wasm = Wasm::new(&env.app); + + let query_msg = QueryMsg::TestQueryContractRegistrationInfo { + contract_address: env.contract_address.to_owned(), + }; + + let response: QueryContractRegistrationInfoResponse = wasm.query(&env.contract_address, &query_msg).unwrap(); + assert!(response.contract.is_none()) +} diff --git a/contracts/injective-cosmwasm-mock/src/types.rs b/contracts/injective-cosmwasm-mock/src/types.rs index e83690bd..e4e3642e 100644 --- a/contracts/injective-cosmwasm-mock/src/types.rs +++ b/contracts/injective-cosmwasm-mock/src/types.rs @@ -62,14 +62,14 @@ pub struct SpotOrder { /// order. #[allow(clippy::derive_partial_eq_without_eq)] #[derive( -Clone, -PartialEq, -Eq, -::prost::Message, -::serde::Serialize, -::serde::Deserialize, -::schemars::JsonSchema, -// CosmwasmExt, + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + // CosmwasmExt, )] // #[proto_message(type_url = "/injective.exchange.v1beta1.MsgCreateSpotMarketOrder")] pub struct MsgCreateSpotMarketOrder { @@ -79,6 +79,25 @@ pub struct MsgCreateSpotMarketOrder { pub order: ::core::option::Option, } +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + // CosmwasmExt, +)] +// #[proto_message(type_url = "/injective.exchange.v1beta1.MsgCreateSpotLimitOrder")] +pub struct MsgCreateSpotLimitOrder { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub order: ::core::option::Option, +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] #[derive(::serde::Serialize, ::serde::Deserialize, ::schemars::JsonSchema)] @@ -95,3 +114,57 @@ pub enum OrderType { BuyAtomic = 9, SellAtomic = 10, } + +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + //CosmwasmExt +)] +//#[proto_message(type_url = "/injective.exchange.v1beta1.MsgCreateDerivativeLimitOrder")] +pub struct MsgCreateDerivativeLimitOrder { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub order: ::core::option::Option, +} + +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + // CosmwasmExt, +)] +// #[proto_message(type_url = "/injective.exchange.v1beta1.DerivativeOrder")] +pub struct DerivativeOrder { + /// market_id represents the unique ID of the market + #[prost(string, tag = "1")] + #[serde(alias = "marketID")] + pub market_id: ::prost::alloc::string::String, + /// order_info contains the information of the order + #[prost(message, optional, tag = "2")] + pub order_info: ::core::option::Option, + /// order types + #[prost(enumeration = "OrderType", tag = "3")] + // #[serde( + // serialize_with = "crate::serde::as_str::serialize", + // deserialize_with = "crate::serde::as_str::deserialize" + // )] + pub order_type: i32, + /// margin is the margin used by the limit order + #[prost(string, tag = "4")] + pub margin: ::prost::alloc::string::String, + /// trigger_price is the trigger price used by stop/take orders + #[prost(string, tag = "5")] + pub trigger_price: ::prost::alloc::string::String, +} diff --git a/contracts/injective-cosmwasm-mock/src/utils.rs b/contracts/injective-cosmwasm-mock/src/utils.rs index d044d400..ae74b15d 100644 --- a/contracts/injective-cosmwasm-mock/src/utils.rs +++ b/contracts/injective-cosmwasm-mock/src/utils.rs @@ -1,35 +1,38 @@ -use crate::msg::{InstantiateMsg, MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT}; +use crate::msg::{InstantiateMsg, MSG_CREATE_DERIVATIVE_LIMIT_ORDER_ENDPOINT, MSG_CREATE_SPOT_LIMIT_ORDER_ENDPOINT}; use cosmwasm_std::{coin, Addr, Coin}; use injective_cosmwasm::{checked_address_to_subaccount_id, SubaccountId}; use injective_math::{scale::Scaled, FPDecimal}; -use injective_test_tube::{ - Account, Authz, Bank, Exchange, ExecuteResponse, Gov, InjectiveTestApp, Insurance, Module, Oracle, Runner, SigningAccount, Wasm, -}; - -use prost::Message; -use std::{collections::HashMap, str::FromStr}; - -use injective_std::shim::Timestamp; -use injective_std::types::cosmos::authz::v1beta1::{GenericAuthorization, Grant, MsgGrant, MsgRevoke, MsgRevokeResponse}; -use injective_std::types::cosmos::bank::v1beta1::SendAuthorization; -use injective_std::types::injective::exchange::v1beta1::{ - DerivativeOrder, MsgCreateDerivativeLimitOrder, MsgCreateSpotLimitOrder, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, OrderInfo, - OrderType, QueryDerivativeMarketsRequest, QuerySpotMarketsRequest, SpotOrder, -}; -use injective_std::types::injective::insurance::v1beta1::MsgCreateInsuranceFund; -use injective_std::types::injective::oracle::v1beta1::OracleType; use injective_std::{ - shim::Any, + shim::{Any, Timestamp}, types::{ cosmos::{ - bank::v1beta1::MsgSend, + authz::v1beta1::{GenericAuthorization, Grant, MsgGrant, MsgRevoke, MsgRevokeResponse}, + bank::v1beta1::{MsgSend, SendAuthorization}, base::v1beta1::Coin as BaseCoin, - gov::{v1::MsgVote, v1beta1::MsgSubmitProposal as MsgSubmitProposalV1Beta1}, + gov::{ + v1::{MsgSubmitProposal, MsgVote}, + v1beta1::MsgSubmitProposal as MsgSubmitProposalV1Beta1, + }, + }, + injective::{ + exchange::v1beta1::{ + DerivativeOrder, MsgCreateDerivativeLimitOrder, MsgCreateSpotLimitOrder, MsgInstantPerpetualMarketLaunch, MsgInstantSpotMarketLaunch, + OrderInfo, OrderType, QueryDerivativeMarketsRequest, QuerySpotMarketsRequest, SpotOrder, + }, + insurance::v1beta1::MsgCreateInsuranceFund, + oracle::v1beta1::{ + GrantPriceFeederPrivilegeProposal, MsgRelayPriceFeedPrice, MsgRelayPythPrices, MsgUpdateParams, OracleType, Params, PriceAttestation, + }, }, - injective::oracle::v1beta1::{GrantPriceFeederPrivilegeProposal, MsgRelayPriceFeedPrice}, }, }; -use injective_test_tube::injective_cosmwasm::get_default_subaccount_id_for_checked_address; +use injective_test_tube::{ + injective_cosmwasm::get_default_subaccount_id_for_checked_address, Account, Authz, Bank, Exchange, ExecuteResponse, Gov, InjectiveTestApp, + Insurance, Module, Oracle, Runner, SigningAccount, Wasm, +}; +use injective_testing::human_to_i64; +use prost::Message; +use std::{collections::HashMap, ops::Neg, str::FromStr}; pub const EXCHANGE_DECIMALS: i32 = 18i32; pub const BASE_DECIMALS: i32 = 18i32; @@ -39,6 +42,9 @@ pub const QUOTE_DECIMALS: i32 = 6i32; pub const ATOM_DENOM: &str = "atom"; pub const BASE_DENOM: &str = "inj"; pub const QUOTE_DENOM: &str = "usdt"; +pub const INJ_PYTH_PRICE_ID: &str = "0x7a5bc1d2b56ad029048cd63964b3ad2776eadf812edc1a43a31406cb54bff592"; +pub const USDT_PYTH_PRICE_ID: &str = "0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588"; +pub const GOV_MODULE_ADDRESS: &str = "inj10d07y265gmmuvt4z0w9aw880jnsr700jstypyt"; pub struct UserInfo { pub account: SigningAccount, @@ -319,7 +325,7 @@ pub fn launch_spot_market(exchange: &Exchange, signer: &Signin base_denom: BASE_DENOM.to_string(), quote_denom: QUOTE_DENOM.to_string(), min_price_tick_size: dec_to_proto(FPDecimal::must_from_str("0.000000000000001")), - min_quantity_tick_size: dec_to_proto(FPDecimal::must_from_str("1000000000000000")), + min_quantity_tick_size: dec_to_proto(FPDecimal::must_from_str("1")), }, signer, ) @@ -437,6 +443,16 @@ pub fn add_spot_orders(app: &InjectiveTestApp, market_id: String, orders: Vec Vec { vec![ + HumanOrder { + price: "15".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Sell, + }, + HumanOrder { + price: "12".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Sell, + }, HumanOrder { price: "10.2".to_string(), quantity: "5".to_string(), @@ -457,6 +473,16 @@ pub fn get_initial_liquidity_orders_vector() -> Vec { quantity: "5".to_string(), order_type: OrderType::Buy, }, + HumanOrder { + price: "8".to_string(), + quantity: "5".to_string(), + order_type: OrderType::Buy, + }, + HumanOrder { + price: "5".to_string(), + quantity: "10".to_string(), + order_type: OrderType::Buy, + }, ] } @@ -616,11 +642,13 @@ pub fn create_send_authorization(app: &InjectiveTestApp, granter: &SigningAccoun } pub fn execute_all_authorizations(app: &InjectiveTestApp, granter: &SigningAccount, grantee: String) { + create_generic_authorization(app, granter, grantee.clone(), MSG_CREATE_SPOT_LIMIT_ORDER_ENDPOINT.to_string(), None); + create_generic_authorization( app, granter, grantee.clone(), - MSG_CREATE_SPOT_MARKET_ORDER_ENDPOINT.to_string(), + MSG_CREATE_DERIVATIVE_LIMIT_ORDER_ENDPOINT.to_string(), None, ); @@ -632,7 +660,6 @@ pub fn execute_all_authorizations(app: &InjectiveTestApp, granter: &SigningAccou None, ); - create_generic_authorization( app, granter, @@ -641,13 +668,7 @@ pub fn execute_all_authorizations(app: &InjectiveTestApp, granter: &SigningAccou None, ); - create_generic_authorization( - app, - granter, - grantee, - "/injective.exchange.v1beta1.MsgWithdraw".to_string(), - None, - ); + create_generic_authorization(app, granter, grantee, "/injective.exchange.v1beta1.MsgWithdraw".to_string(), None); } // Human Utils @@ -664,16 +685,32 @@ pub fn dec_to_proto(val: FPDecimal) -> String { } pub fn scale_price_quantity_for_spot_market(price: &str, quantity: &str, base_decimals: &i32, quote_decimals: &i32) -> (String, String) { + let (scaled_price, scaled_quantity) = scale_price_quantity_for_spot_market_dec(price, quantity, base_decimals, quote_decimals); + (dec_to_proto(scaled_price), dec_to_proto(scaled_quantity)) +} + +pub fn scale_price_quantity_for_spot_market_dec(price: &str, quantity: &str, base_decimals: &i32, quote_decimals: &i32) -> (FPDecimal, FPDecimal) { let price_dec = FPDecimal::must_from_str(price.replace('_', "").as_str()); let quantity_dec = FPDecimal::must_from_str(quantity.replace('_', "").as_str()); let scaled_price = price_dec.scaled(quote_decimals - base_decimals); let scaled_quantity = quantity_dec.scaled(*base_decimals); - (dec_to_proto(scaled_price), dec_to_proto(scaled_quantity)) + (scaled_price, scaled_quantity) } pub fn scale_price_quantity_perp_market(price: &str, quantity: &str, margin_ratio: &str, quote_decimals: &i32) -> (String, String, String) { + let (scaled_price, scaled_quantity, scaled_margin) = scale_price_quantity_perp_market_dec(price, quantity, margin_ratio, quote_decimals); + + (dec_to_proto(scaled_price), dec_to_proto(scaled_quantity), dec_to_proto(scaled_margin)) +} + +pub fn scale_price_quantity_perp_market_dec( + price: &str, + quantity: &str, + margin_ratio: &str, + quote_decimals: &i32, +) -> (FPDecimal, FPDecimal, FPDecimal) { let price_dec = FPDecimal::must_from_str(price.replace('_', "").as_str()); let quantity_dec = FPDecimal::must_from_str(quantity.replace('_', "").as_str()); let margin_ratio_dec = FPDecimal::must_from_str(margin_ratio.replace('_', "").as_str()); @@ -683,5 +720,114 @@ pub fn scale_price_quantity_perp_market(price: &str, quantity: &str, margin_rati let scaled_margin = (price_dec * quantity_dec * margin_ratio_dec).scaled(*quote_decimals); - (dec_to_proto(scaled_price), dec_to_proto(scaled_quantity), dec_to_proto(scaled_margin)) + (scaled_price, scaled_quantity, scaled_margin) +} + +pub fn set_address_of_pyth_contract(app: &InjectiveTestApp, validator: &SigningAccount, pyth_address: &SigningAccount) { + let gov = Gov::new(app); + + let mut buf = vec![]; + MsgUpdateParams::encode( + &MsgUpdateParams { + authority: GOV_MODULE_ADDRESS.to_string(), + params: Some(Params { + pyth_contract: pyth_address.address(), + }), + }, + &mut buf, + ) + .unwrap(); + + let res = gov + .submit_proposal( + MsgSubmitProposal { + messages: vec![Any { + type_url: "/injective.oracle.v1beta1.MsgUpdateParams".to_string(), + value: buf, + }], + initial_deposit: vec![BaseCoin { + amount: "100000000000000000000".to_string(), + denom: "inj".to_string(), + }], + proposer: validator.address(), + metadata: "".to_string(), + title: "Set Pyth contract address".to_string(), + summary: "Set Pyth contract address".to_string(), + }, + validator, + ) + .unwrap(); + + let proposal_id = res.events.iter().find(|e| e.ty == "submit_proposal").unwrap().attributes[0] + .value + .to_owned(); + + gov.vote( + MsgVote { + proposal_id: u64::from_str(&proposal_id).unwrap(), + voter: validator.address(), + option: 1i32, + metadata: "".to_string(), + }, + validator, + ) + .unwrap(); + + // NOTE: increase the block time in order to move past the voting period + app.increase_time(11u64); +} + +pub fn relay_pyth_price(oracle: &Oracle, price_attestations: Vec, pyth_address: &SigningAccount) { + let pyth_price_msg = MsgRelayPythPrices { + sender: pyth_address.address(), + price_attestations, + }; + + oracle.relay_pyth_prices(pyth_price_msg, pyth_address).unwrap(); +} + +pub fn create_some_inj_price_attestation(human_price: &str, decimal_precision: i32, publish_time: i64) -> PriceAttestation { + if decimal_precision < 0 { + panic!("Desired exponent cannot be negative") + }; + + let (price_i64, exponent_to_use) = if decimal_precision == 1 { + (human_price.parse::().unwrap(), 1) + } else { + (human_to_i64(human_price, decimal_precision), decimal_precision.neg()) + }; + + PriceAttestation { + price_id: INJ_PYTH_PRICE_ID.to_string(), + price: price_i64, + conf: 500, + expo: exponent_to_use, + ema_price: price_i64, + ema_conf: 2000, + ema_expo: exponent_to_use, + publish_time, + } +} + +pub fn create_some_usdt_price_attestation(human_price: &str, decimal_precision: i32, publish_time: i64) -> PriceAttestation { + if decimal_precision < 0 { + panic!("Desired exponent cannot be negative") + }; + + let (price_i64, exponent_to_use) = if decimal_precision == 0 { + (human_price.parse::().unwrap(), 0) + } else { + (human_to_i64(human_price, decimal_precision), decimal_precision.neg()) + }; + + PriceAttestation { + price_id: USDT_PYTH_PRICE_ID.to_string(), + price: price_i64, + conf: 500, + expo: exponent_to_use, + ema_price: price_i64, + ema_conf: 2000, + ema_expo: exponent_to_use, + publish_time, + } } diff --git a/packages/injective-cosmwasm/src/exchange_mock_querier.rs b/packages/injective-cosmwasm/src/exchange_mock_querier.rs index bc7d5a2b..5cadb1dd 100644 --- a/packages/injective-cosmwasm/src/exchange_mock_querier.rs +++ b/packages/injective-cosmwasm/src/exchange_mock_querier.rs @@ -25,9 +25,8 @@ use crate::{ CancellationStrategy, Deposit, DerivativeMarketResponse, ExchangeParamsResponse, FullDerivativeMarket, InjectiveQuery, InjectiveQueryWrapper, MarketMidPriceAndTOBResponse, MarketStatus, MarketVolatilityResponse, OracleInfo, OracleVolatilityResponse, OrderSide, PerpetualMarketFundingResponse, PerpetualMarketInfoResponse, PythPriceResponse, QueryAggregateMarketVolumeResponse, QueryAggregateVolumeResponse, - QueryDenomDecimalResponse, QueryDenomDecimalsResponse, QueryMarketAtomicExecutionFeeMultiplierResponse, SpotMarket, SpotMarketResponse, - SubaccountDepositResponse, SubaccountEffectivePositionInMarketResponse, SubaccountPositionInMarketResponse, TraderDerivativeOrdersResponse, - TraderSpotOrdersResponse, + QueryMarketAtomicExecutionFeeMultiplierResponse, SpotMarket, SpotMarketResponse, SubaccountDepositResponse, + SubaccountEffectivePositionInMarketResponse, SubaccountPositionInMarketResponse, TraderDerivativeOrdersResponse, TraderSpotOrdersResponse, }; use crate::{MarketId, SubaccountId}; @@ -211,16 +210,6 @@ fn default_aggregate_account_volume_handler() -> QuerierResult { SystemResult::Ok(ContractResult::from(to_json_binary(&response))) } -fn default_denom_decimal_handler() -> QuerierResult { - let response = QueryDenomDecimalResponse { decimals: 6 }; - SystemResult::Ok(ContractResult::from(to_json_binary(&response))) -} - -fn default_denom_decimals_handler() -> QuerierResult { - let response = QueryDenomDecimalsResponse { denom_decimals: vec![] }; - SystemResult::Ok(ContractResult::from(to_json_binary(&response))) -} - fn default_oracle_volatility_response_handler() -> QuerierResult { let response = OracleVolatilityResponse { volatility: Some(FPDecimal::ONE), @@ -550,14 +539,6 @@ impl WasmMockQuerier { _ => panic!("unsupported"), }, QueryRequest::Custom(query) => match query.query_data.clone() { - InjectiveQuery::Grants { - granter: _, - grantee: _, - msg_type_url: _, - pagination: _, - } => todo!(), - InjectiveQuery::GranteeGrants { grantee: _, pagination: _ } => todo!(), - InjectiveQuery::GranterGrants { granter: _, pagination: _ } => todo!(), InjectiveQuery::SubaccountDeposit { subaccount_id, denom } => match &self.subaccount_deposit_response_handler { Some(handler) => handler.handle(subaccount_id, denom), None => default_subaccount_deposit_response_handler(), @@ -660,14 +641,6 @@ impl WasmMockQuerier { Some(handler) => handler.handle(account), None => default_aggregate_account_volume_handler(), }, - InjectiveQuery::DenomDecimal { denom } => match &self.denom_decimal_handler { - Some(handler) => handler.handle(denom), - None => default_denom_decimal_handler(), - }, - InjectiveQuery::DenomDecimals { denoms } => match &self.denom_decimals_handler { - Some(handler) => handler.handle(denoms), - None => default_denom_decimals_handler(), - }, InjectiveQuery::StakedAmount { delegator_address, max_delegations, diff --git a/packages/injective-cosmwasm/src/querier.rs b/packages/injective-cosmwasm/src/querier.rs index e7af446a..ab604d9d 100644 --- a/packages/injective-cosmwasm/src/querier.rs +++ b/packages/injective-cosmwasm/src/querier.rs @@ -1,18 +1,11 @@ -use cosmwasm_std::{Addr, QuerierWrapper, StdResult}; - -use injective_math::FPDecimal; - -use crate::authz::response::{GranteeGrantsResponse, GranterGrantsResponse, GrantsResponse}; -use crate::exchange::response::StakedAmountResponse; use crate::exchange::{ cancel::CancellationStrategy, order::OrderSide, response::{ DerivativeMarketResponse, ExchangeParamsResponse, MarketMidPriceAndTOBResponse, MarketVolatilityResponse, OracleVolatilityResponse, PerpetualMarketFundingResponse, PerpetualMarketInfoResponse, QueryAggregateMarketVolumeResponse, QueryAggregateVolumeResponse, - QueryDenomDecimalResponse, QueryDenomDecimalsResponse, QueryMarketAtomicExecutionFeeMultiplierResponse, QueryOrderbookResponse, - SpotMarketResponse, SubaccountDepositResponse, SubaccountEffectivePositionInMarketResponse, SubaccountPositionInMarketResponse, - TraderDerivativeOrdersResponse, TraderSpotOrdersResponse, + QueryMarketAtomicExecutionFeeMultiplierResponse, QueryOrderbookResponse, SpotMarketResponse, StakedAmountResponse, SubaccountDepositResponse, + SubaccountEffectivePositionInMarketResponse, SubaccountPositionInMarketResponse, TraderDerivativeOrdersResponse, TraderSpotOrdersResponse, }, types::{MarketId, SubaccountId}, }; @@ -25,6 +18,8 @@ use crate::query::{InjectiveQuery, InjectiveQueryWrapper}; use crate::route::InjectiveRoute; use crate::tokenfactory::response::{TokenFactoryCreateDenomFeeResponse, TokenFactoryDenomSupplyResponse}; use crate::wasmx::response::QueryContractRegistrationInfoResponse; +use cosmwasm_std::{Addr, QuerierWrapper, StdResult}; +use injective_math::FPDecimal; pub struct InjectiveQuerier<'a> { querier: &'a QuerierWrapper<'a, InjectiveQueryWrapper>, @@ -35,48 +30,6 @@ impl<'a> InjectiveQuerier<'a> { InjectiveQuerier { querier } } - // Authz - pub fn query_grants(&self, grantee: &str, granter: &str, msg_type_url: &str, pagination: &Option) -> StdResult { - let request = InjectiveQueryWrapper { - route: InjectiveRoute::Authz, - query_data: InjectiveQuery::Grants { - grantee: grantee.to_string(), - granter: granter.to_string(), - msg_type_url: msg_type_url.to_string(), - pagination: *pagination, - }, - }; - - let res: GrantsResponse = self.querier.query(&request.into())?; - Ok(res) - } - - pub fn query_grantee_grants(&self, grantee: &str, pagination: &Option) -> StdResult { - let request = InjectiveQueryWrapper { - route: InjectiveRoute::Authz, - query_data: InjectiveQuery::GranteeGrants { - grantee: grantee.to_string(), - pagination: *pagination, - }, - }; - - let res: GranteeGrantsResponse = self.querier.query(&request.into())?; - Ok(res) - } - - pub fn query_granter_grants(&self, granter: &str, pagination: &Option) -> StdResult { - let request = InjectiveQueryWrapper { - route: InjectiveRoute::Authz, - query_data: InjectiveQuery::GranterGrants { - granter: granter.to_string(), - pagination: *pagination, - }, - }; - - let res: GranterGrantsResponse = self.querier.query(&request.into())?; - Ok(res) - } - // Exchange pub fn query_exchange_params(&self) -> StdResult { let request = InjectiveQueryWrapper { @@ -363,28 +316,6 @@ impl<'a> InjectiveQuerier<'a> { Ok(res) } - pub fn query_denom_decimal + Clone>(&self, denom: &'a T) -> StdResult { - let request = InjectiveQueryWrapper { - route: InjectiveRoute::Exchange, - query_data: InjectiveQuery::DenomDecimal { denom: denom.clone().into() }, - }; - - let res: QueryDenomDecimalResponse = self.querier.query(&request.into())?; - Ok(res) - } - - pub fn query_denom_decimals> + Clone>(&self, denoms: &'a T) -> StdResult { - let request = InjectiveQueryWrapper { - route: InjectiveRoute::Exchange, - query_data: InjectiveQuery::DenomDecimals { - denoms: denoms.clone().into(), - }, - }; - - let res: QueryDenomDecimalsResponse = self.querier.query(&request.into())?; - Ok(res) - } - pub fn query_spot_market_mid_price_and_tob + Clone>(&self, market_id: &'a T) -> StdResult { let request = InjectiveQueryWrapper { route: InjectiveRoute::Exchange, diff --git a/packages/injective-cosmwasm/src/query.rs b/packages/injective-cosmwasm/src/query.rs index 3a4b8066..b62eadea 100644 --- a/packages/injective-cosmwasm/src/query.rs +++ b/packages/injective-cosmwasm/src/query.rs @@ -26,21 +26,6 @@ pub struct InjectiveQueryWrapper { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum InjectiveQuery { - // Authz - Grants { - granter: String, - grantee: String, - msg_type_url: String, - pagination: Option, - }, - GranteeGrants { - grantee: String, - pagination: Option, - }, - GranterGrants { - granter: String, - pagination: Option, - }, // Exchange ExchangeParams {}, SubaccountDeposit { @@ -130,12 +115,6 @@ pub enum InjectiveQuery { AggregateAccountVolume { account: String, }, - DenomDecimal { - denom: String, - }, - DenomDecimals { - denoms: Vec, - }, MarketAtomicExecutionFeeMultiplier { market_id: MarketId, }, diff --git a/packages/injective-protobuf/src/proto/mod.rs b/packages/injective-protobuf/src/proto/mod.rs index de6005c4..de0fb666 100644 --- a/packages/injective-protobuf/src/proto/mod.rs +++ b/packages/injective-protobuf/src/proto/mod.rs @@ -1,9 +1,9 @@ // @generated +pub mod account; pub mod auth; pub mod coin; pub mod distribution; pub mod exchange; -pub mod tx; pub mod oracle; -pub mod account; +pub mod tx; From 1c4c30283919b9357f05177f1aceebdf93c1ed39 Mon Sep 17 00:00:00 2001 From: jbernal87 Date: Thu, 21 Mar 2024 15:07:20 +0100 Subject: [PATCH 13/13] changelog fix --- Cargo.lock | 10 +++++----- .../injective-cosmwasm/CHANGELOG.md | 2 +- packages/injective-cosmwasm/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) rename CHANGELOG.md => packages/injective-cosmwasm/CHANGELOG.md (94%) diff --git a/Cargo.lock b/Cargo.lock index e7c01f7a..dc7769c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,7 +90,7 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw-utils 0.16.0", "cw2 0.16.0", - "injective-cosmwasm 0.2.21", + "injective-cosmwasm 0.2.22", "injective-math 0.2.4", "injective-protobuf", "protobuf 2.28.0", @@ -785,7 +785,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus 1.2.0", "cw2 0.16.0", - "injective-cosmwasm 0.2.21", + "injective-cosmwasm 0.2.22", "schemars", "serde 1.0.196", "thiserror", @@ -1547,7 +1547,7 @@ dependencies = [ [[package]] name = "injective-cosmwasm" -version = "0.2.21" +version = "0.2.22" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -1573,7 +1573,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus 1.2.0", "cw2 0.16.0", - "injective-cosmwasm 0.2.21", + "injective-cosmwasm 0.2.22", "injective-math 0.2.4", "injective-protobuf", "injective-std 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1686,7 +1686,7 @@ dependencies = [ "base64 0.13.1", "cosmwasm-std", "cw-multi-test", - "injective-cosmwasm 0.2.21", + "injective-cosmwasm 0.2.22", "injective-math 0.2.4", "rand 0.4.6", "secp256k1", diff --git a/CHANGELOG.md b/packages/injective-cosmwasm/CHANGELOG.md similarity index 94% rename from CHANGELOG.md rename to packages/injective-cosmwasm/CHANGELOG.md index 00fb444b..a74c6761 100644 --- a/CHANGELOG.md +++ b/packages/injective-cosmwasm/CHANGELOG.md @@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed -## [Unreleased] - 2024-03-18 +## [0.2.22] - 2024-03-21 ### Added - Tests queries (injective-cosmwasm-mock) covering functionality of querier.rs diff --git a/packages/injective-cosmwasm/Cargo.toml b/packages/injective-cosmwasm/Cargo.toml index 3275b07d..71192f3d 100644 --- a/packages/injective-cosmwasm/Cargo.toml +++ b/packages/injective-cosmwasm/Cargo.toml @@ -6,7 +6,7 @@ license = "Apache-2.0" name = "injective-cosmwasm" readme = "README.md" repository = "https://github.com/InjectiveLabs/cw-injective/tree/dev/packages/injective-cosmwasm" -version = "0.2.21" +version = "0.2.22" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies]