From 94a08a7447f6d3e2e46ec921f09231ced680c3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Wo=C5=BAniak?= Date: Thu, 1 Aug 2024 17:51:54 +0200 Subject: [PATCH] Sylvia: Describe forwarding attributes to message fields --- .../sylvia/basics/contract-structure.mdx | 27 +++++++------- src/pages/sylvia/macros/contract.mdx | 36 +++++++++++++++++-- src/pages/sylvia/macros/interface.mdx | 25 +++++++++++++ 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/pages/sylvia/basics/contract-structure.mdx b/src/pages/sylvia/basics/contract-structure.mdx index 7149b2fc..9cafea9b 100644 --- a/src/pages/sylvia/basics/contract-structure.mdx +++ b/src/pages/sylvia/basics/contract-structure.mdx @@ -65,17 +65,18 @@ In the first two lines, we see the usage of two macros: point collision. - [`contract`](../macros/contract) - Parses every method inside the `impl` block marked with the - `[sv::msg(...)]` attribute and create proper messages and utilities like helpers for - [`MultiTest`](../../cw-multi-test). + [`[sv::msg(...)]`](../attributes/msg) attribute and create proper messages and utilities like + helpers for [`MultiTest`](../../cw-multi-test). -This simple example also has the `sv::msg(...)` attributes. Sylvia macros distinguish the if message -should be generated from the marked method and of what type. +This simple example also has the [`sv::msg(...)`](../attributes/msg) attributes. Sylvia macros +distinguish the if message should be generated from the marked method and of what type. CosmWasm contract requires the `instantiate` message, and it is mandatory to specify it for the -`contract` macro. We have to provide it with the proper context type: +[`contract`](../macros/contract) macro. We have to provide it with the proper context type: [`InstantiateCtx`](https://docs.rs/sylvia/latest/sylvia/types/struct.InstantiateCtx.html). Another -mandatory method is the `new`, as contract fields are out of scope for the `contract` macro, and -otherwise we wouldn't be able to create the contract object in message dispatching. +mandatory method is the `new`, as contract fields are out of scope for the +[`contract`](../macros/contract) macro, and otherwise we wouldn't be able to create the contract +object in message dispatching. Context gives us access to the blockchain state, information about our contract, and the sender of the message. We return the @@ -85,16 +86,16 @@ standard CosmWasm error [`Response`](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/struct.Response.html). The template contract also contains a query and an exec messages. Each type of message in CosmWasm -supports different contexts. F.e. the -[`QueryCtx`](https://docs.rs/sylvia/latest/sylvia/types/struct.QueryCtx.html) exposes to the user an +supports different contexts. F.e. the [`QueryCtx`](../types/context) exposes to the user an immutable [`Deps`](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/struct.Deps.html) as by design, -queries should never mutate the state. This is not the case for the -[`ExecCtx`](https://docs.rs/sylvia/latest/sylvia/types/struct.ExecCtx.html) and `InstantiateCtx` -which exposes the [`DepsMut`](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/struct.DepsMut.html). +queries should never mutate the state. This is not the case for the [`ExecCtx`](../types/context) +and `InstantiateCtx` which exposes the +[`DepsMut`](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/struct.DepsMut.html). Fell free expanding the macro now and seeing what Sylvia generates. It might be overwhelming, as there will be a lot of things generated that seem not relevant to our code, so for the bare minimum, -check the `InstantiateMsg` and its `impl` block. +check the [`InstantiateMsg`](../macros/generated-types/message-types#contract-messages) and its +`impl` block. Sylvia doesn't generate anything magical, but regular CosmWasm contract types customized based on the provided methods and attributes. This means that the Sylvia contract is fully interoperational diff --git a/src/pages/sylvia/macros/contract.mdx b/src/pages/sylvia/macros/contract.mdx index 9bff9ddf..32f7bc2a 100644 --- a/src/pages/sylvia/macros/contract.mdx +++ b/src/pages/sylvia/macros/contract.mdx @@ -6,13 +6,18 @@ import { Callout } from "nextra/components"; # Contract -Use the `contract` macro to generate contract messages +Use the [`contract`](https://docs.rs/sylvia/latest/sylvia/attr.contract.html) macro to generate +contract messages -Use `contract` macro only on top of struct impl blocks + + Use [`contract`](https://docs.rs/sylvia/latest/sylvia/attr.contract.html) macro only on top of + struct impl blocks + ## Attributes -List of attributes supported by `contract` macro: +List of attributes supported by +[`contract`](https://docs.rs/sylvia/latest/sylvia/attr.contract.html) macro: - [`custom`](../attributes/custom) - [`error`](../attributes/error) @@ -142,6 +147,31 @@ This is a standard way to create generic structs in Rust. Two important things t fulfill their trait bounds. In most cases it's enough to add the `sylvia::types::CustomMsg + \'static` bounds. +## Forwarding attributes to fields + +The [`contract`](https://docs.rs/sylvia/latest/sylvia/attr.contract.html) macro can forward +attributes to the fields of the messages. + +```rust {5} +#[sv::msg(instantiate)] +fn instantiate( + &self, + ctx: InstantiateCtx, + #[serde(default)] value: String, +) -> StdResult { + Ok(Response::new()) +} +``` + +The output of the above code will be: + +```rust {2} +pub struct InstantiateMsg { + #[serde(default)] + pub value: String, +} +``` + ## Good practices ### Prefer generic custom types diff --git a/src/pages/sylvia/macros/interface.mdx b/src/pages/sylvia/macros/interface.mdx index c5546d71..682f4b3a 100644 --- a/src/pages/sylvia/macros/interface.mdx +++ b/src/pages/sylvia/macros/interface.mdx @@ -103,3 +103,28 @@ pub trait Interface { fn interface_exec(&self, ctx: ExecCtx, param: Self::MyType) -> StdResult; } ``` + +## Forwarding attributes to fields + +The [`interface`](https://docs.rs/sylvia/latest/sylvia/attr.interface.html) macro can forward +attributes to the fields of the messages. + +```rust {5} +#[sv::msg(exec)] +fn exec( + &self, + ctx: ExecCtx, + #[serde(default)] value: String, +) -> Result; +``` + +The output of the above code will be: + +```rust {2} +pub enum MyInterfaceExecMsg { + Exec { + #[serde(default)] + value: String, + }, +} +```