use std::str::FromStr;
use cosmwasm_std::{to_json_binary, Binary, Reply, SubMsgResponse, SubMsgResult};
use enumset::enum_set;
use injective_cosmwasm::{MarketId, OracleType};
use injective_math::FPDecimal;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::vault::{
AmmInstantiateMsg, AmmOrderType, DerivativeInstantiateMsg, DerivativeRedemptionType, PricingStrategy, SpotInstantiateMsg, SpotRedemptionType,
};
pub const MOCKED_OWNER: &str = "owner";
pub const MOCKED_OWNER_VALID: &str = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku";
pub const MOCKED_MASTER_ADDRESS: &str = "inj1gfawuv6fslzjlfa4v7exv27mk6rpfeyv823eu2";
pub const MOCKED_MARKET_ID: &str = "0x01edfab47f124748dc89998eb33144af734484ba07099014594321729a0ca16b";
pub const MOCKED_DERIV_MARKET_ID: &str = "0x427aee334987c52fa7b567b2662bdbb68614e48c000000000000000000000000";
pub const MOCKED_USER: &str = "inj1995xnrrtnmtdgjmx0g937vf28dwefhkhy6gy5e";
pub fn mock_cpmm_instantiate_msg(owner: String, master_address: String, market_id: String) -> AmmInstantiateMsg {
AmmInstantiateMsg {
config_owner: owner.to_owned(),
market_id: MarketId::new(market_id).unwrap(),
master_address,
order_density: 10u8,
max_invariant_sensitivity_bps: FPDecimal::from_str("0.1").unwrap(),
max_price_sensitivity_bps: FPDecimal::from_str("0.1").unwrap(),
pricing_strategy: PricingStrategy::ConstantPricingWithTickSize(FPDecimal::must_from_str("0.00000000000001")),
base_decimals: 18u8,
quote_decimals: 6u8,
fee_bps: 0u32,
notional_value_cap: FPDecimal::from(100_000_000_000_000_000_000u128),
first_subscriber_address: None,
order_type: AmmOrderType::PostOnly,
}
}
pub fn mock_scpmm_instantiate_msg(owner: String, master_address: String, market_id: String) -> AmmInstantiateMsg {
AmmInstantiateMsg {
config_owner: owner.to_owned(),
market_id: MarketId::new(market_id).unwrap(),
master_address,
order_density: 10u8,
max_invariant_sensitivity_bps: FPDecimal::from_str("0.1").unwrap(),
max_price_sensitivity_bps: FPDecimal::from_str("0.1").unwrap(),
pricing_strategy: PricingStrategy::SmoothingPricingWithRelativePriceRange {
bid_range: FPDecimal::must_from_str("0.1"),
ask_range: FPDecimal::must_from_str("0.1"),
},
base_decimals: 18u8,
quote_decimals: 6u8,
notional_value_cap: FPDecimal::from(100_000_000_000_000_000_000u128),
fee_bps: 30u32,
first_subscriber_address: None,
order_type: AmmOrderType::PostOnly,
}
}
pub fn mock_spot_instantiate_msg(owner: String, master_address: String, market_id: String) -> SpotInstantiateMsg {
SpotInstantiateMsg {
market_id: MarketId::new(market_id).unwrap(),
order_density: 8,
reservation_price_sensitivity_ratio: FPDecimal::must_from_str("0.916"),
reservation_spread_sensitivity_ratio: FPDecimal::ONE,
max_active_capital_utilization_ratio: FPDecimal::ONE,
head_change_tolerance_ratio: FPDecimal::ONE,
head_to_tail_deviation_ratio: FPDecimal::must_from_str("0.05"),
min_volatility_ratio: FPDecimal::must_from_str("0.002"),
signed_min_head_to_fair_price_deviation_ratio: FPDecimal::must_from_str("0.01"),
signed_min_head_to_tob_deviation_ratio: FPDecimal::must_from_str("-0.01"),
default_mid_price_volatility_ratio: FPDecimal::must_from_str("0.005"),
target_base_weight: FPDecimal::ONE,
master_address,
config_owner: owner.to_owned(),
oracle_type: OracleType::PriceFeed,
allowed_redemption_types: enum_set!(SpotRedemptionType::FixedBaseAndQuote),
base_decimals: 18,
quote_decimals: 6,
base_oracle_symbol: "inj".to_string(),
quote_oracle_symbol: "usdt".to_string(),
notional_value_cap: FPDecimal::from(999_000_000_000_000_000_000_000_000u128),
oracle_stale_time: 75,
min_oracle_volatility_sample_size: 5,
emergency_oracle_volatility_sample_size: 6,
oracle_volatility_max_age: 100,
}
}
pub fn mock_derivative_instantiate_msg(owner: String, master_address: String, market_id: String) -> DerivativeInstantiateMsg {
DerivativeInstantiateMsg {
market_id: MarketId::new(market_id).unwrap(),
leverage: FPDecimal::TWO,
order_density: 3,
reservation_price_sensitivity_ratio: FPDecimal::must_from_str("0.1"),
reservation_spread_sensitivity_ratio: FPDecimal::must_from_str("0.2"),
max_active_capital_utilization_ratio: FPDecimal::must_from_str("0.8"),
signed_min_head_to_fair_price_deviation_ratio: FPDecimal::must_from_str("0.1"),
signed_min_head_to_tob_deviation_ratio: FPDecimal::must_from_str("0.1"),
head_change_tolerance_ratio: FPDecimal::must_from_str("0.4"),
min_proximity_to_liquidation: FPDecimal::must_from_str("1.4"),
min_oracle_volatility_sample_size: 5,
emergency_oracle_volatility_sample_size: 6,
oracle_volatility_max_age: 100,
default_mid_price_volatility_ratio: FPDecimal::must_from_str("0.88"),
min_volatility_ratio: FPDecimal::must_from_str("0.001"),
master_address,
config_owner: owner.to_owned(),
head_to_tail_deviation_ratio: FPDecimal::must_from_str("0.1"),
allowed_redemption_types: enum_set!(DerivativeRedemptionType::QuoteOnly | DerivativeRedemptionType::PositionAndQuote),
position_pnl_penalty: FPDecimal::must_from_str("0.01"),
notional_value_cap: FPDecimal::from(999_000_000_000_000_000_000u128),
oracle_stale_time: 60 * 60 * 6,
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct MockedMsgInstantiateContractResponse {
pub contract_address: String,
pub data: Option<Binary>,
}
fn encode_bytes(data: Vec<u8>) -> Vec<u8> {
let mut encoded_data = Vec::new();
let field_tag: u8 = (1 << 3) | 2;
encoded_data.push(field_tag);
let mut len = data.len();
while len >= 0x80 {
encoded_data.push((len as u8) | 0x80);
len >>= 7;
}
encoded_data.push(len as u8);
encoded_data.extend(data);
encoded_data
}
pub fn wrap_as_contract_reply(mut bin_vec: Vec<u8>, reply_id: u64) -> Reply {
bin_vec = encode_bytes(bin_vec);
let as_binary = Binary::from(bin_vec);
Reply {
id: reply_id,
result: SubMsgResult::Ok(SubMsgResponse {
events: vec![],
data: Some(as_binary),
}),
}
}
pub fn mock_instantiate_reply_msg(contract_addr: &str, reply_id: u64) -> Reply {
let mut bin_vec = to_json_binary(&contract_addr.to_string()).unwrap().as_slice().to_vec();
bin_vec.remove(0);
bin_vec.pop();
wrap_as_contract_reply(bin_vec, reply_id)
}