cw-orch 0.11.0-alpha.3

Scripting library for deploying and interacting with CosmWasm smart-contracts
Documentation

cw-orchestrator

Cw-orchestrator is a Rust library for interacting with CosmWasm smart contracts. It provides a type-safe interface to CosmWasm contracts and allows you to easily interact with them. It does this by providing a set of macros that generate type-safe interfaces to your contracts. You can then combine your contract interfaces into a single object that can be shared with others to ease integration efforts and encourage collaboration.

The documentation here gives you a brief overview of the functionality that cw-orchestrator provides. We provide more documentation at orchestrator.abstract.money.

How it works

Interacting with a CosmWasm contract is done by calling the contract's endpoints using the appropriate message for that endpoint (ExecuteMsg,InstantiateMsg, QueryMsg, MigrateMsg, etc.). cw-orchestrator generates typed interfaces for your contracts, allowing them to be type-checked at compile time. This generic interface then allows you to write environment-generic code, meaning that you can re-use the code that you write to deploy your application to cw-multi-test when deploying to test/mainnet.

Maintained Interfaces

We maintain a small set of interfaces ourselves that we use in our own projects. These interfaces are maintained by the Abstract team and are a good reference for how to use the library.

Codebase Latest Version
cw-plus
wyndex
AbstractSDK

Creating an Interface

In order to generate a typed interface to your contract you can either pass the contract's message types into the contract macro or you can add the interface macro to your endpoint function exports!

contract macro

Provide your messages to a new struct that's named after your contract.

use cw_orch::contract;
// Provide the messages in the order Init, Exec, Query, Migrate.
#[contract(InstantiateMsg, ExecuteMsg, QueryMsg, MigrateMsg)]
pub struct Cw20;

Then implement a constructor for it:

use cw_orch::{CwEnv,Contract};
impl<Chain: CwEnv> Cw20 <Chain>{
    pub fn new(name: &str, chain: Chain) -> Self {
        Self(Contract::new(name, chain))
    }
}

interface macro

You create a contract interface by adding the interface macro to your contract endpoints. The name of the generated interface will be the crate name in PascalCase.

#[cw_orch::interface]
fn instantiate(...)

#[cw_orch::interface]
fn execute(...)

You now have a contract interface that you can use to interact with your contract.

Usage

You can then use this interface to interact with the contract:

// .. setup environment 

let cw20_base: Cw20<Chain> = Cw20::new("my_token", chain);
// instantiate a CW20 token instance
let cw20_init_msg = cw20_base::msg::InstantiateMsg {
    decimals: 6,
    name: "Test Token".to_string(),
    initial_balances: vec![Cw20Coin {
        address: sender.to_string(),
        amount: 1000000u128.into(),
    }],
    marketing: None,
    mint: None,
    symbol: "TEST".to_string(),
};
cw20_base.instantiate(&cw20_init_msg, None, None)?;
// Query balance
// Notice that this query is generated by a macro and not defined in the object itself!
// There is also no need to provide a return type of the query.
let balance = cw20_base.balance(sender.to_string())?;

Features

cw-orchestrator provides two additional macros that can be used to improve the scripting experience.

ExecuteFns

The ExecuteFns macro can be added to the ExecuteMsg definition of your contract. It will generate a trait that allows you to call the variants of the message directly without the need to construct the struct yourself.

The macros should only be added to the structs when the "interface" trait is enable. This is ensured by the interface feature in the following example

Example:

#[cfg_attr(feature="interface", derive(cw_orch::ExecuteFns))]
pub enum ExecuteMsg{
    /// 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> },
    /// the `payable` attribute will add a `coins` argument to the generated function
    #[cfg_attr(feature="interface", derive(cw_orch::payable))]
    Deposit {}
}

#[contract(Empty,ExecuteMsg,Empty,Empty)]
struct Cw1

impl<Chain: CwEnv> Cw1<Chain> {
    pub fn test_macro(&self) {
        self.freeze().unwrap();
        self.update_admins(vec![]).unwrap();
        self.deposit(&[Coin::new(13,"juno")]).unwrap();
    }
}

We recommend shielding the ExecuteMsgFns macro behind a feature flag to avoid pulling in cw-orchestrator by default. The resulting derive would look like this: #[cfg_attr(feature = "interface", derive(cw_orch::ExecuteFns))]

For nested execute messages you can add an impl_into attribute. This expects the message to implement the Into trait for the provided type. This can be used with generic messages.

QueryFns

The QueryFns derive macro works in the same way as the ExecuteFns macro but it also uses the #[returns(QueryResponse)] attribute from cosmwasm-schema to generate the queries with the correct response types.

Contributing

We'd really appreciate your help! Please read our contributing guidelines to get started.

Documentation

The documentation is generated using mdbook. Edit the files in the docs/src folder and run

cd docs && mdbook serve --open

to view the changes.

Testing

To test the full application you can run the following command:

cargo test --jobs 1 --all-features

References

Enjoy scripting your smart contracts with ease? Build your contracts with ease by using Abstract.

Disclaimer

This software is provided as-is without any guarantees.

Credits

cw-orchestrator is inspired by terra-rust-api and uses cosmos-rust for protocol buffer gRPC communication.