Junø
WebDiscordGithubTwitter
  • Juno
    • Intro
    • Home of CosmWasm
    • Contributors - Core Software
    • Brand Identity
    • Security Disclosures
    • Economic Overview
      • Disclaimer
      • Native Asset (JUNO)
      • Incentive structure
      • Supply API - Data
  • Developer Guides
    • CosmWasm Contracts
      • Compile a Contract
      • Deploy a Contract
      • Guide: How to Upload a Smart Contract on the Juno Chain
      • Use Cw-orchestrator to speed-up your development
      • Query A Contract
      • Send Tokens to a Contract
    • Miscellaneous
      • Conversions
      • Multi Message Transaction
      • Get & Decode Transactions
      • Get Token Prices
      • Get Account Transactions
      • IBC Transfer
      • State Export / Airdrop
    • Juno Modules
      • FeeShare
      • TokenFactory
    • API Endpoints
      • Cosmos
        • Tx
          • V1beta1
            • Simulate
            • Txs
              • Block
        • Params
          • V1beta1
            • Params
        • Bank
          • V1beta1
            • Balances
              • By denom
            • Denoms metadata
            • Params
            • Spendable balances
            • Supply
        • Upgrade
          • V1beta1
            • Applied plan
            • Current plan
            • Module versions
            • Upgraded consensus state
        • Auth
          • V1beta1
            • Accounts
            • Module accounts
            • Params
        • Staking
          • V1beta1
            • Delegations
            • Historical info
            • Params
            • Pool
            • Validators
              • Delegations
                • Unbonding delegation
              • Unbonding delegations
            • Delegators
              • Redelegations
              • Unbonding delegations
              • Validators
        • Evidence
          • V1beta1
            • Evidence
        • Mint
          • V1beta1
            • Annual provisions
            • Inflation
            • Params
        • Feegrant
          • V1beta1
            • Allowance
            • Allowances
            • Issued
        • Gov
          • V1beta1
            • Params
            • Proposals
              • Deposits
              • Tally
              • Votes
        • Distribution
          • V1beta1
            • Community pool
            • Params
            • Delegators
              • Rewards
              • Validators
              • Withdraw address
            • Validators
              • Commission
              • Outstanding rewards
              • Slashes
        • Slashing
          • V1beta1
            • Params
            • Signing infos
        • Authz
          • V1beta1
            • Grants
              • Grantee
              • Granter
        • Base
          • Tendermint
            • V1beta1
              • Blocks
                • Latest
              • Node info
              • Syncing
              • Validatorsets
                • Latest
          • Node
            • V1beta1
              • Config
      • Cosmwasm
        • Wasm
          • V1
            • Code
              • Contracts
            • Contract
              • History
              • Raw
              • Smart
              • State
            • Codes
              • Params
              • Pinned
            • Contracts
              • Creator
      • Juno
        • Feeshare
          • V1
            • Fee shares
            • Params
        • Tokenfactory
          • V1beta1
            • Denoms from creator
            • Params
            • Denoms
              • Authority metadata
      • Ibc
        • Apps
          • Router
            • V1
              • Params
      • API Specification
    • Local Interchain
      • Local Interchain Rust Example
    • Junod Local Dev Setup
    • Integrate Leap wallet
    • SubQuery Indexer
  • Governance
    • Before submitting a proposal
    • Submitting a Proposal (CLI)
      • Formatting Proposal Markdown
  • Command-Line Interface (CLI)
    • Introduction
    • Useful CLI Commands
    • Module Reference
      • bank
      • distribution
      • gov
      • keys
      • params
      • slashing
      • staking
      • status
      • tendermint
      • upgrade
      • wasm
  • Nodes & Validators
    • Junod Installation and setup
    • Setting up Cosmovisor
    • Mainnet Setup and Tooling
    • Joining Mainnet
      • Sync from Snapshot
      • Sync with state-sync
      • Mainnet Upgrades
    • Joining Testnet
    • Relaying
    • Juno Delegations Program
Powered by GitBook
On this page
  • Introduction
  • Summary
  • Single Contract Integration
  • Adding cw-orch to your Cargo.toml file
  • Creating an Interface
  • Interaction helpers
  • Using the integration
  • Integration in a workspace
  • Handling dependencies and features
  • Creating an interface crate
  • Integrating single contracts
  • More examples and scripts

