From f7422b44660beb54c99d744ff03db75ba5bdb5c8 Mon Sep 17 00:00:00 2001 From: Michele Meloni Date: Thu, 6 Nov 2025 15:33:11 +0100 Subject: [PATCH] chore: use external injective-testing --- Cargo.lock | 31 +- Cargo.toml | 4 +- contracts/injective-cosmwasm-mock/Cargo.toml | 2 +- packages/injective-testing/CHANGELOG.md | 24 - packages/injective-testing/Cargo.toml | 23 - packages/injective-testing/src/lib.rs | 4 - packages/injective-testing/src/mocks.rs | 66 -- .../src/multi_test/address_generator.rs | 141 --- .../src/multi_test/chain_mock.rs | 345 ------- .../injective-testing/src/multi_test/mod.rs | 2 - .../injective-testing/src/test_tube/authz.rs | 89 -- .../injective-testing/src/test_tube/bank.rs | 33 - .../src/test_tube/exchange.rs | 901 ------------------ .../src/test_tube/insurance.rs | 40 - .../injective-testing/src/test_tube/mod.rs | 6 - .../injective-testing/src/test_tube/oracle.rs | 116 --- .../injective-testing/src/test_tube/utils.rs | 24 - packages/injective-testing/src/utils.rs | 75 -- 18 files changed, 8 insertions(+), 1918 deletions(-) delete mode 100644 packages/injective-testing/CHANGELOG.md delete mode 100644 packages/injective-testing/Cargo.toml delete mode 100644 packages/injective-testing/src/lib.rs delete mode 100644 packages/injective-testing/src/mocks.rs delete mode 100644 packages/injective-testing/src/multi_test/address_generator.rs delete mode 100644 packages/injective-testing/src/multi_test/chain_mock.rs delete mode 100644 packages/injective-testing/src/multi_test/mod.rs delete mode 100644 packages/injective-testing/src/test_tube/authz.rs delete mode 100644 packages/injective-testing/src/test_tube/bank.rs delete mode 100644 packages/injective-testing/src/test_tube/exchange.rs delete mode 100644 packages/injective-testing/src/test_tube/insurance.rs delete mode 100644 packages/injective-testing/src/test_tube/mod.rs delete mode 100644 packages/injective-testing/src/test_tube/oracle.rs delete mode 100644 packages/injective-testing/src/test_tube/utils.rs delete mode 100644 packages/injective-testing/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 55a0704f..0ae4b2fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1733,7 +1733,7 @@ dependencies = [ "injective-math", "injective-std", "injective-test-tube", - "injective-testing 1.1.13-1", + "injective-testing", "prost 0.13.5", "schemars 0.8.22", "serde", @@ -1754,7 +1754,7 @@ dependencies = [ "injective-math", "injective-std", "injective-test-tube", - "injective-testing 1.1.13-1 (registry+https://github.com/rust-lang/crates.io-index)", + "injective-testing", "prost 0.13.5", "schemars 0.8.22", "serde", @@ -1822,28 +1822,7 @@ dependencies = [ [[package]] name = "injective-testing" -version = "1.1.13-1" -dependencies = [ - "anyhow", - "cosmwasm-std", - "cw-multi-test", - "injective-cosmwasm 0.3.5-1 (registry+https://github.com/rust-lang/crates.io-index)", - "injective-math", - "injective-std", - "injective-test-tube", - "prost 0.13.5", - "rand 0.4.6", - "regex", - "secp256k1 0.30.0", - "serde", - "tiny-keccak", -] - -[[package]] -name = "injective-testing" -version = "1.1.13-1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "696d6fff16d73e1f1655e69643ae259991571915a8a91d83715b67486439832b" +version = "1.2.0" dependencies = [ "anyhow", "cosmwasm-std", @@ -2321,7 +2300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.12.1", "proc-macro2", "quote", "syn 2.0.101", @@ -2334,7 +2313,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.12.1", "proc-macro2", "quote", "syn 2.0.101", diff --git a/Cargo.toml b/Cargo.toml index deb63f03..7bfa7117 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ injective-cosmwasm = { version = "0.3.5-1" } injective-math = { version = "0.3.5-1" } injective-std = { version = "1.16.4-1" } injective-test-tube = { version = "1.16.4-1" } -injective-testing = { version = "1.1.13-1"} +injective-testing = { version = "1.2.0"} primitive-types = { version = "0.12.2", default-features = false } prost = { version = "0.13.5", features = [ "prost-derive" ] } rand = { version = "0.4.6" } @@ -52,4 +52,4 @@ rpath = false # injective-cosmwasm = { path = "./packages/injective-cosmwasm" } # injective-math = { path = "./packages/injective-math" } # injective-protobuf = { path = "./packages/injective-protobuf" } -# injective-testing = { path = "./packages/injective-testing" } +injective-testing = { path = "../injective-testing" } diff --git a/contracts/injective-cosmwasm-mock/Cargo.toml b/contracts/injective-cosmwasm-mock/Cargo.toml index d9b409af..96223b37 100644 --- a/contracts/injective-cosmwasm-mock/Cargo.toml +++ b/contracts/injective-cosmwasm-mock/Cargo.toml @@ -27,6 +27,7 @@ cosmwasm-std = { workspace = true } cw-storage-plus = { workspace = true } cw2 = { workspace = true } injective-cosmwasm = { path = "../../packages/injective-cosmwasm" } +injective-testing = { workspace = true } injective-math = { version = "0.3.5-1"} injective-std = { workspace = true } prost = { workspace = true } @@ -36,4 +37,3 @@ thiserror = { workspace = true } [dev-dependencies] injective-test-tube = { workspace = true } -injective-testing = { path = "../../packages/injective-testing" } diff --git a/packages/injective-testing/CHANGELOG.md b/packages/injective-testing/CHANGELOG.md deleted file mode 100644 index 6476f48f..00000000 --- a/packages/injective-testing/CHANGELOG.md +++ /dev/null @@ -1,24 +0,0 @@ -# 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/). - -## [1.1.1] - 2024-10-02 - -### Added - -- Added a staking denom to the mocks - -## [1.1.0] - 2024-08-23 - -### Changed - -- Updated `lib.rs` so that the re-organisation is adhered to - -## [1.0.0] - 2024-08-23 - -### Changed - -- Restructure of architecture to improve organisation of helper functions and also to enable re-use with multiple projects diff --git a/packages/injective-testing/Cargo.toml b/packages/injective-testing/Cargo.toml deleted file mode 100644 index 66735212..00000000 --- a/packages/injective-testing/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -authors = ["Markus Waas ", "Jose Luis Bernal Castillo " ] -description = "Testing utils for Injective Cosmwasm and core modules" -edition = "2021" -license = "Apache-2.0" -name = "injective-testing" -repository = "https://github.com/InjectiveLabs/cw-injective/tree/dev/packages/injective-testing" -version = "1.1.13-1" - -[dependencies] -anyhow = { version = "1.0.66" } -cosmwasm-std = { version = "3.0.2", features = ["cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4", "cosmwasm_2_0", "iterator", "stargate" ] } -cw-multi-test = { version = "3.0.1" } -injective-test-tube = { version = "1.16.4-1"} -injective-cosmwasm = { version = "0.3.5-1"} -injective-math = { version = "0.3.5-1"} -injective-std = { version = "1.16.4-1"} -prost = { version = "0.13.5", features = [ "prost-derive" ] } -rand = { version = "0.4.6" } -regex = { version = "1.11.1" } -secp256k1 = { version = "0.30.0", features = [ "rand" ] } -serde = { version = "1.0.196", default-features = false, features = [ "derive" ] } -tiny-keccak = { version = "1.2.1" } diff --git a/packages/injective-testing/src/lib.rs b/packages/injective-testing/src/lib.rs deleted file mode 100644 index a7a13400..00000000 --- a/packages/injective-testing/src/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod mocks; -pub mod multi_test; -pub mod test_tube; -pub mod utils; diff --git a/packages/injective-testing/src/mocks.rs b/packages/injective-testing/src/mocks.rs deleted file mode 100644 index b2bb7c7c..00000000 --- a/packages/injective-testing/src/mocks.rs +++ /dev/null @@ -1,66 +0,0 @@ -use crate::utils::human_to_dec; - -use injective_cosmwasm::{DerivativeMarket, MarketId, MarketMidPriceAndTOBResponse, MarketStatus, OracleType, SpotMarket}; -use injective_math::FPDecimal; - -pub const MOCKED_MARKET_ID: &str = "0x01edfab47f124748dc89998eb33144af734484ba07099014594321729a0ca16b"; -pub const MOCKED_SUBACCOUNT_ID: &str = "0x427aee334987c52fa7b567b2662bdbb68614e48c000000000000000000000001"; -pub const MOCKED_FEE_RECIPIENT: &str = "0x01edfab47f124748dc89998eb33144af734484ba07099014594321729a0ca16b"; - -pub const MOCK_EXCHANGE_DECIMALS: i32 = 18i32; -pub const MOCK_BASE_DECIMALS: i32 = 18i32; -pub const MOCK_STAKE_DECIMALS: i32 = 18i32; -pub const MOCK_ATOM_DECIMALS: i32 = 8i32; -pub const MOCK_QUOTE_DECIMALS: i32 = 6i32; - -pub const MOCK_ATOM_DENOM: &str = "atom"; -pub const MOCK_BASE_DENOM: &str = "inj"; -pub const MOCK_STAKE_DENOM: &str = "hinj"; -pub const MOCK_QUOTE_DENOM: &str = "usdt"; -pub const MOCK_USDC_DENOM: &str = "usdc"; - -// Mock INJ Market -pub fn mock_spot_market(market_id: &str) -> SpotMarket { - SpotMarket { - ticker: String::from("INJ:USDT"), - base_denom: String::from("inj"), - quote_denom: String::from("usdt"), - market_id: MarketId::unchecked(market_id), - maker_fee_rate: FPDecimal::ZERO, - taker_fee_rate: FPDecimal::ZERO, - status: MarketStatus::Active, - min_price_tick_size: FPDecimal::must_from_str("0.000000000000001000"), - min_quantity_tick_size: FPDecimal::must_from_str("10000000000000.0"), // 0.00001 @ 18dp - relayer_fee_share_rate: FPDecimal::must_from_str("0.4"), - min_notional: FPDecimal::ZERO, - } -} - -// Mock INJ Market -pub fn mock_derivative_market(market_id: &str) -> DerivativeMarket { - DerivativeMarket { - ticker: String::from("INJ:USDT"), - oracle_base: String::from("inj"), - oracle_quote: String::from("usdt"), - oracle_type: OracleType::PriceFeed, - oracle_scale_factor: 0u32, - quote_denom: String::from("usdt"), - market_id: MarketId::unchecked(market_id), - initial_margin_ratio: FPDecimal::must_from_str("0.195"), - maintenance_margin_ratio: FPDecimal::must_from_str("0.05"), - maker_fee_rate: FPDecimal::ZERO, - taker_fee_rate: FPDecimal::ZERO, - isPerpetual: true, - status: MarketStatus::Active, - min_price_tick_size: FPDecimal::must_from_str("1000.0"), // 0.001 - min_quantity_tick_size: FPDecimal::must_from_str("0.001"), // 0.001 - } -} - -pub fn mock_mid_price_tob() -> MarketMidPriceAndTOBResponse { - MarketMidPriceAndTOBResponse { - mid_price: Some(human_to_dec("10.0", MOCK_QUOTE_DECIMALS - MOCK_BASE_DECIMALS)), - best_buy_price: Some(human_to_dec("9.95", MOCK_QUOTE_DECIMALS - MOCK_BASE_DECIMALS)), - best_sell_price: Some(human_to_dec("10.05", MOCK_QUOTE_DECIMALS - MOCK_BASE_DECIMALS)), - } -} diff --git a/packages/injective-testing/src/multi_test/address_generator.rs b/packages/injective-testing/src/multi_test/address_generator.rs deleted file mode 100644 index ba7bd085..00000000 --- a/packages/injective-testing/src/multi_test/address_generator.rs +++ /dev/null @@ -1,141 +0,0 @@ -use cosmwasm_std::{Addr, Storage}; -use cw_multi_test::AddressGenerator; -use injective_cosmwasm::addr_to_bech32; -use secp256k1::{rand, PublicKey, Secp256k1, SecretKey}; -use std::fmt::Write; - -const ADDRESS_LENGTH: usize = 40; -const ADDRESS_BYTES: usize = ADDRESS_LENGTH / 2; -const KECCAK_OUTPUT_BYTES: usize = 32; -const ADDRESS_BYTE_INDEX: usize = KECCAK_OUTPUT_BYTES - ADDRESS_BYTES; - -#[derive(Default)] -pub struct InjectiveAddressGenerator(); - -impl AddressGenerator for InjectiveAddressGenerator { - fn contract_address( - &self, - _api: &dyn cosmwasm_std::Api, - _storage: &mut dyn Storage, - _code_id: u64, - _instance_id: u64, - ) -> Result { - Ok(generate_inj_address()) - } - - fn predictable_contract_address( - &self, - api: &dyn cosmwasm_std::Api, - _storage: &mut dyn Storage, - _code_id: u64, - _instance_id: u64, - checksum: &[u8], - creator: &cosmwasm_std::CanonicalAddr, - salt: &[u8], - ) -> Result { - let canonical_addr = cosmwasm_std::instantiate2_address(checksum, creator, salt)?; - api.addr_humanize(&canonical_addr) - } -} - -pub struct StorageAwareInjectiveAddressGenerator { - key: String, -} - -impl Default for StorageAwareInjectiveAddressGenerator { - fn default() -> Self { - Self { - key: "generated_addresses".to_string(), - } - } -} - -impl AddressGenerator for StorageAwareInjectiveAddressGenerator { - fn contract_address( - &self, - _api: &dyn cosmwasm_std::Api, - storage: &mut dyn Storage, - _code_id: u64, - _instance_id: u64, - ) -> Result { - let generated_address = generate_inj_address(); - let key = self.key.as_bytes(); - let stored = storage.get(key); - - match stored { - Some(value) => { - let as_string = String::from_utf8_lossy(&value); - let mut split = as_string.split(',').collect::>(); - split.push(generated_address.as_str()); - let joined_as_string = split.join(","); - storage.set(key, joined_as_string.as_bytes()) - } - None => { - let value = generated_address.as_str().as_bytes(); - storage.set(key, value); - } - } - - Ok(generated_address) - } -} - -pub fn generate_inj_address() -> Addr { - let secp256k1 = Secp256k1::new(); - - let secret_key = SecretKey::new(&mut rand::thread_rng()); - - let public_key = PublicKey::from_secret_key(&secp256k1, &secret_key); - - let public_key_array = &public_key.serialize()[1..]; - - let keccak = tiny_keccak::keccak256(public_key_array); - - let address_short = to_hex_string(&keccak[ADDRESS_BYTE_INDEX..], 40); // get rid of the constant 0x04 byte - let full_address = format!("0x{address_short}"); - - let inj_address = addr_to_bech32(full_address); - - Addr::unchecked(inj_address) -} - -fn to_hex_string(slice: &[u8], expected_string_size: usize) -> String { - let mut result = String::with_capacity(expected_string_size); - - for &byte in slice { - write!(&mut result, "{byte:02x}").expect("Unable to format the public key."); - } - - result -} - -#[cfg(test)] -mod tests { - use super::*; - use regex::Regex; - - #[test] - fn test_generate_inj_address() { - // Generate an Injective address - let generated_address = generate_inj_address(); - - // Ensure the generated address is not empty - assert!(!generated_address.to_string().is_empty(), "Generated address should not be empty"); - - // Ensure the generated address starts with the Injective prefix (e.g., "inj") - assert!(generated_address.as_str().starts_with("inj"), "Generated address should start with 'inj'"); - - println!("generated address: {:?}", generated_address); - - // Ensure the address matches a valid bech32 format - let bech32_regex = Regex::new(r"^inj[0-9a-z]{39}$").unwrap(); - assert!( - bech32_regex.is_match(generated_address.as_str()), - "Generated address does not match valid bech32 format" - ); - - // Ensure each generated address is unique (you can extend this for more iterations) - let another_generated_address = generate_inj_address(); - assert_ne!(generated_address, another_generated_address, "Generated addresses should be unique"); - } -} diff --git a/packages/injective-testing/src/multi_test/chain_mock.rs b/packages/injective-testing/src/multi_test/chain_mock.rs deleted file mode 100644 index 98ae2987..00000000 --- a/packages/injective-testing/src/multi_test/chain_mock.rs +++ /dev/null @@ -1,345 +0,0 @@ -use crate::multi_test::address_generator::InjectiveAddressGenerator; -use cosmwasm_std::{ - testing::{MockApi, MockStorage}, - to_json_binary, Addr, Api, Binary, BlockInfo, Coin, CustomQuery, Empty, Querier, StdError, Storage, -}; -use cw_multi_test::{ - no_init, AddressGenerator, App, AppResponse, BankKeeper, BasicAppBuilder, CosmosRouter, Module, StargateAccepting, StargateFailing, WasmKeeper, -}; -use injective_cosmwasm::{InjectiveMsgWrapper, InjectiveQueryWrapper}; -use std::{ - cell::{Ref, RefCell}, - marker::PhantomData, - ops::Deref, - rc::Rc, -}; - -pub enum StargateT { - Accepting(StargateAccepting), - Failing(StargateFailing), -} - -pub type MockedInjectiveApp = App>; - -#[derive(Clone)] -pub struct InitialBalance { - pub amounts: Vec, - pub address: Addr, -} - -pub struct CachingCustomHandlerState { - pub execs: Rc>>, - pub queries: Rc>>, - _p: PhantomData, -} - -impl CachingCustomHandlerState -where - CustomModule: Module, - CustomModule::ExecT: Clone + 'static, - CustomModule::QueryT: CustomQuery + 'static, -{ - pub fn execs(&self) -> impl Deref + '_ { - Ref::map(self.execs.borrow(), Vec::as_slice) - } - - pub fn queries(&self) -> impl Deref + '_ { - Ref::map(self.queries.borrow(), Vec::as_slice) - } - - pub fn reset(&self) { - self.execs.borrow_mut().clear(); - self.queries.borrow_mut().clear(); - } -} - -impl Default for CachingCustomHandlerState { - fn default() -> Self { - Self { - execs: Rc::new(RefCell::new(vec![])), - queries: Rc::new(RefCell::new(vec![])), - _p: PhantomData, - } - } -} - -pub type ExecuteResponse = Result, anyhow::Error>; -pub type QueryResponse = Result; - -pub struct ExecuteResponseContainer { - response: Option, -} - -impl ExecuteResponseContainer { - pub fn with_ok_response(payload: &T) -> Self { - ExecuteResponseContainer { - response: Some(Ok(Some(to_json_binary(payload).unwrap()))), - } - } - - pub fn with_error(error: anyhow::Error) -> Self { - ExecuteResponseContainer { response: Some(Err(error)) } - } - - pub fn empty() -> Self { - ExecuteResponseContainer { response: None } - } - - pub fn is_empty(&self) -> bool { - self.response.is_none() - } -} - -pub struct QueryResponseContainer { - response: Option, -} - -impl QueryResponseContainer { - pub fn with_ok_response(payload: &T) -> Self { - QueryResponseContainer { - response: Some(Ok(to_json_binary(payload).unwrap())), - } - } - - pub fn with_error(error: anyhow::Error) -> Self { - QueryResponseContainer { response: Some(Err(error)) } - } - - pub fn empty() -> Self { - QueryResponseContainer { response: None } - } - - pub fn is_empty(&self) -> bool { - self.response.is_none() - } -} - -pub type ExecuteAssertion = fn(message: &Msg); -pub type QueryAssertion = fn(query: &Query); - -pub struct ExecuteAssertionContainer { - pub assertion: Option>, -} - -impl ExecuteAssertionContainer { - pub fn new(assertion: ExecuteAssertion) -> Self { - ExecuteAssertionContainer { assertion: Some(assertion) } - } - - pub fn empty() -> Self { - ExecuteAssertionContainer { assertion: None } - } - - pub fn is_empty(&self) -> bool { - self.assertion.is_none() - } -} - -pub struct QueryAssertionContainer { - pub assertion: Option>, -} - -impl QueryAssertionContainer { - pub fn new(assertion: QueryAssertion) -> Self { - QueryAssertionContainer { assertion: Some(assertion) } - } - - pub fn empty() -> Self { - QueryAssertionContainer { assertion: None } - } - - pub fn is_empty(&self) -> bool { - self.assertion.is_none() - } -} - -pub struct CustomInjectiveHandlerAssertions { - pub executes: Vec>, - pub queries: Vec>, -} - -impl Default for CustomInjectiveHandlerAssertions { - fn default() -> Self { - Self { - executes: vec![], - queries: vec![], - } - } -} - -#[derive(Default)] -pub struct CustomInjectiveHandlerResponses { - pub executes: Vec, - pub queries: Vec, -} - -#[derive(Default)] -pub struct CustomInjectiveHandler { - pub state: CachingCustomHandlerState, - pub responses: CustomInjectiveHandlerResponses, - pub assertions: CustomInjectiveHandlerAssertions, - pub enable_debug: bool, -} - -impl Module for CustomInjectiveHandler { - type ExecT = InjectiveMsgWrapper; - type QueryT = InjectiveQueryWrapper; - type SudoT = Empty; - - fn execute( - &self, - _api: &dyn Api, - _storage: &mut dyn Storage, - _router: &dyn CosmosRouter, - _block: &BlockInfo, - _sender: Addr, - msg: Self::ExecT, - ) -> Result { - let mut exec_calls_count = self.state.execs.borrow().len(); - - if !self.assertions.executes.is_empty() - && exec_calls_count < self.assertions.executes.len() - && !self.assertions.executes[exec_calls_count].is_empty() - { - self.assertions.executes[exec_calls_count].assertion.unwrap()(&msg); - } - - self.state.execs.borrow_mut().push(msg.clone()); - exec_calls_count += 1; - - if self.enable_debug { - println!("[{exec_calls_count}] Execute message: {msg:?}"); - } - - if self.responses.executes.is_empty() - || exec_calls_count > self.responses.executes.len() - || self.responses.executes[exec_calls_count - 1].is_empty() - { - return Ok(AppResponse::default()); - } - - let stored_result = self.responses.executes.get(exec_calls_count - 1).unwrap().response.as_ref().unwrap(); - - // In order to implement the trait that method has to receive &self and neither Result nor Binary implements Copy - // and that's the reason why I'm manually copying the underlying [u8] in order to return owned data - match &stored_result { - Ok(optional_data) => match &optional_data { - Some(binary) => Ok(AppResponse { - events: vec![], - data: Some(copy_binary(binary)), - }), - &None => Ok(AppResponse::default()), - }, - Err(e) => Err(StdError::msg(e.to_string())), - } - } - - fn query( - &self, - _api: &dyn Api, - _storage: &dyn Storage, - _querier: &dyn Querier, - _block: &BlockInfo, - request: Self::QueryT, - ) -> Result { - let mut query_calls_count = self.state.queries.borrow().len(); - - if !self.assertions.queries.is_empty() - && query_calls_count < self.assertions.queries.len() - && !self.assertions.queries[query_calls_count].is_empty() - { - self.assertions.queries[query_calls_count].assertion.unwrap()(&request); - } - - self.state.queries.borrow_mut().push(request.clone()); - query_calls_count += 1; - - if self.enable_debug { - println!("[{query_calls_count}] Query request: {request:?}"); - } - - if self.responses.queries.is_empty() - || query_calls_count > self.responses.queries.len() - || self.responses.queries[query_calls_count - 1].is_empty() - { - Ok(Binary::default()) - } else { - let stored_result = self.responses.queries.get(query_calls_count - 1).unwrap().response.as_ref().unwrap(); - - // In order to implement the trait that method has to receive &self and neither Result nor Binary implements Copy - // and that's the reason why I'm manually copying the underlying [u8] in order to return owned data - match &stored_result { - Ok(optional_data) => Ok(copy_binary(optional_data)), - Err(e) => Err(StdError::msg(e.to_string())), - } - } - } - - fn sudo( - &self, - _api: &dyn Api, - _storage: &mut dyn Storage, - _router: &dyn CosmosRouter, - _block: &BlockInfo, - msg: Self::SudoT, - ) -> Result { - Err(StdError::msg(format!("Unexpected sudo msg {:?}", msg))) - } -} - -pub fn mock_custom_injective_chain_app( - initial_balances: Vec, - execute_responses: Vec, - query_responses: Vec, - execute_assertions: Vec>, - query_assertions: Vec>, - address_generator: Option, - enable_debug: bool, -) -> MockedInjectiveApp { - let inj_handler = CustomInjectiveHandler { - responses: CustomInjectiveHandlerResponses { - executes: execute_responses, - queries: query_responses, - }, - assertions: CustomInjectiveHandlerAssertions { - executes: execute_assertions, - queries: query_assertions, - }, - enable_debug, - ..Default::default() - }; - - let inj_wasm_keeper = match address_generator { - Some(generator) => WasmKeeper::::new().with_address_generator(generator), - None => WasmKeeper::::new().with_address_generator(InjectiveAddressGenerator()), - }; - - BasicAppBuilder::new_custom() - .with_custom(inj_handler) - .with_wasm::>(inj_wasm_keeper) - .build(|router, _, storage| { - initial_balances.into_iter().for_each(|balance| { - router - .bank - .init_balance(storage, &balance.address, balance.amounts) - .expect("balances added") - }) - }) -} - -pub fn mock_default_injective_chain_app() -> MockedInjectiveApp { - let inj_wasm_keeper = WasmKeeper::::new().with_address_generator(InjectiveAddressGenerator()); - - let inj_handler = CustomInjectiveHandler::default(); - - BasicAppBuilder::new_custom() - .with_custom(inj_handler) - .with_wasm::>(inj_wasm_keeper) - .build(no_init) -} - -fn copy_binary(binary: &Binary) -> Binary { - let mut c: Vec = vec![0; binary.to_vec().len()]; - c.clone_from_slice(binary); - Binary::new(c) -} diff --git a/packages/injective-testing/src/multi_test/mod.rs b/packages/injective-testing/src/multi_test/mod.rs deleted file mode 100644 index d670f997..00000000 --- a/packages/injective-testing/src/multi_test/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod address_generator; -pub mod chain_mock; diff --git a/packages/injective-testing/src/test_tube/authz.rs b/packages/injective-testing/src/test_tube/authz.rs deleted file mode 100644 index 2ce68ce3..00000000 --- a/packages/injective-testing/src/test_tube/authz.rs +++ /dev/null @@ -1,89 +0,0 @@ -use injective_test_tube::{ - injective_std::{ - shim::{Any, Timestamp}, - types::cosmos::{ - authz::v1beta1::{GenericAuthorization, Grant, MsgGrant, MsgRevoke, MsgRevokeResponse}, - bank::v1beta1::SendAuthorization, - base::v1beta1::Coin as BaseCoin, - }, - }, - Account, Authz, ExecuteResponse, InjectiveTestApp, Module, Runner, SigningAccount, -}; -use prost::Message; - -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: GenericAuthorization::TYPE_URL.to_string(), - value: buf.clone(), - }), - expiration, - }), - }, - granter, - ) - .unwrap(); -} - -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_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: SendAuthorization::TYPE_URL.to_string(), - value: buf.clone(), - }), - expiration, - }), - }, - granter, - ) - .unwrap(); -} - -pub fn execute_generic_authorizations(app: &InjectiveTestApp, granter: &SigningAccount, grantee: String, msgs: Vec) { - for msg in msgs { - create_generic_authorization(app, granter, grantee.clone(), msg, None); - } -} diff --git a/packages/injective-testing/src/test_tube/bank.rs b/packages/injective-testing/src/test_tube/bank.rs deleted file mode 100644 index 91e08db6..00000000 --- a/packages/injective-testing/src/test_tube/bank.rs +++ /dev/null @@ -1,33 +0,0 @@ -use cosmwasm_std::Uint128; -use injective_test_tube::{ - injective_std::types::cosmos::{ - bank::v1beta1::{MsgSend, QueryBalanceRequest}, - base::v1beta1::Coin, - }, - Account, Bank, InjectiveTestApp, SigningAccount, -}; -use std::str::FromStr; - -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![Coin { - amount: amount.to_string(), - denom: denom.to_string(), - }], - }, - from, - ) - .unwrap(); -} - -pub fn query_balance(bank: &Bank, address: String, denom: String) -> Uint128 { - let response = bank.query_balance(&QueryBalanceRequest { address, denom }).unwrap(); - - match response.balance { - Some(balance) => Uint128::from_str(&balance.amount).unwrap(), - None => Uint128::zero(), - } -} diff --git a/packages/injective-testing/src/test_tube/exchange.rs b/packages/injective-testing/src/test_tube/exchange.rs deleted file mode 100644 index 84b3475c..00000000 --- a/packages/injective-testing/src/test_tube/exchange.rs +++ /dev/null @@ -1,901 +0,0 @@ -use crate::{ - mocks::{ - MOCK_ATOM_DECIMALS, MOCK_ATOM_DENOM, MOCK_BASE_DECIMALS, MOCK_BASE_DENOM, MOCK_QUOTE_DECIMALS, MOCK_QUOTE_DENOM, MOCK_STAKE_DECIMALS, - MOCK_STAKE_DENOM, MOCK_USDC_DENOM, - }, - utils::{dec_to_proto, scale_price_quantity_perp_market, scale_price_quantity_spot_market, str_coin}, -}; - -use cosmwasm_std::{Addr, Uint128}; -use injective_cosmwasm::{get_default_subaccount_id_for_checked_address, SubaccountId}; -use injective_math::FPDecimal; -use injective_std::types::cosmos::gov; -use injective_test_tube::{ - injective_std::{ - shim::Any, - types::{ - cosmos::{ - base::v1beta1::Coin as BaseCoin, - gov::v1::{MsgSubmitProposal, MsgVote}, - }, - injective::exchange::v1beta1::{ - BatchExchangeModificationProposal, DenomDecimals, DenomMinNotional, DenomMinNotionalProposal, DerivativeOrder, MsgBatchUpdateOrders, - MsgBatchUpdateOrdersResponse, MsgCancelDerivativeOrder, MsgCreateDerivativeLimitOrder, MsgCreateDerivativeLimitOrderResponse, - MsgCreateSpotLimitOrder, MsgInstantSpotMarketLaunch, MsgUpdateParams, OrderInfo, OrderType, PerpetualMarketFunding, Position, - QueryDerivativeMarketsRequest, QueryExchangeParamsRequest, QueryExchangeParamsResponse, QuerySpotMarketsRequest, - QuerySubaccountDepositsRequest, QuerySubaccountEffectivePositionInMarketRequest, SpotOrder, UpdateDenomDecimalsProposal, - }, - injective::exchange::v2, - }, - }, - Account, Exchange, Gov, InjectiveTestApp, Module, Runner, SigningAccount, -}; -use prost::Message; -use std::str::FromStr; - -pub fn add_exchange_admin(app: &InjectiveTestApp, validator: &SigningAccount, admin_address: String) { - let gov = Gov::new(app); - - let res: QueryExchangeParamsResponse = app - .query("/injective.exchange.v1beta1.Query/QueryExchangeParams", &QueryExchangeParamsRequest {}) - .unwrap(); - - let mut exchange_params = res.params.unwrap(); - exchange_params.exchange_admins.push(admin_address); - exchange_params.max_derivative_order_side_count = 300u32; - - // NOTE: this could change in the future - let governance_module_address = "inj10d07y265gmmuvt4z0w9aw880jnsr700jstypyt"; - - let mut buf = vec![]; - MsgUpdateParams::encode( - &MsgUpdateParams { - authority: governance_module_address.to_string(), - params: Some(exchange_params), - }, - &mut buf, - ) - .unwrap(); - - let res = gov - .submit_proposal( - MsgSubmitProposal { - messages: vec![Any { - type_url: MsgUpdateParams::TYPE_URL.to_string(), - value: buf, - }], - initial_deposit: vec![BaseCoin { - amount: "100000000000000000000".to_string(), - denom: "inj".to_string(), - }], - proposer: validator.address(), - metadata: "".to_string(), - title: "Update params".to_string(), - summary: "Basically updating the params".to_string(), - expedited: false, - }, - validator, - ) - .unwrap(); - - let proposal_id = res.events.iter().find(|e| e.ty == "submit_proposal").unwrap().attributes[0].value.clone(); - - gov.vote( - MsgVote { - proposal_id: u64::from_str(&proposal_id).unwrap(), - voter: validator.address(), - option: 1i32, - metadata: "".to_string(), - }, - validator, - ) - .unwrap(); - - // Increase time to pass the proposal - app.increase_time(20u64); -} - -pub fn add_denom_notional_and_decimal(app: &InjectiveTestApp, validator: &SigningAccount, denom: String, min_notional: String, decimals: u64) { - let gov = Gov::new(app); - - let proposal = BatchExchangeModificationProposal { - title: "Update params".to_string(), - description: "Basically updating the params".to_string(), - spot_market_param_update_proposals: vec![], - derivative_market_param_update_proposals: vec![], - spot_market_launch_proposals: vec![], - perpetual_market_launch_proposals: vec![], - expiry_futures_market_launch_proposals: vec![], - trading_reward_campaign_update_proposal: None, - binary_options_market_launch_proposals: vec![], - binary_options_param_update_proposals: vec![], - denom_decimals_update_proposal: Some(UpdateDenomDecimalsProposal { - title: "Update denom decimals".to_string(), - description: "Love it!".to_string(), - denom_decimals: vec![DenomDecimals { - denom: denom.clone(), - decimals, - }], - }), - fee_discount_proposal: None, - market_forced_settlement_proposals: vec![], - denom_min_notional_proposal: Some(DenomMinNotionalProposal { - title: "Update min notional".to_string(), - description: "Love it!".to_string(), - denom_min_notionals: vec![DenomMinNotional { denom, min_notional }], - }), - }; - - let mut buf = vec![]; - proposal.encode(&mut buf).unwrap(); - - let content_any = Any { - type_url: "/injective.exchange.v2.BatchExchangeModificationProposal".to_string(), - value: buf, - }; - - let msg_submit_proposal = gov::v1beta1::MsgSubmitProposal { - content: Some(content_any), - initial_deposit: vec![BaseCoin { - amount: "100000000000000000000".to_string(), - denom: "inj".to_string(), - }], - proposer: validator.address(), - }; - - let res = gov.submit_proposal_v1beta1(msg_submit_proposal, validator).unwrap(); - - let proposal_id = res.events.iter().find(|e| e.ty == "submit_proposal").unwrap().attributes[0].value.clone(); - - gov.vote( - MsgVote { - proposal_id: u64::from_str(&proposal_id).unwrap(), - voter: validator.address(), - option: 1i32, - metadata: "".to_string(), - }, - validator, - ) - .unwrap(); - - // Increase time to pass the proposal - app.increase_time(20u64); -} - -pub fn create_perp_mid_price(app: &InjectiveTestApp, market_id: &str, base_price: &str, base_quantity: &str, base_margin: &str, spread: f64) { - // Calculate adjusted prices for buy and sell based on the spread - let sell_price = format!("{:.1}", base_price.parse::().unwrap() + spread); - let buy_price = format!("{:.1}", base_price.parse::().unwrap() - spread); - - // Scaling and executing the sell order - let (price, quantity, margin) = scale_price_quantity_perp_market(&sell_price, base_quantity, base_margin, &MOCK_QUOTE_DECIMALS); - execute_derivative_limit_order(app, market_id.to_string(), price, quantity, margin, OrderType::Sell); - - // Scaling and executing the buy order - let (price, quantity, margin) = scale_price_quantity_perp_market(&buy_price, base_quantity, base_margin, &MOCK_QUOTE_DECIMALS); - execute_derivative_limit_order(app, market_id.to_string(), price, quantity, margin, OrderType::Buy); -} - -pub fn create_perp_mid_price_as( - app: &InjectiveTestApp, - market_id: &str, - base_price: &str, - base_quantity: &str, - base_margin: &str, - spread: f64, - trader: &SigningAccount, - subaccount_id: &SubaccountId, -) { - // Calculate adjusted prices for buy and sell based on the spread - let sell_price = format!("{}", base_price.parse::().unwrap() + spread); - let buy_price = format!("{}", base_price.parse::().unwrap() - spread); - - // Scaling and executing the sell order - let (price, quantity, margin) = scale_price_quantity_perp_market(&sell_price, base_quantity, base_margin, &MOCK_QUOTE_DECIMALS); - execute_derivative_limit_order_as( - app, - market_id.to_string(), - price, - quantity, - margin, - OrderType::Sell, - trader, - subaccount_id, - ); - - // Scaling and executing the buy order - let (price, quantity, margin) = scale_price_quantity_perp_market(&buy_price, base_quantity, base_margin, &MOCK_QUOTE_DECIMALS); - execute_derivative_limit_order_as(app, market_id.to_string(), price, quantity, margin, OrderType::Buy, trader, subaccount_id); -} - -pub fn create_spot_mid_price( - app: &InjectiveTestApp, - market_id: &str, - base_price: &str, - base_quantity: &str, - base_decimals: &i32, - quote_decimals: &i32, - spread: f64, -) { - // Calculate adjusted prices for buy and sell based on the spread - let sell_price = format!("{}", base_price.parse::().unwrap() + spread); - let buy_price = format!("{}", base_price.parse::().unwrap() - spread); - - // Scaling and executing the sell order - let (price, quantity) = scale_price_quantity_spot_market(&sell_price, base_quantity, base_decimals, quote_decimals); - execute_spot_limit_order(app, market_id.to_string(), price, quantity, OrderType::Sell); - - // Scaling and executing the buy order - let (price, quantity) = scale_price_quantity_spot_market(&buy_price, base_quantity, base_decimals, quote_decimals); - execute_spot_limit_order(app, market_id.to_string(), price, quantity, OrderType::Buy); -} - -pub fn create_spot_mid_price_as( - app: &InjectiveTestApp, - market_id: &str, - base_price: &str, - base_quantity: &str, - base_decimals: &i32, - quote_decimals: &i32, - spread: f64, - trader: &SigningAccount, - subaccount_id: &SubaccountId, -) { - // Calculate adjusted prices for buy and sell based on the spread - let sell_price = format!("{:.1}", base_price.parse::().unwrap() + spread); - let buy_price = format!("{:.1}", base_price.parse::().unwrap() - spread); - - // Scaling and executing the sell order - let (price, quantity) = scale_price_quantity_spot_market(&sell_price, base_quantity, base_decimals, quote_decimals); - execute_spot_limit_order_as(app, market_id.to_string(), price, quantity, OrderType::Sell, trader, subaccount_id); - - // Scaling and executing the buy order - let (price, quantity) = scale_price_quantity_spot_market(&buy_price, base_quantity, base_decimals, quote_decimals); - execute_spot_limit_order_as(app, market_id.to_string(), price, quantity, OrderType::Buy, trader, subaccount_id); -} - -pub fn create_price_perp( - app: &InjectiveTestApp, - market_id: &str, - base_price: &str, - base_quantity: &str, - base_margin: &str, - spread: f64, - trader: &SigningAccount, - subaccount_id: &SubaccountId, -) -> MsgBatchUpdateOrdersResponse { - let exchange = Exchange::new(app); - - // Calculate adjusted prices for buy and sell based on the spread - let sell_price = format!("{}", base_price.parse::().unwrap() + spread); - let buy_price = format!("{}", base_price.parse::().unwrap() - spread); - - // Scaling and executing the sell order - let (sell_price, sell_quantity, sell_margin) = scale_price_quantity_perp_market(&sell_price, base_quantity, base_margin, &MOCK_QUOTE_DECIMALS); - - // Scaling and executing the buy order - let (buy_price, buy_quantity, buy_margin) = scale_price_quantity_perp_market(&buy_price, base_quantity, base_margin, &MOCK_QUOTE_DECIMALS); - - exchange - .batch_update_orders( - MsgBatchUpdateOrders { - sender: trader.address(), - subaccount_id: subaccount_id.as_str().to_string(), - derivative_market_ids_to_cancel_all: vec![market_id.to_string()], - derivative_orders_to_create: vec![ - DerivativeOrder { - market_id: market_id.to_string(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.as_str().to_string(), - fee_recipient: trader.address(), - price: buy_price.clone(), - quantity: buy_quantity.clone(), - cid: "".to_string(), - }), - margin: buy_margin.clone(), - order_type: OrderType::Buy.into(), - trigger_price: "".to_string(), - }, - DerivativeOrder { - market_id: market_id.to_string(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.as_str().to_string(), - fee_recipient: trader.address(), - price: sell_price.clone(), - quantity: sell_quantity.clone(), - cid: "".to_string(), - }), - margin: sell_margin.clone(), - order_type: OrderType::Sell.into(), - trigger_price: "".to_string(), - }, - ], - ..Default::default() - }, - trader, - ) - .unwrap() - .data -} - -pub fn create_price_spot( - app: &InjectiveTestApp, - market_id: &str, - base_price: &str, - base_quantity: &str, - spread: f64, - trader: &SigningAccount, - subaccount_id: &SubaccountId, -) -> MsgBatchUpdateOrdersResponse { - let exchange = Exchange::new(app); - - // Calculate adjusted prices for buy and sell based on the spread - let sell_price = format!("{}", base_price.parse::().unwrap() + spread); - let buy_price = format!("{}", base_price.parse::().unwrap() - spread); - - // Scaling and executing the sell order - let (sell_price, sell_quantity) = scale_price_quantity_spot_market(&sell_price, base_quantity, &MOCK_BASE_DECIMALS, &MOCK_QUOTE_DECIMALS); - - // Scaling and executing the buy order - let (buy_price, buy_quantity) = scale_price_quantity_spot_market(&buy_price, base_quantity, &MOCK_BASE_DECIMALS, &MOCK_QUOTE_DECIMALS); - - exchange - .batch_update_orders( - MsgBatchUpdateOrders { - sender: trader.address(), - subaccount_id: subaccount_id.as_str().to_string(), - spot_market_ids_to_cancel_all: vec![market_id.to_string()], - spot_orders_to_create: vec![ - SpotOrder { - market_id: market_id.to_string(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.as_str().to_string(), - fee_recipient: trader.address(), - price: buy_price.clone(), - quantity: buy_quantity.clone(), - cid: "".to_string(), - }), - order_type: OrderType::Buy.into(), - trigger_price: "".to_string(), - }, - SpotOrder { - market_id: market_id.to_string(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.as_str().to_string(), - fee_recipient: trader.address(), - price: sell_price.clone(), - quantity: sell_quantity.clone(), - cid: "".to_string(), - }), - order_type: OrderType::Sell.into(), - trigger_price: "".to_string(), - }, - ], - ..Default::default() - }, - trader, - ) - .unwrap() - .data -} - -pub fn create_price_spot_and_perp_market( - app: &InjectiveTestApp, - perp_market_id: &str, - spot_market_id: &str, - base_price: &str, - base_quantity: &str, - base_margin: &str, - spread: f64, - trader: &SigningAccount, - subaccount_id: &SubaccountId, -) -> MsgBatchUpdateOrdersResponse { - let exchange = Exchange::new(app); - - // Calculate adjusted prices for buy and sell based on the spread - let sell_price = format!("{}", base_price.parse::().unwrap() + spread); - let buy_price = format!("{}", base_price.parse::().unwrap() - spread); - - // Scaling and executing the sell order - let (perp_sell_price, perp_sell_quantity, perp_sell_margin) = - scale_price_quantity_perp_market(&sell_price, base_quantity, base_margin, &MOCK_QUOTE_DECIMALS); - - // Scaling and executing the buy order - let (perp_buy_price, perp_buy_quantity, perp_buy_margin) = - scale_price_quantity_perp_market(&buy_price, base_quantity, base_margin, &MOCK_QUOTE_DECIMALS); - - // Scaling and executing the sell order - let (spot_sell_price, spot_sell_quantity) = - scale_price_quantity_spot_market(&sell_price, base_quantity, &MOCK_BASE_DECIMALS, &MOCK_QUOTE_DECIMALS); - - // Scaling and executing the buy order - let (spot_buy_price, spot_buy_quantity) = scale_price_quantity_spot_market(&buy_price, base_quantity, &MOCK_BASE_DECIMALS, &MOCK_QUOTE_DECIMALS); - - exchange - .batch_update_orders( - MsgBatchUpdateOrders { - sender: trader.address(), - subaccount_id: subaccount_id.as_str().to_string(), - derivative_market_ids_to_cancel_all: vec![perp_market_id.to_string()], - spot_market_ids_to_cancel_all: vec![spot_market_id.to_string()], - derivative_orders_to_create: vec![ - DerivativeOrder { - market_id: perp_market_id.to_string(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.as_str().to_string(), - fee_recipient: trader.address(), - price: perp_buy_price.clone(), - quantity: perp_buy_quantity.clone(), - cid: "".to_string(), - }), - margin: perp_buy_margin.clone(), - order_type: OrderType::Buy.into(), - trigger_price: "".to_string(), - }, - DerivativeOrder { - market_id: perp_market_id.to_string(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.as_str().to_string(), - fee_recipient: trader.address(), - price: perp_sell_price.clone(), - quantity: perp_sell_quantity.clone(), - cid: "".to_string(), - }), - margin: perp_sell_margin.clone(), - order_type: OrderType::Sell.into(), - trigger_price: "".to_string(), - }, - ], - spot_orders_to_create: vec![ - SpotOrder { - market_id: spot_market_id.to_string(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.as_str().to_string(), - fee_recipient: trader.address(), - price: spot_buy_price.clone(), - quantity: spot_buy_quantity.clone(), - cid: "".to_string(), - }), - order_type: OrderType::Buy.into(), - trigger_price: "".to_string(), - }, - SpotOrder { - market_id: spot_market_id.to_string(), - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.as_str().to_string(), - fee_recipient: trader.address(), - price: spot_sell_price.clone(), - quantity: spot_sell_quantity.clone(), - cid: "".to_string(), - }), - order_type: OrderType::Sell.into(), - trigger_price: "".to_string(), - }, - ], - ..Default::default() - }, - trader, - ) - .unwrap() - .data -} - -pub fn cancel_derivative_order_as( - app: &InjectiveTestApp, - market_id: String, - order_hash: String, - trader: &SigningAccount, - subaccount_id: &SubaccountId, -) { - let exchange = Exchange::new(app); - - exchange - .cancel_derivative_order( - MsgCancelDerivativeOrder { - sender: trader.address(), - market_id, - subaccount_id: subaccount_id.as_str().to_string(), - order_hash, - order_mask: 0i32, - cid: "".to_string(), - }, - trader, - ) - .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: MOCK_BASE_DENOM.to_string(), - quote_denom: MOCK_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_notional: dec_to_proto(FPDecimal::must_from_str("1")), - base_decimals: MOCK_BASE_DECIMALS as u32, - quote_decimals: MOCK_QUOTE_DECIMALS as u32, - }, - signer, - ) - .unwrap(); - - get_spot_market_id(exchange, ticker) -} - -pub fn launch_spot_market_atom(exchange: &Exchange, signer: &SigningAccount, ticker: String) -> String { - exchange - .instant_spot_market_launch_v2( - v2::MsgInstantSpotMarketLaunch { - sender: signer.address(), - ticker: "ATOM/USDT".to_owned(), - base_denom: MOCK_ATOM_DENOM.to_owned(), - quote_denom: MOCK_QUOTE_DENOM.to_owned(), - min_price_tick_size: dec_to_proto(FPDecimal::must_from_str("0.000010000000000000")), - min_quantity_tick_size: dec_to_proto(FPDecimal::must_from_str("100000")), - min_notional: dec_to_proto(FPDecimal::must_from_str("1")), - base_decimals: MOCK_ATOM_DECIMALS as u32, - quote_decimals: MOCK_QUOTE_DECIMALS as u32, - }, - signer, - ) - .unwrap(); - - get_spot_market_id(exchange, ticker) -} - -pub fn launch_spot_market_custom( - exchange: &Exchange, - signer: &SigningAccount, - ticker: String, - base_denom: String, - quote_denom: String, - min_price_tick_size: String, - min_quantity_tick_size: String, -) -> String { - exchange - .instant_spot_market_launch( - MsgInstantSpotMarketLaunch { - sender: signer.address(), - ticker: ticker.clone(), - base_denom, - quote_denom, - min_price_tick_size: dec_to_proto(FPDecimal::must_from_str(&min_price_tick_size)), - min_quantity_tick_size: dec_to_proto(FPDecimal::must_from_str(&min_quantity_tick_size)), - min_notional: dec_to_proto(FPDecimal::must_from_str("1")), - base_decimals: MOCK_BASE_DECIMALS as u32, - quote_decimals: MOCK_QUOTE_DECIMALS as u32, - }, - signer, - ) - .unwrap(); - - get_spot_market_id(exchange, ticker) -} - -pub fn launch_spot_market_custom_v2( - exchange: &Exchange, - signer: &SigningAccount, - ticker: String, - base_denom: String, - quote_denom: String, - min_price_tick_size: String, - min_quantity_tick_size: String, - base_decimals: u32, - quote_decimals: u32, -) -> String { - exchange - .instant_spot_market_launch_v2( - v2::MsgInstantSpotMarketLaunch { - sender: signer.address(), - ticker: ticker.clone(), - base_denom, - quote_denom, - min_price_tick_size: dec_to_proto(FPDecimal::must_from_str(&min_price_tick_size)), - min_quantity_tick_size: dec_to_proto(FPDecimal::must_from_str(&min_quantity_tick_size)), - min_notional: dec_to_proto(FPDecimal::must_from_str("1")), - base_decimals, - quote_decimals, - }, - signer, - ) - .unwrap(); - - get_spot_market_id(exchange, ticker) -} - -pub fn launch_perp_market(exchange: &Exchange, signer: &SigningAccount, ticker: String) -> String { - exchange - .instant_perpetual_market_launch_v2( - v2::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: "-000100000000000000".to_owned(), - taker_fee_rate: "0005000000000000000".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(), - min_notional: dec_to_proto(FPDecimal::must_from_str("1")), - reduce_margin_ratio: "150000000000000000".to_string(), - }, - signer, - ) - .unwrap(); - - get_perpetual_market_id(exchange, ticker) -} - -pub fn launch_perp_market_atom(exchange: &Exchange, signer: &SigningAccount, ticker: String) -> String { - exchange - .instant_perpetual_market_launch_v2( - v2::MsgInstantPerpetualMarketLaunch { - sender: signer.address(), - ticker: ticker.to_owned(), - quote_denom: MOCK_QUOTE_DENOM.to_owned(), - oracle_base: MOCK_ATOM_DENOM.to_owned(), - oracle_quote: MOCK_QUOTE_DENOM.to_owned(), - oracle_scale_factor: 6u32, - oracle_type: 2i32, - maker_fee_rate: "-000100000000000000".to_owned(), - taker_fee_rate: "0005000000000000000".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: "10000000000000000".to_owned(), - min_notional: dec_to_proto(FPDecimal::must_from_str("1")), - reduce_margin_ratio: "150000000000000000".to_string(), - }, - signer, - ) - .unwrap(); - - get_perpetual_market_id(exchange, ticker) -} - -pub fn execute_spot_limit_order(app: &InjectiveTestApp, market_id: String, price: String, quantity: String, order_type: OrderType) { - let trader = app - .init_account(&[ - str_coin("1000000", MOCK_ATOM_DENOM, MOCK_ATOM_DECIMALS), - str_coin("1000000", MOCK_BASE_DENOM, MOCK_BASE_DECIMALS), - str_coin("1000000", MOCK_STAKE_DENOM, MOCK_STAKE_DECIMALS), - str_coin("1000000", MOCK_QUOTE_DENOM, MOCK_QUOTE_DECIMALS), - str_coin("1000000", MOCK_USDC_DENOM, MOCK_QUOTE_DECIMALS), - ]) - .unwrap(); - - let exchange = Exchange::new(app); - - exchange - .create_spot_limit_order( - MsgCreateSpotLimitOrder { - sender: trader.address(), - order: Some(SpotOrder { - market_id, - 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, - cid: "".to_string(), - }), - order_type: order_type.into(), - trigger_price: "".to_string(), - }), - }, - &trader, - ) - .unwrap(); -} - -pub fn execute_spot_limit_order_as( - app: &InjectiveTestApp, - market_id: String, - price: String, - quantity: String, - order_type: OrderType, - trader: &SigningAccount, - subaccount_id: &SubaccountId, -) { - let exchange = Exchange::new(app); - - exchange - .create_spot_limit_order( - MsgCreateSpotLimitOrder { - sender: trader.address(), - order: Some(SpotOrder { - market_id, - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.as_str().to_string(), - fee_recipient: trader.address(), - price, - quantity, - cid: "".to_string(), - }), - order_type: order_type.into(), - trigger_price: "".to_string(), - }), - }, - trader, - ) - .unwrap(); -} - -pub fn estimate_funding_apy(funding_info: &PerpetualMarketFunding, position: &Position) -> FPDecimal { - let cumulative_funding = FPDecimal::from_str(&funding_info.cumulative_funding).unwrap(); - let cumulative_funding_entry = FPDecimal::from_str(&position.cumulative_funding_entry).unwrap(); - - cumulative_funding - cumulative_funding_entry -} - -pub fn execute_derivative_limit_order( - app: &InjectiveTestApp, - market_id: String, - price: String, - quantity: String, - margin: String, - order_type: OrderType, -) { - let trader = app - .init_account(&[ - str_coin("1000000", MOCK_ATOM_DENOM, MOCK_ATOM_DECIMALS), - str_coin("1000000", MOCK_BASE_DENOM, MOCK_BASE_DECIMALS), - str_coin("1000000", MOCK_STAKE_DENOM, MOCK_STAKE_DECIMALS), - str_coin("1000000", MOCK_QUOTE_DENOM, MOCK_QUOTE_DECIMALS), - ]) - .unwrap(); - - let exchange = Exchange::new(app); - - exchange - .create_derivative_limit_order( - MsgCreateDerivativeLimitOrder { - sender: trader.address(), - order: Some(DerivativeOrder { - market_id, - 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, - cid: "".to_string(), - }), - margin, - order_type: order_type.into(), - trigger_price: "".to_string(), - }), - }, - &trader, - ) - .unwrap(); -} - -pub fn execute_derivative_limit_order_as( - app: &InjectiveTestApp, - market_id: String, - price: String, - quantity: String, - margin: String, - order_type: OrderType, - trader: &SigningAccount, - subaccount_id: &SubaccountId, -) -> MsgCreateDerivativeLimitOrderResponse { - let exchange = Exchange::new(app); - - exchange - .create_derivative_limit_order( - MsgCreateDerivativeLimitOrder { - sender: trader.address(), - order: Some(DerivativeOrder { - market_id, - order_info: Some(OrderInfo { - subaccount_id: subaccount_id.as_str().to_string(), - fee_recipient: trader.address(), - price, - quantity, - cid: "".to_string(), - }), - margin, - order_type: order_type.into(), - trigger_price: "".to_string(), - }), - }, - trader, - ) - .unwrap() - .data -} - -pub fn remove_orders( - app: &InjectiveTestApp, - perp_market_id: &str, - spot_market_id: &str, - trader: &SigningAccount, - subaccount_id: &SubaccountId, -) -> MsgBatchUpdateOrdersResponse { - let exchange = Exchange::new(app); - - exchange - .batch_update_orders( - MsgBatchUpdateOrders { - sender: trader.address(), - subaccount_id: subaccount_id.as_str().to_string(), - derivative_market_ids_to_cancel_all: vec![perp_market_id.to_string()], - spot_market_ids_to_cancel_all: vec![spot_market_id.to_string()], - ..Default::default() - }, - trader, - ) - .unwrap() - .data -} - -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() -} - -pub fn get_subaccount_total_value(exchange: &Exchange, market_id: String, subaccount_id: String, denom: String) -> Uint128 { - let trade_deposits_during = exchange - .query_subaccount_deposits(&QuerySubaccountDepositsRequest { - subaccount_id: subaccount_id.clone(), - subaccount: None, - }) - .unwrap(); - - let total_balance = Uint128::from_str(&trade_deposits_during.deposits[&denom].total_balance) - .unwrap_or(Uint128::zero()) // Use zero if the result is an Err - / Uint128::one(); - - let effective_position = exchange - .query_subaccount_effective_position_in_market(&QuerySubaccountEffectivePositionInMarketRequest { market_id, subaccount_id }) - .unwrap(); - - let effective_margin = effective_position.state.as_ref().map_or(Uint128::zero(), |state| { - Uint128::from_str(&state.effective_margin).unwrap_or(Uint128::zero()) - }) / Uint128::one(); - - total_balance + effective_margin -} - -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() -} diff --git a/packages/injective-testing/src/test_tube/insurance.rs b/packages/injective-testing/src/test_tube/insurance.rs deleted file mode 100644 index 69369c62..00000000 --- a/packages/injective-testing/src/test_tube/insurance.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::{mocks::MOCK_QUOTE_DECIMALS, utils::human_to_dec}; - -use injective_test_tube::{ - injective_std::types::{ - cosmos::base::v1beta1::Coin as BaseCoin, - injective::{insurance::v1beta1::MsgCreateInsuranceFund, oracle::v1beta1::OracleType}, - }, - Account, InjectiveTestApp, Insurance, Module, SigningAccount, -}; - -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", MOCK_QUOTE_DECIMALS).to_string(), - denom: quote.to_string(), - }), - }, - signer, - ) - .unwrap(); -} diff --git a/packages/injective-testing/src/test_tube/mod.rs b/packages/injective-testing/src/test_tube/mod.rs deleted file mode 100644 index 9dfe4276..00000000 --- a/packages/injective-testing/src/test_tube/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod authz; -pub mod bank; -pub mod exchange; -pub mod insurance; -pub mod oracle; -pub mod utils; diff --git a/packages/injective-testing/src/test_tube/oracle.rs b/packages/injective-testing/src/test_tube/oracle.rs deleted file mode 100644 index 21fd52ba..00000000 --- a/packages/injective-testing/src/test_tube/oracle.rs +++ /dev/null @@ -1,116 +0,0 @@ -use injective_test_tube::{ - injective_std::{ - shim::Any, - types::{ - cosmos::{ - base::v1beta1::Coin as BaseCoin, - gov::{v1::MsgVote, v1beta1::MsgSubmitProposal as MsgSubmitProposalV1Beta1}, - }, - injective::oracle::v1beta1::{ - GrantPriceFeederPrivilegeProposal, MsgRelayPriceFeedPrice, QueryOraclePriceRequest, QueryOraclePriceResponse, - }, - }, - }, - Account, Gov, InjectiveTestApp, Module, Oracle, SigningAccount, -}; -use prost::Message; -use std::str::FromStr; - -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 relay_price_feed_price(oracle: &Oracle, relayer: &SigningAccount, base_denom: &str, quote_denom: &str, price: &str) { - oracle - .relay_price_feed( - MsgRelayPriceFeedPrice { - sender: relayer.address(), - base: vec![base_denom.to_string()], - quote: vec![quote_denom.to_string()], - price: vec![price.to_string()], - }, - relayer, - ) - .unwrap(); -} - -pub fn query_oracle_mark_price(app: &InjectiveTestApp, base_denom: &str, quote_denom: &str) -> QueryOraclePriceResponse { - let oracle = Oracle::new(app); - - oracle - .query_oracle_price(&QueryOraclePriceRequest { - oracle_type: 2, - base: base_denom.to_string(), - quote: quote_denom.to_string(), - scaling_options: None, - }) - .unwrap() -} diff --git a/packages/injective-testing/src/test_tube/utils.rs b/packages/injective-testing/src/test_tube/utils.rs deleted file mode 100644 index e28ba6aa..00000000 --- a/packages/injective-testing/src/test_tube/utils.rs +++ /dev/null @@ -1,24 +0,0 @@ -use injective_test_tube::{InjectiveTestApp, SigningAccount, Wasm}; - -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 store_code(wasm: &Wasm, owner: &SigningAccount, contract_name: String) -> u64 { - let wasm_byte_code = std::fs::read(wasm_file(contract_name)).unwrap(); - wasm.store_code(&wasm_byte_code, None, owner).unwrap().data.code_id -} diff --git a/packages/injective-testing/src/utils.rs b/packages/injective-testing/src/utils.rs deleted file mode 100644 index bc654efd..00000000 --- a/packages/injective-testing/src/utils.rs +++ /dev/null @@ -1,75 +0,0 @@ -use cosmwasm_std::{coin, Coin}; -use injective_math::{scale::Scaled, FPDecimal}; - -pub fn assert_execute_error(message: &str) -> String { - format!( - "execute error: failed to execute message; message index: 0: {}: execute wasm contract failed", - message - ) -} - -pub fn assert_instantiate_error(message: &str) -> String { - format!( - "execute error: failed to execute message; message index: 0: {}: instantiate wasm contract failed", - message - ) -} - -pub fn proto_to_dec(val: &str) -> FPDecimal { - FPDecimal::must_from_str(val).scaled(-18) -} - -pub fn dec_to_human(val: FPDecimal, exponent: i32) -> String { - val.scaled(-exponent).to_string() -} - -pub fn dec_to_proto(val: FPDecimal) -> String { - val.scaled(18).to_string() -} - -pub fn human_to_dec(raw_number: &str, decimals: i32) -> FPDecimal { - FPDecimal::must_from_str(&raw_number.replace('_', "")).scaled(decimals) -} - -pub fn human_to_dec_vector(values: Vec<&str>, decimals: i32) -> Vec { - values.iter().map(|v| human_to_dec(v, decimals)).collect::>() -} - -pub fn human_to_i64(raw_number: &str, exponent: i32) -> i64 { - let scaled_amount = FPDecimal::must_from_str(&raw_number.replace('_', "")).scaled(exponent); - let as_int: i64 = scaled_amount.to_string().parse().unwrap(); - as_int -} - -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 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 scale_price_quantity_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)) -}