Skip to content

Commit

Permalink
initial contract startgate example
Browse files Browse the repository at this point in the history
  • Loading branch information
jbernal87 committed Apr 24, 2024
1 parent 944c0f7 commit 9d50d68
Show file tree
Hide file tree
Showing 13 changed files with 1,363 additions and 0 deletions.
55 changes: 55 additions & 0 deletions contracts/injective-cosmwasm-stargate-example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[package]
authors = [ "Markus Waas <[email protected]>" ]
edition = "2018"
name = "injective-cosmwasm-stargate-example"
version = "0.0.1"

exclude = [
# Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication.
"contract.wasm",
"hash.txt",
]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = [ "cdylib", "rlib" ]

[features]
# for more explicit tests, cargo test --features=backtraces
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 \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/workspace-optimizer-arm64:0.12.11
"""

[dependencies]
cosmwasm-std = { version = "1.5.0", features = [ "abort", "cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4", "iterator", "stargate" ] }
cw-storage-plus = { version = "1.2.0" }
cw2 = { version = "0.16.0" }
injective-cosmwasm = { path = "../../packages/injective-cosmwasm" }
injective-math = { path = "../../packages/injective-math" }
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 = { version = "3.3.0" }
prost = { version = "0.12.3" }
injective-std = { path = "../../packages/injective-std" }
cosmos-sdk-proto = { version = "0.20.0", default-features = false }
cosmwasm-schema = { version = "1.5.0" }
base64 = "0.21.5"
serde_json = "1.0.111"



[dev-dependencies]
injective-test-tube = { path = "/home/jose/RustroverProjects/test-tube/packages/injective-test-tube" }
injective-std = { path = "../../packages/injective-std" }
injective-testing = { version = "0.1.6" }
46 changes: 46 additions & 0 deletions contracts/injective-cosmwasm-stargate-example/src/contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crate::{
error::ContractError,
msg::{ExecuteMsg, InstantiateMsg, QueryMsg},
query::{
handle_query_stargate,
},
};
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};

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)]
pub fn instantiate(deps: DepsMut, _env: Env, _info: MessageInfo, _msg: InstantiateMsg) -> Result<Response, ContractError> {
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
Ok(Response::default())
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut<InjectiveQueryWrapper>,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response<InjectiveMsgWrapper>, ContractError> {
match msg {
ExecuteMsg::TestDepositMsg { subaccount_id, amount } => {
Ok(Response::new().add_message(create_deposit_msg(env.contract.address, subaccount_id, amount)))
}
}
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps<InjectiveQueryWrapper>, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
let querier = InjectiveQuerier::new(&deps.querier);
match msg {
QueryMsg::QueryStargate { path, query_request } => handle_query_stargate(&deps.querier, path, query_request),
}
}


14 changes: 14 additions & 0 deletions contracts/injective-cosmwasm-stargate-example/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use cosmwasm_std::StdError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ContractError {
#[error("{0}")]
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),
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

13 changes: 13 additions & 0 deletions contracts/injective-cosmwasm-stargate-example/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pub mod contract;
mod error;
mod handle;
pub mod msg;
mod order_management;
mod query;
mod state;
#[cfg(test)]
mod testing;
mod types;
#[cfg(test)]
pub mod utils;
pub use crate::error::ContractError;
34 changes: 34 additions & 0 deletions contracts/injective-cosmwasm-stargate-example/src/msg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use cosmwasm_std::Coin;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use injective_cosmwasm::{CancellationStrategy, MarketId, OracleInfo, OracleType, OrderSide, SubaccountId};

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 {}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
TestDepositMsg {
subaccount_id: SubaccountId,
amount: Coin,
},
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
QueryStargate {
path: String,
query_request: String,
},
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct QueryStargateResponse {
pub value: String,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use crate::types;
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<u8>) -> StdResult<CosmosMsg<InjectiveMsgWrapper>> {
Ok(CosmosMsg::Stargate {
type_url: type_url.to_string(),
value: value.into(),
})
}

pub fn create_spot_limit_order(
price: FPDecimal,
quantity: FPDecimal,
order_type: OrderType,
sender: &str,
subaccount_id: &str,
market: &SpotMarket,
) -> types::MsgCreateSpotLimitOrder {
types::MsgCreateSpotLimitOrder {
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(),
}),
}
}

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<T: Message>(order_msg: &T) -> Result<Vec<u8>, prost::EncodeError> {
let mut buffer = Vec::new();
order_msg.encode(&mut buffer)?; // Encode the message using prost
Ok(buffer)
}
31 changes: 31 additions & 0 deletions contracts/injective-cosmwasm-stargate-example/src/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use cosmwasm_std::{to_json_binary, Binary, to_json_vec, ContractResult, StdError, StdResult, SystemResult, QuerierWrapper};
use injective_cosmwasm::{InjectiveQueryWrapper};
use crate::msg::QueryStargateResponse;
use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
use base64::Engine as _;

pub fn handle_query_stargate(querier: &QuerierWrapper<InjectiveQueryWrapper>, path: String, query_request: String) -> StdResult<Binary> {

let data = Binary::from_base64(&query_request)?;
let request = &cosmwasm_std::QueryRequest::<cosmwasm_std::Empty>::Stargate { path, data };

let raw = to_json_vec(request).map_err(|serialize_err| {
StdError::generic_err(format!("Serializing QueryRequest: {}", serialize_err))
})?;

let value = match querier.raw_query (&raw) {
SystemResult::Err(system_err) => Err(StdError::generic_err(format!(
"Querier system error: {}",
system_err
))),
SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(format!(
"Querier contract error: {}",
contract_err
))),
SystemResult::Ok(ContractResult::Ok(value)) => Ok(value),
}?;


to_json_binary(&QueryStargateResponse { value: String::from(decoded_value)? })
}

11 changes: 11 additions & 0 deletions contracts/injective-cosmwasm-stargate-example/src/state.rs
Original file line number Diff line number Diff line change
@@ -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<Vec<CacheOrderInfo>> = Item::new("order_call_cache");

#[cw_serde]
pub struct CacheOrderInfo {
pub subaccount: SubaccountId,
pub market_id: MarketId,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod test_bank;
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use cosmwasm_std::{Addr, from_json, Coin};
use injective_test_tube::{Account, Module, Wasm};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use injective_cosmwasm::{checked_address_to_subaccount_id};

use crate::{
msg::QueryMsg,
utils::{
ExchangeType, Setup,
},
};
use crate::msg::QueryStargateResponse;
use serde_json::{Value, Map};
use crate::utils::{BASE_DECIMALS, BASE_DENOM, str_coin};

#[test]
#[cfg_attr(not(feature = "integration"), ignore)]
fn test_msg_deposit() {
let env = Setup::new(ExchangeType::None);

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 query_msg = QueryMsg::QueryStargate {
path: "/cosmos.auth.v1beta1.Query/Params".to_string(),
query_request: "".to_string(),
};

let contract_response: QueryStargateResponse = wasm.query(&env.contract_address, &query_msg).unwrap();
let contract_response = contract_response.value;
let response: ParamResponse<AuthParams> = serde_json::from_str(&contract_response).unwrap();
assert_eq!(response.params.max_memo_characters, "256");
// let response: Value = serde_json::from_str(&contract_response).unwrap();
// let response = response.as_object().unwrap();
// println!("{:?}", response);
// assert_eq!(response.get("params").unwrap().as_object().unwrap().get("max_memo_characters").unwrap().as_str().unwrap(), "256");
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct ParamResponse<T> {
pub params: T,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct AuthParams {
pub max_memo_characters: String,
pub sig_verify_cost_ed25519: String,
}


#[test]
#[cfg_attr(not(feature = "integration"), ignore)]
fn test_exchange_param() {
let env = Setup::new(ExchangeType::None);

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 query_msg = QueryMsg::QueryStargate {
path: "/injective.exchange.v1beta1.Query/QueryExchangeParams".to_string(),
query_request: "".to_string(),
};

let contract_response: QueryStargateResponse = wasm.query(&env.contract_address, &query_msg).unwrap();
let contract_response = contract_response.value;
println!("{:?}", contract_response);
let response: ParamResponse<ExchangeParams> = from_json(&contract_response).unwrap();
println!("{:?}", response);
let listing_fee_coin = str_coin("1000", BASE_DENOM, BASE_DECIMALS);
assert_eq!(response.params.spot_market_instant_listing_fee, listing_fee_coin);
assert_eq!(1,2)
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
pub struct ExchangeParams {
pub spot_market_instant_listing_fee: Coin,
}
Loading

0 comments on commit 9d50d68

Please sign in to comment.