Was this helpful?

  1. Developer Guides
  2. CosmWasm Contracts

Use Cw-orchestrator to speed-up your development

Integrate you smart-contract with cw-orch and facilitate testing/development and maintenance of your project.

PreviousGuide: How to Upload a Smart Contract on the Juno ChainNextQuery A Contract

Last updated 1 year ago

Was this helpful?

Introduction

cw-orchestrator is the most advanced scripting, testing, and deployment framework for CosmWasm smart-contracts. It makes it easy to write cross-environment compatible code for , , (alpha), and live networks, significantly reducing code duplication and test-writing time.

Get ready to change the way you interact with contracts and simplify you smart-contracts journey. The following steps will allow you to integrate cw-orch and write clean code such as:

counter.upload()?;
counter.instantiate(&InstantiateMsg { count: 0 }, None, None)?;
counter.increment()?;

let count = counter.get_count()?;
assert_eq!(count.count, 1);

In this quick-start guide, we will review the necessary steps in order to integrate into a simple contract crate. .

NOTE: Quicker than the quick start

If you're moving quicker than everybody else, we suggest looking at . This will help you catch the additions you need to make to your contract to be able to interact with it using cw-orchestrator.

NOTE: If you want to go more in depth, .

Summary

Single Contract Integration

Throughout this example, we will be using cw-orch to interact with a simple counter contract. All the steps below apply to any smart contract, no matter the complexity.

Adding cw-orch to your Cargo.toml file

To use cw-orchestrator, you need to add cw-orch to your contract's TOML file. Run the command below in your contract's directory:

cargo add --optional cw-orch

Alternatively, you can add it manually in your Cargo.toml file as shown below:

[dependencies]
cw-orch = {version = "0.19.1", optional = true } # Latest version at time of writing

Now that we have added cw-orch as an optional dependency we will want to enable it through a feature-flag. This ensures that the code added by cw-orch is not included in the wasm artifact of the contract.

To do this add an interface feature to the Cargo.toml and enable cw-orch when it is enabled like so:

[features]
interface = ["dep:cw-orch"] # Enables cw-orch when the feature is enabled

NOTE: If you are using rust-analyzer, you can add the following two lines in your settings.json to make sure the features get taken into account when checking the project:

 "rust-analyzer.cargo.features": "all",
 "rust-analyzer.check.features": "all",

Creating an Interface

When using a single contract, we advise creating an interface.rs file inside your contract's directory. You then need to add this module to your lib.rs file. Don't forget to feature-flag the module in order to be able to use cw-orch inside it.

#[cfg(feature = "interface")]
mod interface;

Then, inside that interface.rs file, you can define the interface for your contract:

use cw_orch::{interface, prelude::*};

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

pub const CONTRACT_ID: &str = "counter_contract";

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

impl<Chain: CwEnv> Uploadable for CounterContract<Chain> {
    /// Return the path to the wasm file corresponding to the contract
    fn wasm(&self) -> WasmPath {
        artifacts_dir_from_workspace!()
            .find_wasm_path("counter_contract")
            .unwrap()
    }
    /// Returns a CosmWasm contract wrapper
    fn wrapper(&self) -> Box<dyn MockContract<Empty>> {
        Box::new(
            ContractWrapper::new_with_empty(
                crate::contract::execute,
                crate::contract::instantiate,
                crate::contract::query,
            )
            .with_migrate(crate::contract::migrate),
        )
    }
}

NOTE: It can be useful to re-export this struct to simplify usage (in lib.rs):

#[cfg(feature = "interface")]
pub use crate::interface::CounterContract;

Interaction helpers

cw-orchestrator provides a additional macros that simplify contract calls and queries. The macro implements functions on the interface for each variant of the contract's ExecuteMsg and QueryMsg.

Enabling this functionality is very straightforward. Find your ExecuteMsg and QueryMsg definitions (in msg.rs in our example) and add the ExecuteFns and QueryFns derive macros to them like below:

#[cw_serde]
#[cfg_attr(feature = "interface", 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,
    },
}

#[cw_serde]
#[cfg_attr(feature = "interface", 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 {},
}

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

