From 69c79e5e9543122a097ea2df528868a5c3dd713d Mon Sep 17 00:00:00 2001 From: Tomasz Kulik Date: Thu, 4 Jul 2024 13:15:59 +0200 Subject: [PATCH] docs: Add `sudo` and `Executor`. Improve URLs --- src/SUMMARY.md | 2 + src/advanced/attributes_forwarding.md | 54 +++++++++++++++++++++++ src/advanced/entry_points_overriding.md | 17 ++++---- src/advanced/sudo.md | 57 +++++++++++++++++++++++++ src/basics/create-project.md | 2 +- src/basics/entry-points.md | 2 +- src/basics/first-messages.md | 4 +- src/basics/remote.md | 38 ++++++++++++++--- src/basics/reusability.md | 2 +- 9 files changed, 159 insertions(+), 19 deletions(-) create mode 100644 src/advanced/attributes_forwarding.md create mode 100644 src/advanced/sudo.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 1ca4d21..fac867e 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -25,8 +25,10 @@ - [Advanced](advanced.md) - [Override entry point](advanced/entry_points_overriding.md) + - [Sudo entry point](advanced/sudo.md) - [Custom messages](advanced/custom.md) - [Generics](advanced/generics.md) + - [Attributes forwarding](advanced/attributes_forwarding.md) - [Ibc]() diff --git a/src/advanced/attributes_forwarding.md b/src/advanced/attributes_forwarding.md new file mode 100644 index 0000000..89f81cd --- /dev/null +++ b/src/advanced/attributes_forwarding.md @@ -0,0 +1,54 @@ +# Attributes forwarding + +This feature allows ^sylvia users to forward any attribute to every message +type using `#[sv::msg_attr(msg_type, ...)]` attribute. For the messages +that resolves to enum types it is possible to forward attributes per +enum field by using `#[sv::attr(...)]` - this works for `exec`, `query` +and `sudo` methods. + +## Example + +```rust,noplayground +use cosmwasm_std::{Response, StdResult}; +use sylvia::types::{InstantiateCtx, ExecCtx}; +use sylvia::{contract, entry_points}; + + +pub mod interface { + use cosmwasm_std::{Response, StdResult, StdError}; + use sylvia::types::QueryCtx; + use sylvia::interface; + + #[interface] + #[sv::msg_attr(query, derive(PartialOrd))] + pub trait Interface { + type Error: From; + + #[sv::msg(query)] + #[sv::attr(serde(rename(serialize = "QuErY")))] + fn interface_query_msg(&self, _ctx: QueryCtx) -> StdResult; + } +} + +pub struct CounterContract; + +#[entry_points] +#[contract] +#[sv::msg_attr(exec, derive(PartialOrd))] +impl CounterContract { + pub const fn new() -> Self { + Self + } + + #[sv::msg(instantiate)] + pub fn instantiate(&self, _ctx: InstantiateCtx) -> StdResult { + Ok(Response::default()) + } + + #[sv::msg(exec)] + #[sv::attr(serde(rename(serialize = "EXEC_METHOD")))] + pub fn exec_method(&self, _ctx: ExecCtx) -> StdResult { + Ok(Response::default()) + } +} +``` \ No newline at end of file diff --git a/src/advanced/entry_points_overriding.md b/src/advanced/entry_points_overriding.md index 3d99fd0..dff64ed 100644 --- a/src/advanced/entry_points_overriding.md +++ b/src/advanced/entry_points_overriding.md @@ -1,29 +1,30 @@ # Override entry point -^Sylvia is still developing and lacks features like f.e. `sudo` support. -If you need to use a lacking feature of `CosmWasm` or prefer to define some custom -entry point, it is possible to use the `#[sv::override_entry_point(...)]` attribute. +It may happen that for any reason CosmWasm will start support some new +entry point that is not yet implemented in ^sylvia. There is a way to +add it manually using `#[sv::override_entry_point(...)]` attribute. +This feature can be used to override already implemented entry points +like `execute` and `query`. ## Example -To make ^sylvia generate multitest helpers with `sudo` support, you first need to define your +To make ^sylvia generate multitest helpers with `cusom_entrypoint` support, you first need to define your `entry point`. ```rust,noplayground #[entry_point] -pub fn sudo(deps: DepsMut, _env: Env, _msg: SudoMsg) -> StdResult { +pub fn cusom_entrypoint(deps: DepsMut, _env: Env, _msg: SudoMsg) -> StdResult { CounterContract::new().counter.save(deps.storage, &3)?; Ok(Response::new()) } ``` -You have to define the `SudoMsg` yourself, as it is not yet supported. +You have to define the `CustomEntrypointMsg` yourself, as it is not yet supported. ```rust,noplayground #[cfg_attr(not(feature = "library"), entry_points)] #[contract] -#[sv::override_entry_point(sudo=crate::entry_points::sudo(crate::messages::SudoMsg))] -#[sv::override_entry_point(exec=crate::entry_points::execute(crate::messages::CustomExecMsg))] +#[sv::override_entry_point(custom=crate::entry_points::custom_entrypoint(crate::messages::CustomEntrypointMsg))] impl CounterContract { } ``` diff --git a/src/advanced/sudo.md b/src/advanced/sudo.md new file mode 100644 index 0000000..7052f7c --- /dev/null +++ b/src/advanced/sudo.md @@ -0,0 +1,57 @@ +# Sudo entry point + +Sylvia supports a `sudo` type entry point both in interfaces and in +contracts. Those methods can be used as a part of the network's +governance procedures. More informations can be found in official +CosmWasm documentation. From ^sylvia user point of view there's no +much difference between `sudo` and `exec` methods. + +## Example + +```rust,noplayground +use cosmwasm_std::{Response, StdResult}; +use sylvia::types::{InstantiateCtx, SudoCtx}; +use sylvia::{contract, entry_points}; + + +pub mod interface { + use cosmwasm_std::{Response, StdResult, StdError}; + use sylvia::types::{SudoCtx}; + use sylvia::interface; + + #[interface] + pub trait Interface { + type Error: From; + + #[sv::msg(sudo)] + fn interface_sudo_msg(&self, _ctx: SudoCtx) -> StdResult; + } +} + +pub struct CounterContract; + +#[entry_points] +#[contract] +#[sv::messages(interface)] +impl CounterContract { + pub const fn new() -> Self { + Self + } + + #[sv::msg(instantiate)] + pub fn instantiate(&self, _ctx: InstantiateCtx) -> StdResult { + Ok(Response::default()) + } + + #[sv::msg(sudo)] + pub fn sudo_method(&self, _ctx: SudoCtx) -> StdResult { + Ok(Response::default()) + } +} + +impl interface::Interface for CounterContract { + fn interface_sudo_msg(&self, _ctx: SudoCtx) -> StdResult { + Ok(Response::default()) + } +} +``` \ No newline at end of file diff --git a/src/basics/create-project.md b/src/basics/create-project.md index 7447010..c4ebb38 100644 --- a/src/basics/create-project.md +++ b/src/basics/create-project.md @@ -38,7 +38,7 @@ Additionally, we added some core dependencies for smart contracts: standard library for smart contracts. It provides essential utilities for communication with the outside world, helper functions, and types. Every smart contract we will build will use this dependency. -- [`sylvia`](https://docs.rs/sylvia/0.9.3/sylvia/) - Crate, we will learn in this +- [`sylvia`](https://docs.rs/sylvia/latest/sylvia/) - Crate, we will learn in this book. It provides us with three procedural macros: `entry_points`, `contract` and `interface`. I will expand on them later in the book. - [`schemars`](https://docs.rs/schemars/0.8.12/schemars/index.html) - Crate used to create JSON diff --git a/src/basics/entry-points.md b/src/basics/entry-points.md index caba4c8..2430fba 100644 --- a/src/basics/entry-points.md +++ b/src/basics/entry-points.md @@ -17,7 +17,7 @@ To start, we will go with three basic entry points: ## Generate entry points -^Sylvia provides an attribute macro named [`entry_points`](https://docs.rs/sylvia/0.7.0/sylvia/attr.entry_points.html). +^Sylvia provides an attribute macro named [`entry_points`](https://docs.rs/sylvia/latest/sylvia/attr.entry_points.html). In most cases, your entry point will just dispatch received messages to the handler, so it's not necessary to manually create them, and we can rely on a macro to do that for us. diff --git a/src/basics/first-messages.md b/src/basics/first-messages.md index e0eca94..13b9f22 100644 --- a/src/basics/first-messages.md +++ b/src/basics/first-messages.md @@ -40,14 +40,14 @@ impl CounterContract { So what is going on here? First, we define the CounterContract struct. It is empty right now but later when we learn about states, we will use its fields to store them. -We mark the `impl` block with [`contract`](https://docs.rs/sylvia/0.7.0/sylvia/attr.contract.html) +We mark the `impl` block with [`contract`](https://docs.rs/sylvia/latest/sylvia/attr.contract.html) attribute macro. It will parse every method inside the `impl` block marked with the `[sv::msg(...)]` attribute and create proper messages and utilities like `multitest helpers` for them. More on them later. `CosmWasm` contract requires only the `instantiate` entry point, and it is mandatory to specify it for the `contract` macro. We have to provide it with the proper context type -[`InstantiateCtx`](https://docs.rs/sylvia/0.7.0/sylvia/types/struct.InstantiateCtx.html). +[`InstantiateCtx`](https://docs.rs/sylvia/latest/sylvia/types/struct.InstantiateCtx.html). Context gives us access to the blockchain state, information about our contract, and the sender of the message. We return the [`StdResult`](https://docs.rs/cosmwasm-std/1.3.1/cosmwasm_std/type.StdResult.html) diff --git a/src/basics/remote.md b/src/basics/remote.md index e0d58c5..9066ded 100644 --- a/src/basics/remote.md +++ b/src/basics/remote.md @@ -4,28 +4,42 @@ Your contract may rely on communication with another one. For example, it could `instantiate` a `CW20` contract and, during the workflow, send `Mint` messages to it. If `CW20` contract was created using ^sylvia, it would have a `Remote` type generated which would make this process more user friendly. -Currently, it is only possible to send queries using `Remote` but support for the `execute` messages -is on the way. +It is possible to send queries and build `execute` messages by using `Remote`. To check some examples, checkout the ^sylvia repository -and go to `sylvia/tests/remote.rs`. +and go to `sylvia/tests/remote.rs` and `sylvia/tests/executor.rs`. ## Working with Remote `Remote` represents some contract instantiated on the blockchain. It aims to give contract developers a gateway to communicate with other contracts. It has only one field, which is a remote contract address. -It exposes only a single method called `querier`, which returns a `BoundQuerier` type. -`BoundQuerier` has a method for every contract and interface query. +There are two main methods implemented for this type: + * `querier`, which returns a `BoundQuerier` type, + * `executor` that returns a `ExecutorBuilder` type. + +`BoundQuerier` implements `Querier` traits of every sylvia contract and interface. +`Querier` traits are auto-generated by `contract` and `interface` macros and consist +of every query method of the given contract and interface. + +Similar to `BoundQuerier` and `Querier`, the `ExecutorBuilder` implements every +`Executor` trait auto-generated for sylvia contracts and interfaces. `Executor` +traits contain `exec` methods. + + If we create a contract relying on our `CounterContract`, it could query its state as below. ```rust,noplayground +use sylvia::types::Remote; +use crate::whitelist::sv::Querier as WhitelistQuerier; +use crate::contract::sv::Querier as ContractQuerier; + let count = Remote::::new(addr) .querier(&ctx.deps.querier) .count()? .count; -let admins = crate::whitelist::Remote::::new(ctx.info.sender) +let admins = Remote::::new(ctx.info.sender) .querier(&ctx.deps.querier) .admins()?; ``` @@ -54,6 +68,18 @@ self.cw20 .query_all_balances()? ``` +Let's see an example for an `exec` method call: + +```rust,noplayground +use sylvia::types::Remote; +use crate::contract::sv::Executor; + +let increment_msg: WasmMsg = Remote::::new(addr) + .executor(&ctx.deps.querier) + .increment_count()? + .build(); +``` + # Next step Phew.. that was a journey. We learned most of the ^sylvia features and should be ready to create our first contracts. diff --git a/src/basics/reusability.md b/src/basics/reusability.md index e85686a..2ae5ab2 100644 --- a/src/basics/reusability.md +++ b/src/basics/reusability.md @@ -156,7 +156,7 @@ pub trait Whitelist { } ``` -We annotate interfaces with [`interface`](https://docs.rs/sylvia/0.7.0/sylvia/attr.interface.html) +We annotate interfaces with [`interface`](https://docs.rs/sylvia/latest/sylvia/attr.interface.html) attribute macro. It expects us to declare the associated type `Error`. This will help us later as otherwise we would have to either expect `StdError` or our custom error in the return type, but we don't know what contracts will use this interface.