diff --git a/src/pages/sylvia/attributes/_meta.json b/src/pages/sylvia/attributes/_meta.json index 0b18a388..54a2b66d 100644 --- a/src/pages/sylvia/attributes/_meta.json +++ b/src/pages/sylvia/attributes/_meta.json @@ -3,5 +3,7 @@ "error": "Error", "message": "Message", "msg": "Msg", - "override-entry-point": "Override_entry_point" + "override-entry-point": "Override_entry_point", + "attr": "Attr", + "msg_attr": "MsgAttr" } diff --git a/src/pages/sylvia/attributes/attr.mdx b/src/pages/sylvia/attributes/attr.mdx new file mode 100644 index 00000000..b3ebbb2b --- /dev/null +++ b/src/pages/sylvia/attributes/attr.mdx @@ -0,0 +1,57 @@ +--- +tags: ["sylvia", "attributes"] +--- + +import { Callout } from "nextra/components"; + +# `sv::attr` attribute + +Use `sv::attr` to forward an external attribute to the generated message variant. + +## Macros + +List of macros supporting the `sv::attr` attribute: + +- [`contract`](../macros/contract) +- [`interface`](../macros/interface) + +## Usage + +Use the `sv::attr` above any of the methods marked with +[`#[sv::msg(exec|sudo|query)]`](../attributes/msg) attribute. + +```rust {19} +use sylvia::contract; +use sylvia::cw_std::{Response, StdResult}; +use sylvia::types::{ExecCtx, InstantiateCtx}; + +pub struct MyContract; + +#[contract] +impl Contract { + pub fn new() -> Self { + Self + } + + #[sv::msg(instantiate)] + fn instantiate(&self, ctx: InstantiateCtx) -> StdResult { + Ok(Response::new()) + } + + #[sv::msg(exec)] + #[sv::attr(serde(rename = "execute"))] + fn exec(&self, ctx: ExecCtx) -> StdResult { + Ok(Response::new()) + } +} +``` + +The [`contract`](../macros/contract) and [`interface`](../macros/interface) macros will decorate the +message variant with the attribute provided in `sv::attr`. + +```rust {2} +pub enum ExecMsg { + #[serde(rename = "execute")] + Exec {}, +} +``` diff --git a/src/pages/sylvia/attributes/msg_attr.mdx b/src/pages/sylvia/attributes/msg_attr.mdx new file mode 100644 index 00000000..ae41aa25 --- /dev/null +++ b/src/pages/sylvia/attributes/msg_attr.mdx @@ -0,0 +1,63 @@ +--- +tags: ["sylvia", "attributes"] +--- + +import { Callout } from "nextra/components"; + +# `sv::msg_attr` attribute + +Use `sv::msg_attr` to forward an external attribute to the generated message. + +## Macros + +List of macros supporting the `sv::msg_attr` attribute: + +- [`contract`](../macros/contract) +- [`interface`](../macros/interface) + +## Usage + +Use the `sv::msg_attr` above any of the methods marked with [`#[sv::msg(..)]`](../attributes/msg) +attribute. + +```rust {19} +use sylvia::contract; +use sylvia::cw_std::{Response, StdResult}; +use sylvia::types::InstantiateCtx; + +pub struct MyContract; + +#[contract] +#[sv::msg_attr(instantiate, derive(MyDeriveMacro))] +#[sv::msg_attr(instantiate, MyAttributeMacro(param))] +#[sv::msg_attr(instantiate, AttributeForMacro(param1, param2))] +impl MyContract { + pub fn new() -> Self { + Self + } + + #[sv::msg(instantiate)] + fn instantiate(&self, ctx: InstantiateCtx) -> StdResult { + Ok(Response::new()) + } +} +``` + +The [`contract`](../macros/contract) and [`interface`](../macros/interface) macros will decorate the +message with the attributes/macros provided in `sv::msg_attr`. + +```rust {8, 10-11} +#[derive( + sylvia::serde::Serialize, + sylvia::serde::Deserialize, + Clone, + Debug, + PartialEq, + sylvia::schemars::JsonSchema, + MyDeriveMacro, +)] +#[MyAttributeMacro(param)] +#[AttributeForMacro(param1, param2)] +#[serde(rename_all = "snake_case")] +pub struct InstantiateMsg {} +``` diff --git a/src/pages/sylvia/basics/contract-structure.mdx b/src/pages/sylvia/basics/contract-structure.mdx index 31f930ef..2cc54dfa 100644 --- a/src/pages/sylvia/basics/contract-structure.mdx +++ b/src/pages/sylvia/basics/contract-structure.mdx @@ -151,17 +151,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 @@ -171,16 +172,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). Feel 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/entry-points.mdx b/src/pages/sylvia/macros/entry-points.mdx index cbb009ff..b30b1c7d 100644 --- a/src/pages/sylvia/macros/entry-points.mdx +++ b/src/pages/sylvia/macros/entry-points.mdx @@ -127,16 +127,3 @@ with concrete types passed in brackets. Remember to pass the types in the order reflecting the order of generics defined on the contract. - -If the contract uses generic custom types we have to do some more work. - -```rust -#[cfg_attr(not(feature = "library"), entry_points(generics, custom(msg=SvCustomMsg, query=SvCustomQuery)))] -``` - -After coma we have to pass another parameter `custom`, and in the paranthesis specify which types -should be used in place of custom message and custom query. The syntax reflects one used in the -[`custom`](../attributes/custom). - -This is required as, for at least now, Sylvia is unable to determine which concrete types are -supposed to be used in place of generic custom types. diff --git a/src/pages/sylvia/macros/interface.mdx b/src/pages/sylvia/macros/interface.mdx index c5546d71..7c5b740f 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 {3} +pub enum MyInterfaceExecMsg { + Exec { + #[serde(default)] + value: String, + }, +} +```