NOTE: Again, it can be useful to re-export these generated traits to simplify usage (in lib.rs):

#[cfg(feature = "interface")]
pub use crate::msg::{ExecuteMsgFns as CounterExecuteMsgFns, QueryMsgFns as CounterQueryMsgFns};

Using the integration

Now that all the setup is done, you can use your contract in tests, integration-tests or scripts.

Start by importing your crate, with the interface feature enabled. Depending on your use-case this will be in [dependencies] or [dev-dependencies]:

counter-contract = { path = "../counter-contract", features = ["interface"] }

You can now use:

use counter_contract::{
    msg::InstantiateMsg, CounterContract, CounterExecuteMsgFns, CounterQueryMsgFns,
};
use cw_orch::{anyhow, prelude::*, tokio};
use tokio::runtime::Runtime;

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";
pub fn main() -> anyhow::Result<()> {
    std::env::set_var("LOCAL_MNEMONIC", LOCAL_MNEMONIC);
    dotenv::dotenv().ok(); // Used to load the `.env` file if any
    pretty_env_logger::init(); // Used to log contract and chain interactions

    let rt = Runtime::new()?;
    let network = networks::LOCAL_JUNO;
    let chain = DaemonBuilder::default()
        .handle(rt.handle())
        .chain(network)
        .build()?;


    let counter = CounterContract::new(chain);

    counter.upload()?;
    counter.instantiate(&InstantiateMsg { count: 0 }, None, None)?;

    counter.increment()?;

    let count = counter.get_count()?;
    assert_eq!(count.count, 1);

    Ok(())
}

Integration in a workspace

In this paragraph, we will use the cw-plus repository as an example. You can review:

Handling dependencies and features

When using workspaces, you need to do the 2 following actions on all crates that include ExecuteMsg and QueryMsg used in your contracts:

  1. Add cw-orch as an optional dependency

  2. Add an interface feature (ensures cw-orch is not compiled into your wasm contract)

For instance, for the cw20_base contract, you need to execute those 2 steps on the cw20-base contract (where the QueryMsg are defined) as well as on the cw20 package (where the ExecuteMsg are defined).

Creating an interface crate

When using a workspace, we advise you to create a new crate inside your workspace for defining your contract's interfaces. In order to do that, use:

cargo new interface --lib
cargo add cw-orch --package interface 

Add the interface package to your workspace Cargo.toml file

[workspace]
members = ["packages/*", "contracts/*", "interface"]

Inside this interface crate, we advise to integrate all your contracts 1 by 1 in separate files. Here is the structure of the cw-plus integration for reference:

interface (interface collection)
├── Cargo.toml
└── src
    ├── cw1_subkeys.rs
    ├── cw1_whitelist.rs
    ├── cw20_base.rs
    ├── cw20_ics20.rs
    └── ..

When importing your crates to get the messages types, you can use the following command in the interface folder. Don't forget to activate the interface feature to be able to use the cw_orch functionalities.

cargo add cw20-base --path ../contracts/cw20-base/ --features=interface
cargo add cw20 --path ../packages/cw20 --features=interface

Integrating single contracts

More examples and scripts

You can find more example interactions on the counter-contract example directly in the cw-orchestrator repo:

Learn more about the content of the interface creation specifics in the

Find out more about the interaction helpers in the

with cw-orch added

that shows you all integration spots (if you want to go fast)

Refer above to for more details on how to do that.

Now that you workspace is setup, you can using the above section

Some examples .

Some other examples show .

FINAL ADVICE: Learn more and explorer our

cw-orch documentation
cw-orch documentation
The full integration code
The complete diff
showcase interacting with live chains
how to use the library for testing your contracts
full cw-orch documentation !
cw-multi-test
Test Tube
Starship
cw-orch
a before-after review of this example integration
browse the full cw-orch documentation
We review integration of rust-workspaces (multiple contracts) at the end of this page
Introduction
Summary
Single Contract Integration
Adding cw-orch to your Cargo.toml file
Creating an Interface
Interaction helpers
Using the integration
Integration in a workspace
Handling dependencies and features
Creating an interface crate
Integrating single contracts
More examples and scripts
Adding cw-orch to your Cargo.toml file
integrate with single contracts