Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand entrypoint docs #76

Merged
merged 3 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs-test-gen/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions docs-test-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ cosmos-sdk-proto = { version = "0.21.1", default-features = false }
cw-storage-plus = "*"
serde = "*"
cw-storey = "*"
schemars = "0.8.21" # Used in entrypoint example
100 changes: 96 additions & 4 deletions src/pages/core/entrypoints.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ these entrypoints, each one different from the last.
In this section we want to give you a quick overview over all the entrypoints
and when they are called.

<Callout>
In our examples, we will always refer to `StdResult` as the error type.
aumetra marked this conversation as resolved.
Show resolved Hide resolved
This is just for convenience since every type that implements the `ToString` type can be used as an error type!

Meaning, as long as it implements `ToString`, nothing is stopping you from
defining `Result<Response, MyError>`. This can reduce your code complexity,
especially if you want to use the try operator.

</Callout>

## Defining entrypoints

While you will learn all about entrypoints in the next sections, we want to give
Expand All @@ -27,16 +37,16 @@ VM: "Hey! This is an entrypoint, please use it when needed!"
When defining an entrypoint, it is important to use the correct types for the
parameters and return type. Incorrect types will cause errors when trying to
call the contract.
<br /> In the following sections we will take a look at all possible entrypoints,
including the correct function signature.
<br /> In the following sections we will take a look at all possible
entrypoints, including the correct function signature.
</Callout>

<Callout>
Even though the sections will show you to use `#[entry_point]`, it is
recommended to define your endpoints as `#[cfg_attr(not(feature = "library"),
entry_point)]`.
<br /> The reason behind that is that it allows you to reuse your contract as a
library.
<br /> The reason behind that is that it allows you to reuse your contract as
a library.
</Callout>

```rust template="core"
Expand All @@ -51,3 +61,85 @@ pub fn instantiate(
Ok(Response::default())
}
```

## Entrypoint parameters

Entrypoints have a few parameters (as you can see above), some of them are
predefined by `cosmwasm-std`, others are defined by the user themselves.

Here we go over the different predefined types the standard library provides,
and how you can define your own types.

### Predefined types

#### `Deps`/`DepsMut`

These structs provide you access to the:

- Storage
- VM API
- Querier

The big difference is that `DepsMut` gives you _mutable_ access to the storage.
This design is deliberate since you, for example, can't mutate the state in the
`query` endpoint. Instead of relying on runtime errors, this is made
_irrepresentable_ through Rust's type system.

#### `Env`

This struct provides you with some information of the current state of the
environment your contract is executed in.

The information provided is, for example, the block height, chain ID,
transaction info, etc. Basically anything you'd ever want to know about the
current state of the execution environment!

#### `MessageInfo`

This struct isn't provided to every endpoint, only to a select few.

It provides you with some information that might be crucial to you, depending on
the operation you want to perform. It contains the sender of the message you
just received, and the funds that were transferred along with it to your
contract.

### Defining your own messages

In our examples, you might have seen messages such as `InstantiateMsg`. These
messages are actually _user-defined_, meaning each contract developer has to
define them themselves.

To make this easier our `cosmwasm-schema` crate provides the `cw_serde`
attribute macro, to define an instantiate message, you simply write this:

```rust filename="instantiate.rs" template="core"
#[cw_serde]
struct CustomInstantiateMsg {
initial_admins: Vec<Addr>,
}
```

<Callout>
This macro actually just expands into a bunch of `derive` attributes.
We provide this simply for your convenience, otherwise you'd have to keep track of all of these derives yourself.

<details>
<summary>Without `#[cw_serde]`</summary>

```rust filename="instantiate.rs" template="core"
#[derive(
serde::Serialize,
serde::Deserialize,
Clone,
Debug,
PartialEq,
schemars::JsonSchema
)]
#[serde(deny_unknown_fields)]
struct CustomInstantiateMsg {
initial_admins: Vec<Addr>,
}
```

</details>
</Callout>
38 changes: 35 additions & 3 deletions src/pages/core/entrypoints/query.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,44 @@ import { Callout } from "nextra/components";

# Query

In the previous section we talked about the [`execute` endpoint]. The `query`
endpoint is actually pretty similar to its sibling `execute`, but with one key
difference: The storage is only accessible immutably.
In the previous section we talked about the [`execute` endpoint]. The `query` endpoint
is actually pretty similar to its sibling `execute`, but with one key difference:
The storage is only accessible immutably.

This means you can only _read_ from the storage but not _write_ to it.

## Properly defining a message

When defining a message for queries, you always return some value. To properly
document these return values, you'll want to define them in your schema.

This is where the `cosmwasm_schema::QueryResponses` derive macro comes in.

```rust filename="contract.rs"
#[cw_serde]
struct GreetResponse {
message: String,
}

#[cw_serde]
struct GoodbyeResponse {
message: String,
}

#[cw_serde]
#[derive(QueryResponses)]
enum CustomQueryMsg {
#[returns(GreetResponse)]
Greet,
#[returns(GoodbyeResponse)]
Goodbye,
}
```

The macro then defines the required code to document the responses in your code
properly so you can easily generate, for example, TypeScript types for your
contract clients.

## Definition

```rust filename="contract.rs" template="core"
Expand Down