Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fun side project] Add on-chain cw-orch #504

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ members = [
"packages/macros/*",
"packages/interchain/*",
"packages/integrations/*",
"packages/cw-orch-on-chain",
]
exclude = [
"test_contracts/compatibility-test", # TODO: add new after cw-orch-core 2.0.0 as it's breaking, it shouldn't be compatible
Expand Down Expand Up @@ -44,6 +45,7 @@ neutron-test-tube = { version = "4.2.3" }
anyhow = "1.0"
serde = { version = "1.0.208", default-features = false, features = ["derive"] }
tokio = { version = "1.39", features = ["full"] }
async-std = "1.13.0"

cw-orch = { path = "./cw-orch", version = "0.27.0" }
cw-orch-daemon = { path = "./cw-orch-daemon", version = "0.28.0" }
Expand Down
7 changes: 4 additions & 3 deletions artifacts/checksums.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
cc02664dc02c571fd0e4bb02061b737571a510a6a4ac01f8cc783545bec6fff4 counter_contract.wasm
9f8d3bc6ea5c58c31dbed31588df591447ffd2410b3c4d1587e2adb8a29c0931 counter_contract.wasm
9b3dbccb37e232d6e21ced348008707ed913762dba8c51e7a75687af05022a73 counter_cousin_contract.wasm
a266c5ab0ffdf78b3aee593d07d3c822fa3c2745bc7bc8210e49860439d65a73 cw_orch_compatibility_test.wasm
0dc79fb31e732310554a07881cfe8a193c068d2f93539356817e5aaf551650dd mock_contract.wasm
08d65b781d7357a6777c836229d971b6c87a5fdfc7cba9806ed508f917859f08 mock_contract_u64.wasm
322d2535c672abb0338f23689d703a468d6bdebe9ce975a842e9a8d5e95bf770 mock_contract.wasm
cdc883c20f370bd68494912e28053f0bef666e8f96c889ba8412b50f4a2cd1ed mock_contract_u64.wasm
Binary file modified artifacts/counter_contract.wasm
Binary file not shown.
Binary file added artifacts/counter_cousin_contract.wasm
Binary file not shown.
Binary file modified artifacts/mock_contract.wasm
Binary file not shown.
Binary file modified artifacts/mock_contract_u64.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions contracts-ws/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ cosmwasm-std = "2.0.0"
cw20 = { version = "2.0.0" }
cw20-base = { version = "2.0.0" }
cw-storage-plus = { version = "2.0.0" }
async-std = "1.13.0"

serde = { version = "1.0.103", default-features = false, features = ["derive"] }
anyhow = "1.0"
Expand Down
3 changes: 2 additions & 1 deletion contracts-ws/contracts/counter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ serde = { workspace = true }
serde_json = "1.0.125"
cw-orch = { workspace = true, features = ["daemon"] }
# Unused, only there to check for wasm compatibility
cw-orch-interchain = { workspace = true, features = ["daemon"] }
# cw-orch-interchain = { workspace = true, features = ["daemon"] }

[[example]]
name = "deploy"
Expand All @@ -35,3 +35,4 @@ dotenv = { version = "0.15.0" }
pretty_env_logger = { version = "0.5.0" }
cw-orch = { workspace = true, features = ["daemon"] }
anyhow = { workspace = true }
async-std = { workspace = true }
4 changes: 2 additions & 2 deletions contracts-ws/contracts/counter/examples/async.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// ANCHOR: full_async_example
use counter_contract::AsyncCounterQueryMsgFns;
use counter_contract::CounterContract;
use cw_orch::{anyhow, prelude::*, tokio};
use cw_orch::{anyhow, prelude::*};

// From https://github.com/CosmosContracts/juno/blob/32568dba828ff7783aea8cb5bb4b8b5832888255/docker/test-user.env#L2
const LOCAL_MNEMONIC: &str = "clip hire initial neck maid actor venue client foam budget lock catalog sweet steak waste crater broccoli pipe steak sister coyote moment obvious choose";

#[tokio::main]
#[async_std::main]
pub async fn main() -> anyhow::Result<()> {
std::env::set_var("LOCAL_MNEMONIC", LOCAL_MNEMONIC);
dotenv::dotenv().ok(); // Used to load the `.env` file if any
Expand Down
2 changes: 1 addition & 1 deletion contracts-ws/contracts/counter/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ fn count() -> anyhow::Result<()> {
assert_eq!(count.count, 0);

// Check negative case
let exec_res: Result<cw_orch::mock::cw_multi_test::AppResponse, CwOrchError> =
let exec_res: Result<cw_orch::core::AppResponse, CwOrchError> =
contract.call_as(&user).reset(0);

let expected_err = ContractError::Unauthorized {};
Expand Down
37 changes: 37 additions & 0 deletions contracts-ws/contracts/counter_cousin/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[package]
name = "counter-cousin-contract"
version = "0.11.0"
description = "counter constract"
keywords = ["cosmwasm", "blockchain"]
edition = { workspace = true }
exclude = [".env"]

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

[features]
default = ["export"]
export = []

[dependencies]
cosmwasm-std = { workspace = true }
cw-storage-plus = { workspace = true }
cw2 = "2.0"
cosmwasm-schema = "2.1"
schemars = "0.8.21"
thiserror = { version = "1.0.63" }
serde = { workspace = true }
serde_json = "1.0.125"
cw-orch = { workspace = true, features = ["daemon"] }
# Unused, only there to check for wasm compatibility
# cw-orch-interchain = { workspace = true, features = ["daemon"] }

cw-orch-on-chain = { path = "../../../packages/cw-orch-on-chain" }

[dev-dependencies]
# Deps for deployment
dotenv = { version = "0.15.0" }
pretty_env_logger = { version = "0.5.0" }
cw-orch = { workspace = true, features = ["daemon"] }
anyhow = { workspace = true }
cw-orch-osmosis-test-tube = { path = "../../../packages/cw-orch-osmosis-test-tube" }
3 changes: 3 additions & 0 deletions contracts-ws/contracts/counter_cousin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Refer to [https://orchestrator.abstract.money/](https://orchestrator.abstract.money/) for more details on how to use this crate

Check out the [examples](./examples) and [tests](./tests) in this crate to understand how to use it by example.
59 changes: 59 additions & 0 deletions contracts-ws/contracts/counter_cousin/src/contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use cosmwasm_std::{
entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult,
};
use cw2::set_contract_version;

use crate::{error::*, execute, msg::*, query, state::*};

// version info for migration info
pub const CONTRACT_NAME: &str = "crates.io:counter";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

// ANCHOR: interface_entry
// ANCHOR: entry_point_line
#[cfg_attr(feature = "export", entry_point)]
// ANCHOR_END: entry_point_line
pub fn instantiate(
deps: DepsMut,
_env: Env,
info: MessageInfo,
msg: InstantiateMsg,
) -> Result<Response, ContractError> {
let state = State {
count: msg.count,
owner: info.sender.clone(),
};
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
STATE.save(deps.storage, &state)?;

Ok(Response::new()
.add_attribute("method", "instantiate")
.add_attribute("owner", info.sender)
.add_attribute("count", msg.count.to_string()))
}

#[cfg_attr(feature = "export", entry_point)]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::Increment {} => execute::increment(deps),
ExecuteMsg::Reset { count } => execute::reset(deps, info, count),
ExecuteMsg::IncrementCousin {} => execute::increment_cousin(deps, &env),
ExecuteMsg::SetCousin { cousin } => execute::set_cousin(deps, env, info, cousin),
}
}

#[cfg_attr(feature = "export", entry_point)]
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::GetCount {} => to_json_binary(&query::count(deps)?),
QueryMsg::GetCousinCount {} => to_json_binary(&query::cousin_count(deps, env)?),
QueryMsg::GetRawCousinCount {} => to_json_binary(&query::raw_cousin_count(deps, &env)?),
}
}

