Skip to content
Merged
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ gen_cov_test

**/logs/

docs/book
docs/book

packages/integrations/**/artifacts
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Add a method on `TxHandler` to select instantiation permissions on Wasm upload
- Adds an `upload_wasm` function to CosmosSender to upload wasm code associated to no Contract structure
- Update syn to 2.0
- Added cw-plus orchestrator interface to the repo. Pacing the way for more integrations inside this repository in the future

### Breaking

Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ members = [
"test_contracts/*",
"packages/macros/*",
"packages/interchain/*",
"packages/integrations/*",
]
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
1 change: 1 addition & 0 deletions before_publish.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cargo run --example download-wasms -p cw-plus-orch
44 changes: 44 additions & 0 deletions packages/integrations/cw-plus/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
[package]
name = "cw-plus-orch"
version = "0.25.0" # Version of cw-orch that's used
edition = "2021"
description = "cw-orch interfaces for cw-plus base contracts"
license = "Apache-2.0"
repository = "https://github.com/AbstractSDK/cw-orchestrator"
homepage = "https://abstract.money"
documentation = "https://orchestrator.abstract.money"

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

[dependencies]
cosmwasm-std = { workspace = true }
cw-utils = { workspace = true }
cosmwasm-schema = { version = "2.0.0" }


cw-controllers = { version = "2.0.0" }
cw1 = { version = "2.0.0" }
cw1-subkeys = { version = "2.0.0", features = ["library"] }
cw1-whitelist = { version = "2.0.0", features = ["library"] }
cw3 = { version = "2.0.0" }
cw3-fixed-multisig = { version = "2.0.0", features = ["library"] }
cw3-flex-multisig = { version = "2.0.0", features = ["library"] }
cw4 = { version = "2.0.0" }
cw4-group = { version = "2.0.0", features = ["library"] }
cw4-stake = { version = "2.0.0", features = ["library"] }
cw20 = { version = "2.0.0" }
cw20-base = { version = "2.0.0", features = ["library"] }
cw20-ics20 = { version = "2.0.0", features = ["library"] }

cw-orch-from-interface-derive = { version = "0.1.0", path = "../../macros/from-interface-derive" }

cw-orch = { workspace = true }

[dev-dependencies]
cw-orch-interchain = { workspace = true }
cw-orch = { workspace = true, features = ["daemon"] }
dotenv = "0.15.0"
octocrab = "0.39.0"
pretty_env_logger = "0.5.0"
reqwest = "0.12.7"
tokio.workspace = true
50 changes: 50 additions & 0 deletions packages/integrations/cw-plus/examples/download_wasms.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use cw_orch::anyhow;
use std::{io::Cursor, path::PathBuf, str::FromStr};

pub const CW_PLUS_REPO_OWNER: &str = "CosmWasm";
pub const CW_PLUS_REPO_NAME: &str = "cw-plus";
pub const CW_PLUS_RELEASE_TAG: &str = "v2.0.0";

pub const ALL_CONTRACTS: &[&str] = &[
"cw1_subkeys",
"cw1_whitelist",
"cw3_fixed_multisig",
"cw3_flex_multisig",
"cw4_group",
"cw4_stake",
"cw20_base",
"cw20_ics20",
];

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let crate_dir = env!("CARGO_MANIFEST_DIR");
let artifacts_dir = PathBuf::from_str(crate_dir)?.join("artifacts");

// We create the artifacts directory if non-existent
std::fs::create_dir_all(&artifacts_dir)?;

// We get the release, common for all artifacts
let release = octocrab::instance()
.repos(CW_PLUS_REPO_OWNER, CW_PLUS_REPO_NAME)
.releases()
.get_by_tag(CW_PLUS_RELEASE_TAG)
.await?;

for contract in ALL_CONTRACTS {
let release_file_name = format!("{contract}.wasm");
let file_name = artifacts_dir.join(&release_file_name);

let wasm_asset = release
.assets
.iter()
.find(|asset| asset.name.eq(&release_file_name))
.unwrap();

let response = reqwest::get(wasm_asset.browser_download_url.clone()).await?;
let mut file = std::fs::File::create(file_name)?;
let mut content = Cursor::new(response.bytes().await?);
std::io::copy(&mut content, &mut file)?;
}
Ok(())
}
28 changes: 28 additions & 0 deletions packages/integrations/cw-plus/examples/test_wasm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use cw_orch::daemon::networks::LOCAL_JUNO;
use cw_orch::prelude::*;
use cw_plus_orch::cw1_subkeys::Cw1SubKeys;
use cw_plus_orch::cw1_whitelist::Cw1Whitelist;
use cw_plus_orch::cw20_base::Cw20Base;
use cw_plus_orch::cw20_ics20::Cw20Ics20;
use cw_plus_orch::cw3_fixed_multisig::Cw3FixedMultisig;
use cw_plus_orch::cw3_flex_multisig::Cw3FlexMultisig;
use cw_plus_orch::cw4_group::Cw4Group;
use cw_plus_orch::cw4_stake::Cw4Stake;

