Skip to content

Commit

Permalink
Merge pull request #7 from CosmWasm/just-an-idea
Browse files Browse the repository at this point in the history
Proposal of using preprocessor
  • Loading branch information
jawoznia authored Feb 7, 2024
2 parents c937654 + e135da8 commit 8fdc08a
Show file tree
Hide file tree
Showing 19 changed files with 60 additions and 47 deletions.
4 changes: 3 additions & 1 deletion book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ authors = ["Jan Woźniak", "Bartłomiej Kuras"]
language = "en"
multilingual = false
src = "src"
title = "Sylvia book"
title = "The Sylvia Book"
description = "Guide to building CosmWasm smart contracts"

[rust]
edition = "2021"

[preprocessor.yapp]
6 changes: 3 additions & 3 deletions src/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Introduction

This book is a guide for creating CosmWasm smart contracts with the Sylvia framework.
This book is a guide for creating CosmWasm smart contracts with the ^sylvia framework.
It will lead you step by step and explain relevant topics from easiest to trickiest.

The idea of the book is not only to tell you about smart contract development but also
to show you how to do it clean and maintainable. I will show you some good practices
for using `Sylvia`.
for using ^sylvia.

This book is not meant to teach you about the `CosmWasm`.
To learn about that, read [The CosmWasm Book](https://book.cosmwasm.com).

This book covers `Sylvia` in version 0.9.0.
> ^note This book covers ^sylvia in version **^sylvia-version**.
## Prerequisites

Expand Down
6 changes: 3 additions & 3 deletions src/advanced.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Advanced

The previous chapter explained basics of `sylvia`. If you read it you should be familiar
with general usage of `sylvia` framework.
The previous chapter explained basics of ^sylvia. If you read it you should be familiar
with general usage of ^sylvia framework.

In this chapter we will go through some "advanced" features of `sylvia` like ability
In this chapter we will go through some "advanced" features of ^sylvia like ability
to override entry points and creating custom messages.
6 changes: 3 additions & 3 deletions src/advanced/custom.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Blockchain creators might define chain-specific logic triggered through defined by them messages.
`CosmWasm` provides a way to send such messages through `cosmwasm_std::CosmosMsg::Custom(..)` variant.

`Sylvia` supports this feature, allowing both custom interfaces and contracts.
^Sylvia supports this feature, allowing both custom interfaces and contracts.

## Custom interface

Expand Down Expand Up @@ -278,10 +278,10 @@ pub mod impl_non_custom {
}
```

As you can see, although it's non-custom, we still have to inform `sylvia` custom types from the contract.
As you can see, although it's non-custom, we still have to inform ^sylvia custom types from the contract.
It's required for the `MultiTest` helpers to be generic over the same types as the contract.

Let's add the last `messages` attribute to the contract. It has to end with `: custom(msg query)`. This way `sylvia`
Let's add the last `messages` attribute to the contract. It has to end with `: custom(msg query)`. This way ^sylvia
will know that it has to cast `Response<Custom>` to `Response<Empty>` for `msg` and `Deps<Custom>` to `Deps<Empty>` for `query`.

`src/contract.rs`
Expand Down
4 changes: 2 additions & 2 deletions src/advanced/entry_points_overriding.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Override entry point

`Sylvia` is still developing and lacks features like f.e. `sudo` support.
^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.

## Example

To make `sylvia` generate multitest helpers with `sudo` support, you first need to define your
To make ^sylvia generate multitest helpers with `sudo` support, you first need to define your
`entry point`.

```rust,noplayground
Expand Down
12 changes: 6 additions & 6 deletions src/advanced/generics.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

When implementing a contract, users might want to define some generic data it should store.
One might even want the message to have some generic parameters or return type.
`Sylvia` supports generics in the contracts and interfaces.
^Sylvia supports generics in the contracts and interfaces.

## Prepare project

Expand Down Expand Up @@ -61,7 +61,7 @@ where
Simple and expected behavior.
What if we want to extend the `custom` functionality with generics?
In such a case, we would have to add `#[sv::custom(..)]` attribute to the trait with the name of our generics.
It is a standard approach when using `CustomMsg` and `CustomQuery` in `sylvia` so there is nothing new here.
It is a standard approach when using `CustomMsg` and `CustomQuery` in ^sylvia so there is nothing new here.

`src/generic.rs`
```rust
Expand Down Expand Up @@ -174,7 +174,7 @@ impl Generic<MyMsg, MyMsg, MyQuery, MyMsg> for NonGenericContract {
```

To implement a generic interface, we have to specify the types. Here we use `MyMsg` and `MyQuery`
we defined earlier. No additional attributes have to be passed as `sylvia` will read them
we defined earlier. No additional attributes have to be passed as ^sylvia will read them
from the interface type.
Because we defined the interface as `custom` we have to pass these types into `sv::custom(..)` attribute
same as in the interface definition.
Expand Down Expand Up @@ -215,7 +215,7 @@ We also had to add `#[sv::custom(..)]` attribute to the contract definition and

## Generic contract

Using generic interfaces in `sylvia` is simple. Let's see how it works with generic contracts.
Using generic interfaces in ^sylvia is simple. Let's see how it works with generic contracts.

Let us define a new module in which we will define a generic contract.

Expand Down Expand Up @@ -260,7 +260,7 @@ This example showcases two usages of generics in contract:
- Generic field
- Generic message parameter

`Sylvia` works in both cases, and you can expand your generics to every message type, return type, or `custom_queries` as shown in the case of the `interface`. For the readability of this example, we will
^Sylvia works in both cases, and you can expand your generics to every message type, return type, or `custom_queries` as shown in the case of the `interface`. For the readability of this example, we will
keep just these two generic types.

`InstantiateParam` is passed as a field to the `InstantiateMsg`. This enforces some bounds
Expand Down Expand Up @@ -443,7 +443,7 @@ Our contract is ready to use. We can test it in the last step of this chapter.

## Test generic contract

`Sylvia` enforces the user to specify a solid type while implementing a generic interface on the contract.
^Sylvia enforces the user to specify a solid type while implementing a generic interface on the contract.
Due to this, we test `NonGenericContract` as a regular contract.

In case of the generic contract, we have to pass the types while constructing `CodeId`.
Expand Down
2 changes: 1 addition & 1 deletion src/basics.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Basics

This chapter will guide you through creating basic smart contract, step by step.
I will explain the core features of `Sylvia` framework and some good practices.
I will explain the core features of ^sylvia framework and some good practices.
4 changes: 2 additions & 2 deletions src/basics/create-project.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ 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.7.0/sylvia/) - Crate, we will learn in this
- [`sylvia`](https://docs.rs/sylvia/0.9.3/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
schema documents for our contracts. It is automatically derived on types generated by
`sylvia` and will be later used to provide concise API for blockchain users, who might not be Rust developers.
^sylvia and will be later used to provide concise API for blockchain users, who might not be Rust developers.
- [`cosmwasm-schema`](https://docs.rs/cosmwasm-schema/1.3.1/cosmwasm_schema/) - Similar to `schemars`.
This crate expands on `schemars` and provides us with trait
[`QueryResponses`](https://docs.rs/cosmwasm-schema/1.3.1/cosmwasm_schema/trait.QueryResponses.html)
Expand Down
4 changes: 2 additions & 2 deletions src/basics/entry-points.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/0.7.0/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.

Expand Down Expand Up @@ -49,7 +49,7 @@ It is because **`#[contract]`** removes attributes like **`#[msg(...)]`** on whi

Always remember to place **`#[entry_points]`** first.

`Sylvia` generates entry points with [`#[entry_point]`](https://docs.rs/cosmwasm-std/1.3.1/cosmwasm_std/attr.entry_point.html)
^Sylvia generates entry points with [`#[entry_point]`](https://docs.rs/cosmwasm-std/1.3.1/cosmwasm_std/attr.entry_point.html)
attribute macro. Its purpose is to wrap the whole entry point to the form the Wasm runtime understands.
The proper Wasm entry points can use only basic types supported natively by Wasm specification, and
Rust structures and enums are not in this set. Working with such entry points would be
Expand Down
6 changes: 3 additions & 3 deletions src/basics/error_handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ A little to explain here. We load the count, and check if it's equal to zero. If
our newly defined error variant. If not, then we decrement its value.
However, this won't work. If you would try to build this you will receive:
`error[E0277]: the trait bound `cosmwasm_std::StdError: From<ContractError>` is not satisfied`.
It is because `sylvia` by default generates `dispatch` returning `Result<_, StdError>`. To
inform `sylvia` that it should be using a new type we add `#[error(ContractError)]` attribute to
It is because ^sylvia by default generates `dispatch` returning `Result<_, StdError>`. To
inform ^sylvia that it should be using a new type we add `#[error(ContractError)]` attribute to
the `contract` macro call.

```rust,noplayground
Expand Down Expand Up @@ -198,5 +198,5 @@ newly defined error variant.

# Next step

We introduced proper error handling to our contract. Now we will learn about `interfaces`. `Sylvia` feature allowing to
We introduced proper error handling to our contract. Now we will learn about `interfaces`. ^Sylvia feature allowing to
split our contract into semantic parts.
2 changes: 1 addition & 1 deletion src/basics/first-messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ which uses standard `CosmWasm` error
It's generic over [`Response`](https://docs.rs/cosmwasm-std/1.3.1/cosmwasm_std/struct.Response.html).
For now, we will return the `default` value of it.

I recommend expanding the macro now and seeing what `Sylvia` generates.
I recommend 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.

Expand Down
2 changes: 1 addition & 1 deletion src/basics/good-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,6 @@ my_contract = { version = "0.1", features = ["library"] }

## Single file/single macro call

I talked about it in some previous chapters. I cannot guarantee that future `sylvia` changes won't
I talked about it in some previous chapters. I cannot guarantee that future ^sylvia changes won't
cause code generation to overlap. To avoid future problems, I recommend restricting yourself
to single macro call per file.
6 changes: 3 additions & 3 deletions src/basics/multitest-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ well, but it is also an excellent tool for testing single-contract scenarios.

## Update dependencies

First, we need to add `sylvia` with `mt` feature enabled to our
First, we need to add ^sylvia with `mt` feature enabled to our
[`dev-dependencies`](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies).

```toml
Expand Down Expand Up @@ -69,9 +69,9 @@ fn instantiate() {
}
```

`Sylvia` generates a lot of helpers for us to make testing as easy as possible.
^Sylvia generates a lot of helpers for us to make testing as easy as possible.
To simulate blockchain, we create `sylvia::multitest::App`. Then we will use it to store the code id
of our contract on the blockchain using `sylvia` generated `CodeId`.
of our contract on the blockchain using ^sylvia generated `CodeId`.

Code id identifies our contract on the blockchain and allows us to instantiate the contract on it.
We do that using `CodeId::instantiate` method. It returns the `InstantiateProxy` type, allowing us
Expand Down
4 changes: 2 additions & 2 deletions src/basics/query.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ when we will talk about generating schema.

`QueryMsg` is an enum that will contain every `query` declared in your expanded `impl`. Thanks to
that you can focus solely on defining the behavior of the contract on receiving a message, and you
can leave it to `sylvia` to generate the messages and the `dispatch`.
can leave it to ^sylvia to generate the messages and the `dispatch`.

Note that our enum has no type assigned to the only `Count` variant. Typically
in Rust, we create variants without additional `{}` after the variant name. Here the
Expand All @@ -123,7 +123,7 @@ Instead of returning the `Response` type on the success case, we return an arbit
object. It's because queries are not using a typical actor model message flow - they cannot trigger
any actions nor communicate with other contracts in ways different than querying them (which is
handled by the `deps` argument). The query always returns plain data, which should be presented
directly to the querier. `Sylvia` does that by returning encoded response as
directly to the querier. ^Sylvia does that by returning encoded response as
[`Binary`](https://docs.rs/cosmwasm-std/1.3.1/cosmwasm_std/struct.Binary.html) by calling
[`to_binary`](https://docs.rs/cosmwasm-std/1.3.1/cosmwasm_std/fn.to_binary.html) function in dispatch.

Expand Down
6 changes: 3 additions & 3 deletions src/basics/remote.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

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
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.

To check some examples, checkout the [`sylvia`](https://github.com/CosmWasm/sylvia) repository
To check some examples, checkout the [^sylvia](https://github.com/CosmWasm/sylvia) repository
and go to `sylvia/tests/remote.rs`.

## Working with Remote
Expand Down Expand Up @@ -49,5 +49,5 @@ self.cw20

# Next step

Phew.. that was a journey. We learned most of the `sylvia` features and should be ready to create our first contracts.
Phew.. that was a journey. We learned most of the ^sylvia features and should be ready to create our first contracts.
In the last chapter, we will learn about some of the best practices that will make our code more readable and maintainable.
18 changes: 9 additions & 9 deletions src/basics/reusability.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Reusability

We have covered almost all the basics of writing smart contracts with `sylvia`.
We have covered almost all the basics of writing smart contracts with ^sylvia.
In this last chapter of the `basics` section, I will tell you about the ability to define
[`interface`](https://docs.rs/sylvia/latest/sylvia/attr.interface.html) in `sylvia`.
[`interface`](https://docs.rs/sylvia/latest/sylvia/attr.interface.html) in ^sylvia.

## Problem

Expand All @@ -15,8 +15,8 @@ into semantically compatible parts.

## Solution

`Sylvia` has a feature to reuse already defined messages and apply them in new contracts.
Clone and open [`sylvia`](https://github.com/CosmWasm/sylvia) repository. Go to
^Sylvia has a feature to reuse already defined messages and apply them in new contracts.
Clone and open [^sylvia](https://github.com/CosmWasm/sylvia) repository. Go to
`contracts/cw1-subkeys/src/contract.rs`. You can notice that the `impl` block for
the `Cw1SubkeysContract` is preceded by `#[messages(...)]` attribute.

Expand Down Expand Up @@ -65,7 +65,7 @@ impl ContractQueryMsg {
```

We can finally see why we need these `ContractQueryMsg` and `ContractExecMsg` next to our
regular message enums. `Sylvia` generated three tuple variants:
regular message enums. ^Sylvia generated three tuple variants:

- `Cw1` - which contains query msg defined in `cw1`;

Expand All @@ -74,7 +74,7 @@ regular message enums. `Sylvia` generated three tuple variants:
- `Cw1SubkeysContract` - which contains query msg defined in our contract.

We use this wrapper to match with the proper variant and then call `dispatch` on this message.
`Sylvia` also ensure that no message overlaps between interfaces and contract so that
^Sylvia also ensure that no message overlaps between interfaces and contract so that
contracts API won't break.

## Declaring interface
Expand Down Expand Up @@ -162,7 +162,7 @@ otherwise we would have to either expect `StdError` or our custom error in the r
but we don't know what contracts will use this interface.

Our trait defines three methods. Let's implement them on our contract.
`Sylvia` still grows and there can be some type duplications in the future. I recommend keeping all
^Sylvia still grows and there can be some type duplications in the future. I recommend keeping all
three: contract implementation, interface definition and interface implementation on contract in
separate modules.

Expand Down Expand Up @@ -218,7 +218,7 @@ the macro where our contract is defined. It's required for pathing. You can expa
and check where it is used.

Next, there is the attribute mentioned before - `messages`. Its purpose is similar to the `module`
with the difference that it provides `sylvia` with path to the interface. We also have to provide
with the difference that it provides ^sylvia with path to the interface. We also have to provide
the interface's name, although it should be optional in the future.
We need to do one more thing, which is to add the `messages` attribute to the contract definition.

Expand Down Expand Up @@ -342,5 +342,5 @@ of one.

# Next step

We have learned about almost all of the `sylvia` features. The next chapter will be about talking
We have learned about almost all of the ^sylvia features. The next chapter will be about talking
with remotes.
2 changes: 1 addition & 1 deletion src/basics/state.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Let's make it more usable. In this chapter, we will introduce the contract's sta
## Adding contract state

The name of our contract is a little spoiler. We will add the `counter` state. It's not a real world
usage of smart contracts, but it helps to see the usage of `Sylvia` without getting into business logic.
usage of smart contracts, but it helps to see the usage of ^Sylvia without getting into business logic.

The first thing to do, is to update `Cargo.toml` with yet another dependency - the
[`storage-plus`](https://crates.io/crates/cw-storage-plus) crate with high-level bindings for
Expand Down
2 changes: 1 addition & 1 deletion src/setting-up-env.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ sylvia $ cargo test

You should see that everything in the repository gets compiled and all tests pass.

`Sylvia` framework contains some examples of contracts. To find them go to `examples/contracts`
^Sylvia framework contains some examples of contracts. To find them go to `examples/contracts`
directory. These contracts are maintained by CosmWasm creators, so contracts in there should follow
good practices.

Expand Down
11 changes: 11 additions & 0 deletions yapp.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
^sylvia-version
0.9.x

^sylvia
[**sylvia**](https://github.com/CosmWasm/sylvia)

^Sylvia
[**Sylvia**](https://github.com/CosmWasm/sylvia)

^note
**NOTE**:

0 comments on commit 8fdc08a

Please sign in to comment.