// ANCHOR_END: interface_entry
16 changes: 16 additions & 0 deletions contracts-ws/contracts/counter_cousin/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use cosmwasm_std::StdError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ContractError {
#[error("{0}")]
Std(#[from] StdError),

#[error("{0}")]
OrchError(#[from] cw_orch::prelude::CwOrchError),

#[error("Unauthorized")]
Unauthorized {},
// Add any other custom errors you like here.
// Look at https://docs.rs/thiserror/1.0.21/thiserror/ for details.
}
43 changes: 43 additions & 0 deletions contracts-ws/contracts/counter_cousin/src/execute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use crate::msg::ExecuteMsgFns;
use crate::CounterContract;
use crate::{error::*, state::*};
use cosmwasm_std::{DepsMut, Env, MessageInfo, Response};

pub fn increment(deps: DepsMut) -> Result<Response, ContractError> {
STATE.update(deps.storage, |mut state| -> Result<_, ContractError> {
state.count += 1;
Ok(state)
})?;

Ok(Response::new().add_attribute("action", "increment"))
}

pub fn increment_cousin(deps: DepsMut, env: &Env) -> Result<Response, ContractError> {
let increment_msg = CounterContract::load(deps, env, "cousin").increment()?;

Ok(Response::new().add_message(increment_msg))
}

pub fn reset(deps: DepsMut, info: MessageInfo, count: i32) -> Result<Response, ContractError> {
STATE.update(deps.storage, |mut state| -> Result<_, ContractError> {
if info.sender != state.owner {
return Err(ContractError::Unauthorized {});
}
state.count = count;
Ok(state)
})?;
Ok(Response::new().add_attribute("action", "reset"))
}

pub fn set_cousin(
deps: DepsMut,
env: Env,
info: MessageInfo,
cousin: String,
) -> Result<Response, ContractError> {
assert_owner(deps.as_ref(), &info)?;

CounterContract::load(deps, &env, "cousin").set_raw_address(&cousin)?;

Ok(Response::new().add_attribute("action", "set_cousin"))
}
72 changes: 72 additions & 0 deletions contracts-ws/contracts/counter_cousin/src/interface.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// ANCHOR: custom_interface
use cw_orch::{interface, prelude::*};

use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
use cw_orch_on_chain::core::OnChain;

use cosmwasm_std::{Deps, Env, StdResult};

#[interface(InstantiateMsg, ExecuteMsg, QueryMsg, MigrateMsg)]
pub struct CounterContract;

impl<Chain: CwEnv> Uploadable for CounterContract<Chain> {
/// Return the path to the wasm file corresponding to the contract
fn wasm(_chain: &ChainInfoOwned) -> WasmPath {
artifacts_dir_from_workspace!()
.find_wasm_path("counter_cousin_contract")
.unwrap()
}
/// Returns a CosmWasm contract wrapper
fn wrapper() -> Box<dyn MockContract<Empty>> {
Box::new(ContractWrapper::new_with_empty(
crate::contract::execute,
crate::contract::instantiate,
crate::contract::query,
))
}
}
// ANCHOR_END: custom_interface
use cosmwasm_std::DepsMut;
use cw_orch_on_chain::core::OnChainDeps;

// All of those could be generated by the interface macro
impl<'a> CounterContract<OnChain<'a>> {
pub fn load(
deps: impl Into<OnChainDeps<'a>>,
env: &Env,
contract_id: &str,
) -> CounterContract<OnChain<'a>> {
let chain = OnChain::new(deps, env);
CounterContract::new(contract_id, chain)
}

pub fn save(
deps: DepsMut<'a>,
env: &Env,
contract_id: &str,
address: Addr,
) -> CounterContract<OnChain<'a>> {
let chain = OnChain::new(deps, env);
let contract = CounterContract::new(contract_id, chain);
contract.set_address(&address);
contract
}

pub fn with_address(
deps: Deps<'a>,
env: &Env,
contract_id: &str,
address: Addr,
) -> CounterContract<OnChain<'a>> {
let chain = OnChain::new(deps, env);
let contract = CounterContract::new(contract_id, chain);
contract.set_address(&address);
contract
}