fn main() -> cw_orch::anyhow::Result<()> {
dotenv::dotenv()?;
pretty_env_logger::init();

let daemon = Daemon::builder(LOCAL_JUNO).build()?;

Cw1SubKeys::new("cw1_subkeys", daemon.clone()).upload()?;
Cw1Whitelist::new("cw1_whitelist", daemon.clone()).upload()?;
Cw3FixedMultisig::new("cw3_fixed_multisig", daemon.clone()).upload()?;
Cw3FlexMultisig::new("cw3_flex_multisig", daemon.clone()).upload()?;
Cw4Group::new("cw4_group", daemon.clone()).upload()?;
Cw4Stake::new("cw4_stake", daemon.clone()).upload()?;
Cw20Base::new("cw20_base", daemon.clone()).upload()?;
Cw20Ics20::new("cw20_ics20", daemon.clone()).upload()?;

Ok(())
}
122 changes: 122 additions & 0 deletions packages/integrations/cw-plus/src/cw1_subkeys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
use cw_orch::interface;

use cw1_subkeys::contract;
pub use cw1_subkeys::msg::{ExecuteMsg, QueryMsg};
pub use cw1_whitelist::msg::InstantiateMsg;
#[cfg(not(target_arch = "wasm32"))]
pub use interfaces::{AsyncQueryMsgInterfaceFns, ExecuteMsgInterfaceFns, QueryMsgInterfaceFns};

#[interface(InstantiateMsg, ExecuteMsg, QueryMsg, Empty)]
pub struct Cw1SubKeys;

#[cfg(not(target_arch = "wasm32"))]
use cw_orch::prelude::*;

#[cfg(not(target_arch = "wasm32"))]
impl<Chain: CwEnv> Uploadable for Cw1SubKeys<Chain> {
// Return the path to the wasm file
fn wasm(_chain: &ChainInfoOwned) -> WasmPath {
artifacts_dir_from_workspace!()
.find_wasm_path("cw1_subkeys")
.unwrap()
}
// Return a CosmWasm contract wrapper
fn wrapper() -> Box<dyn MockContract<Empty>> {
Box::new(
ContractWrapper::new_with_empty(
contract::execute,
contract::instantiate,
contract::query,
)
.with_migrate(contract::migrate),
)
}
}

#[cfg(not(target_arch = "wasm32"))]
/// Copy messages of the contract to implement cw-orch helpers on Execute([`cw_orch::ExecuteFns`]) and Query([`cw_orch::QueryFns`]) interfaces
mod interfaces {
use super::*;

use cosmwasm_schema::schemars::JsonSchema;

#[derive(cw_orch::ExecuteFns, cw_orch_from_interface_derive::FromInterface)]
enum ExecuteMsgInterface<T = Empty>
where
T: Clone + std::fmt::Debug + PartialEq + JsonSchema,
{
/// Execute requests the contract to re-dispatch all these messages with the
/// contract's address as sender. Every implementation has it's own logic to
/// determine in
// This method is renamed to not conflict with [`CwOrchExecute::execute`]
#[cw_orch(fn_name("execute_requests"))]
Execute {
msgs: Vec<cosmwasm_std::CosmosMsg<T>>,
},
/// Freeze will make a mutable contract immutable, must be called by an admin
Freeze {},
/// UpdateAdmins will change the admin set of the contract, must be called by an existing admin,
/// and only works if the contract is mutable
UpdateAdmins { admins: Vec<String> },

/// Add an allowance to a given subkey (subkey must not be admin)
IncreaseAllowance {
spender: String,
amount: Coin,
expires: Option<cw_utils::Expiration>,
},
/// Decreases an allowance for a given subkey (subkey must not be admin)
DecreaseAllowance {
spender: String,
amount: Coin,
expires: Option<cw_utils::Expiration>,
},

// Setups up permissions for a given subkey.
SetPermissions {
spender: String,
permissions: cw1_subkeys::state::Permissions,
},
}

#[cosmwasm_schema::cw_serde]
#[derive(
cosmwasm_schema::QueryResponses,
cw_orch::QueryFns,
cw_orch_from_interface_derive::FromInterface,
)]
enum QueryMsgInterface<T = Empty>
where
T: Clone + std::fmt::Debug + PartialEq + JsonSchema,
{
/// Shows all admins and whether or not it is mutable
#[returns(cw1_whitelist::msg::AdminListResponse)]
AdminList {},
/// Get the current allowance for the given subkey (how much it can spend)
#[returns(cw1_subkeys::state::Allowance)]
Allowance { spender: String },
/// Get the current permissions for the given subkey (how much it can spend)
#[returns(cw1_subkeys::msg::PermissionsInfo)]
Permissions { spender: String },
/// Checks permissions of the caller on this proxy.
/// If CanExecute returns true then a call to `Execute` with the same message,
/// before any further state changes, should also succeed.
#[returns(cw1::CanExecuteResponse)]
CanExecute {
sender: String,
msg: cosmwasm_std::CosmosMsg<T>,
},
/// Gets all Allowances for this contract
#[returns(cw1_subkeys::msg::AllAllowancesResponse)]
AllAllowances {
start_after: Option<String>,
limit: Option<u32>,
},
/// Gets all Permissions for this contract
#[returns(cw1_subkeys::msg::AllPermissionsResponse)]
AllPermissions {
start_after: Option<String>,
limit: Option<u32>,
},
}
}
81 changes: 81 additions & 0 deletions packages/integrations/cw-plus/src/cw1_whitelist.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use cw_orch::interface;

