1 个不稳定版本

0.12.1 2023年6月4日

#12 in #cw

GPL-3.0-only

260KB
5K SLoC

cw-orchestrator

docs.rs Crates.io Codecov

cw-orchestrator是一个用于与CosmWasm智能合约交互的Rust工具。它提供了一个类型安全的接口来访问CosmWasm合约,并允许您轻松地与之交互。它通过提供一组宏来生成对您的合约的类型安全接口来实现这一点。然后,您可以组合您的合约接口到一个单一的对象中,与他人共享以简化集成工作并鼓励协作。

这里的文档为您提供了cw-orchestrator提供功能性的简要概述。我们还在orchestrator.abstract.money提供了更多文档。

工作原理

通过调用合约的端点来与CosmWasm合约交互,使用适用于该端点的适当消息(ExecuteMsgInstantiateMsgQueryMsgMigrateMsg等)。cw-orchestrator为您的合约生成类型接口,允许在编译时进行类型检查。这个通用接口允许您编写环境通用的代码,这意味着您可以将编写用于将应用程序部署到cw-multi-test的代码重用于部署到测试/主网。

维护的接口

我们维护了一小部分我们自己使用的接口,这些接口用于我们的项目。这些接口由Abstract团队维护,是使用库的好参考。

代码库 最新版本
cw-plus GitHub tag (latest SemVer)
wyndex GitHub tag (latest SemVer)
AbstractSDK Crates.io

创建接口

为了生成对您的合约的类型接口,您可以将合约的消息类型传递给contract宏,或者您可以在您的端点函数导出中添加interface宏!

contract

向以您的合约命名的结构体提供您的消息。

use cw_orch::interface;
use cw20_base::msg::{InstantiateMsg, ExecuteMsg, QueryMsg, MigrateMsg};

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

该宏将生成一个接受合约名称和您想要交互的链的new函数。然后,您可以使用此接口与合约交互。

《interface_entry_point》宏

您可以通过将《interface_entry_point》宏添加到您的合约端点来创建一个合约接口。生成的接口名称将是PascalCase格式的crate名称。

use cw_orch::interface_entry_point;

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

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

现在您拥有了一个可以用来与您的合约交互的合约接口。

用法

您可以使用此接口与合约交互

use cw_orch::interface;
use cw_orch::prelude::*;
use cw20::{Cw20Coin, BalanceResponse};
use cw20_base::msg::{InstantiateMsg, ExecuteMsg, QueryMsg, MigrateMsg};

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

// Implement the Uploadable trait so it can be uploaded to the mock. 
impl <Chain: CwEnv> Uploadable for Cw20<Chain> {
    fn wrapper(&self) -> Box<dyn MockContract<Empty>> {
        Box::new(
            ContractWrapper::new_with_empty(
                cw20_base::contract::execute,
                cw20_base::contract::instantiate,
                cw20_base::contract::query,
            )
            .with_migrate(cw20_base::contract::migrate),
        )
    }
}

// ## Environment setup ##

let sender = Addr::unchecked("sender");
// Create a new mock chain (backed by cw-multi-test)
let chain = Mock::new(&sender);

// Create a new Cw20 interface
let cw20_base: Cw20<Mock> = Cw20::new("my_token", chain);

// Upload the contract
cw20_base.upload().unwrap();

// Instantiate a CW20 token
let cw20_init_msg = InstantiateMsg {
    decimals: 6,
    name: "Test Token".to_string(),
    initial_balances: vec![Cw20Coin {
        address: sender.to_string(),
        amount: 10u128.into(),
    }],
    marketing: None,
    mint: None,
    symbol: "TEST".to_string(),
};
cw20_base.instantiate(&cw20_init_msg, None, None).unwrap();

// Query the balance
let balance: BalanceResponse = cw20_base.query(&QueryMsg::Balance { address: sender.to_string() }).unwrap();

assert_eq!(balance.balance.u128(), 10u128);

特性

cw-orchestrator提供了两个额外的宏,可以提高脚本体验。

ExecuteFns

您可以将《ExecuteFns》宏添加到合约的《ExecuteMsg》定义中。这将生成一个特质,允许您直接调用消息的变体,而无需自己构造结构体。

仅当启用了"interface"特质时,才应将宏添加到结构体中。以下示例中的《interface》特质确保了这一点

示例

use cw_orch::prelude::*;

#[cosmwasm_schema::cw_serde]
#[derive(cw_orch::ExecuteFns)]
pub enum ExecuteMsg {
    Freeze {},
    UpdateAdmins { admins: Vec<String> },
    /// the `payable` attribute will add a `coins` argument to the generated function
    #[payable]
    Deposit {}
}

// Define the interface, which is generic over the CosmWasm environment (Chain)
#[cw_orch::interface(Empty,ExecuteMsg,Empty,Empty)]
struct Cw1<Chain>;

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

我们建议在《ExecuteMsgFns》宏后面添加功能标志,以避免默认引入《cw-orchestrator》。

QueryFns

《QueryFns》派生宏的工作方式与《ExecuteFns》宏相同,但它还使用来自《cosmwasm-schema》的《# [returns(QueryResponse)]》属性来生成具有正确响应类型的查询。

impl_into 属性

对于嵌套消息(执行和查询),您可以添加一个《impl_into》属性。这期望枚举实现了提供的类型的《Into》特质。当处理泛型消息时,这非常有用。

use cw_orch::interface;
use cw_orch::prelude::*;

// An execute message that is generic.
#[cosmwasm_schema::cw_serde]
pub enum GenericExecuteMsg<T> {
    Generic(T),
}

// Now the following is possible:
type ExecuteMsg = GenericExecuteMsg<Foo>;

#[cosmwasm_schema::cw_serde]
#[derive(cw_orch::ExecuteFns)]
#[impl_into(ExecuteMsg)]
pub enum Foo {
    Bar { a: String },
}

impl From<Foo> for ExecuteMsg {
    fn from(msg: Foo) -> Self {
        ExecuteMsg::Generic(msg)
    }
}

#[interface(Empty, ExecuteMsg, Empty, Empty)]
struct Example<Chain>;

impl<Chain: CwEnv> Example<Chain> {
    pub fn test_macro(&self) {
        // function `bar` is available because of the `impl_into` attribute!
        self.bar("hello".to_string()).unwrap();
    }
}

贡献

我们非常欢迎您的帮助!请阅读我们的贡献指南以开始。

文档

使用mdbook生成文档。编辑《docs/src》文件夹中的文件,并运行

just serve-docs

以查看更改。

发布文档 开发文档

测试

要测试完整的应用程序,您可以运行以下命令

cargo test --jobs 1 --all-features

参考

喜欢轻松编写智能合约脚本?通过使用Abstract轻松构建您的合约。

免责声明

此软件按原样提供,不提供任何保证。

鸣谢

cw-orchestrator受到terra-rust-api的启发,并使用cosmos-rust进行协议缓冲区 gRPC通信。

依赖项

~9–28MB
~468K SLoC