pub fn set_raw_address(&self, address: &str) -> StdResult<()> {
let address = self.environment().deps.api().addr_validate(address)?;
self.set_address(&address);
Ok(())
}
}
11 changes: 11 additions & 0 deletions contracts-ws/contracts/counter_cousin/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pub mod contract;
mod error;
pub(crate) mod execute;
pub mod interface;
pub mod msg;
pub(crate) mod query;
pub mod state;

pub use error::ContractError;
pub use interface::CounterContract;
pub use msg::{ExecuteMsgFns as CounterExecuteMsgFns, QueryMsgFns as CounterQueryMsgFns};
66 changes: 66 additions & 0 deletions contracts-ws/contracts/counter_cousin/src/msg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#![warn(missing_docs)]
//! # Counter contract

use cosmwasm_schema::{cw_serde, QueryResponses};

#[cw_serde]
/// Instantiate method for counter
pub struct InstantiateMsg {
/// Initial count
pub count: i32,
}

// ANCHOR: exec_msg
#[cw_serde]
#[derive(cw_orch::ExecuteFns)] // Function generation
/// Execute methods for counter
pub enum ExecuteMsg {
/// Increment count by one
Increment {},
/// Reset count
Reset {
/// Count value after reset
count: i32,
},
/// Increment cousin count
IncrementCousin {},
/// Sets the cousin contract, that this contract can query
SetCousin {
/// Address of the cousin contract of this counter
cousin: String,
},
}
// ANCHOR_END: exec_msg

// ANCHOR: query_msg
#[cw_serde]
#[derive(cw_orch::QueryFns)] // Function generation
#[derive(QueryResponses)]
/// Query methods for counter
pub enum QueryMsg {
/// GetCount returns the current count as a json-encoded number
#[returns(GetCountResponse)]
GetCount {},
/// GetCount returns the current count as a json-encoded number
#[returns(GetCountResponse)]
GetCousinCount {},
/// GetCount returns the current count as a json-encoded number
#[returns(GetCountResponse)]
GetRawCousinCount {},
}

// Custom response for the query
#[cw_serde]
/// Response from get_count query
pub struct GetCountResponse {
/// Current count in the state
pub count: i32,
}
// ANCHOR_END: query_msg

#[cw_serde]
/// Migrate message for count contract
pub struct MigrateMsg {
/// Your favorite type of tea
pub t: String,
}
Loading
Loading