Skip to content

Commit

Permalink
Sylvia: Describe attribute forwarding (#124)
Browse files Browse the repository at this point in the history
  • Loading branch information
jawoznia authored Aug 6, 2024
2 parents 47b7d5e + 5c828af commit 53fddff
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 30 deletions.
4 changes: 3 additions & 1 deletion src/pages/sylvia/attributes/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
57 changes: 57 additions & 0 deletions src/pages/sylvia/attributes/attr.mdx
Original file line number Diff line number Diff line change
@@ -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<Response> {
Ok(Response::new())
}

#[sv::msg(exec)]
#[sv::attr(serde(rename = "execute"))]
fn exec(&self, ctx: ExecCtx) -> StdResult<Response> {
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 {},
}
```
63 changes: 63 additions & 0 deletions src/pages/sylvia/attributes/msg_attr.mdx
Original file line number Diff line number Diff line change
@@ -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<Response> {
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 {}
```
27 changes: 14 additions & 13 deletions src/pages/sylvia/basics/contract-structure.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
36 changes: 33 additions & 3 deletions src/pages/sylvia/macros/contract.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

<Callout>Use `contract` macro only on top of struct impl blocks</Callout>
<Callout>
Use [`contract`](https://docs.rs/sylvia/latest/sylvia/attr.contract.html) macro only on top of
struct impl blocks
</Callout>

## 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)
Expand Down Expand Up @@ -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<Response> {
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
Expand Down
13 changes: 0 additions & 13 deletions src/pages/sylvia/macros/entry-points.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,3 @@ with concrete types passed in brackets.
<Callout>
Remember to pass the types in the order reflecting the order of generics defined on the contract.
</Callout>

If the contract uses generic custom types we have to do some more work.

```rust
#[cfg_attr(not(feature = "library"), entry_points(generics<Empty, Empty>, 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.
25 changes: 25 additions & 0 deletions src/pages/sylvia/macros/interface.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,28 @@ pub trait Interface {
fn interface_exec(&self, ctx: ExecCtx, param: Self::MyType) -> StdResult<Response>;
}
```

## 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<Response, Self::Error>;
```

The output of the above code will be:

```rust {3}
pub enum MyInterfaceExecMsg {
Exec {
#[serde(default)]
value: String,
},
}
```

0 comments on commit 53fddff

Please sign in to comment.