1 个不稳定版本
0.12.1 | 2023年6月4日 |
---|
#12 in #cw
260KB
5K SLoC
cw-orchestrator是一个用于与CosmWasm智能合约交互的Rust工具。它提供了一个类型安全的接口来访问CosmWasm合约,并允许您轻松地与之交互。它通过提供一组宏来生成对您的合约的类型安全接口来实现这一点。然后,您可以组合您的合约接口到一个单一的对象中,与他人共享以简化集成工作并鼓励协作。
这里的文档为您提供了cw-orchestrator提供功能性的简要概述。我们还在orchestrator.abstract.money提供了更多文档。
工作原理
通过调用合约的端点来与CosmWasm合约交互,使用适用于该端点的适当消息(ExecuteMsg
、InstantiateMsg
、QueryMsg
、MigrateMsg
等)。cw-orchestrator为您的合约生成类型接口,允许在编译时进行类型检查。这个通用接口允许您编写环境通用的代码,这意味着您可以将编写用于将应用程序部署到cw-multi-test
的代码重用于部署到测试/主网。
维护的接口
我们维护了一小部分我们自己使用的接口,这些接口用于我们的项目。这些接口由Abstract团队维护,是使用库的好参考。
代码库 | 最新版本 |
---|---|
cw-plus | |
wyndex | |
AbstractSDK |
创建接口
为了生成对您的合约的类型接口,您可以将合约的消息类型传递给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