use cw1_whitelist::contract;
pub use cw1_whitelist::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
#[cfg(not(target_arch = "wasm32"))]
pub use interfaces::{AsyncQueryMsgInterfaceFns, ExecuteMsgInterfaceFns, QueryMsgInterfaceFns};

#[interface(InstantiateMsg, ExecuteMsg, QueryMsg, Empty)]
pub struct Cw1Whitelist;

#[cfg(not(target_arch = "wasm32"))]
use cw_orch::prelude::*;

#[cfg(not(target_arch = "wasm32"))]
impl<Chain: CwEnv> Uploadable for Cw1Whitelist<Chain> {
// Return the path to the wasm file
fn wasm(_chain: &ChainInfoOwned) -> WasmPath {
artifacts_dir_from_workspace!()
.find_wasm_path("cw1_whitelist")
.unwrap()
}
// Return a CosmWasm contract wrapper
fn wrapper() -> Box<dyn MockContract<Empty>> {
Box::new(ContractWrapper::new_with_empty(
contract::execute,
contract::instantiate,
contract::query,
))
}
}

#[cfg(not(target_arch = "wasm32"))]
/// Copy messages of the contract to implement cw-orch helpers on Execute([`cw_orch::ExecuteFns`]) and Query([`cw_orch::QueryFns`]) interfaces
mod interfaces {
use super::*;

use cosmwasm_schema::schemars::JsonSchema;

#[derive(cw_orch::ExecuteFns, cw_orch_from_interface_derive::FromInterface)]
enum ExecuteMsgInterface<T = Empty>
where
T: Clone + std::fmt::Debug + PartialEq + JsonSchema,
{
/// Execute requests the contract to re-dispatch all these messages with the
/// contract's address as sender. Every implementation has it's own logic to
/// determine in
// This method is renamed to not conflict with [`CwOrchExecute::execute`]
#[cw_orch(fn_name("execute_requests"))]
Execute {
msgs: Vec<cosmwasm_std::CosmosMsg<T>>,
},
/// Freeze will make a mutable contract immutable, must be called by an admin
Freeze {},
/// UpdateAdmins will change the admin set of the contract, must be called by an existing admin,
/// and only works if the contract is mutable
UpdateAdmins { admins: Vec<String> },
}

#[cosmwasm_schema::cw_serde]
#[derive(
cosmwasm_schema::QueryResponses,
cw_orch::QueryFns,
cw_orch_from_interface_derive::FromInterface,
)]
enum QueryMsgInterface<T = Empty>
where
T: Clone + std::fmt::Debug + PartialEq + JsonSchema,
{
/// Shows all admins and whether or not it is mutable
#[returns(cw1_whitelist::msg::AdminListResponse)]
AdminList {},
/// Checks permissions of the caller on this proxy.
/// If CanExecute returns true then a call to `Execute` with the same message,
/// before any further state changes, should also succeed.
#[returns(cw1::CanExecuteResponse)]
CanExecute {
sender: String,
msg: cosmwasm_std::CosmosMsg<T>,
},
}
}
Loading