Skip to content

Commit 4bace57

Browse files
committed
Added entrypoints descriptions.
1 parent 09ae30c commit 4bace57

File tree

8 files changed

+445
-7
lines changed

8 files changed

+445
-7
lines changed

.vitepress/config.mts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,19 @@ export default withMermaid({
1616
items: [
1717
{text: 'Introduction', link: '/guide/cosmwasm-core/introduction'},
1818
{text: 'Installation', link: '/guide/cosmwasm-core/installation'},
19-
{text: 'Entrypoints', link: '/guide/cosmwasm-core/entrypoints/entrypoints'},
2019
{
21-
text: 'Architecture',
20+
text: 'Entrypoints', link: '/guide/cosmwasm-core/entrypoints/entrypoints',
21+
items: [
22+
{text: 'Instantiate', link: '/guide/cosmwasm-core/entrypoints/instantiate'},
23+
{text: 'Execute', link: '/guide/cosmwasm-core/entrypoints/execute'},
24+
{text: 'Query', link: '/guide/cosmwasm-core/entrypoints/query'},
25+
{text: 'Migrate', link: '/guide/cosmwasm-core/entrypoints/migrate'},
26+
{text: 'Sudo', link: '/guide/cosmwasm-core/entrypoints/sudo'},
27+
{text: 'Reply', link: '/guide/cosmwasm-core/entrypoints/reply'},
28+
]
29+
},
30+
{
31+
text: 'Architecture', link: '/guide/cosmwasm-core/architecture/architecture',
2232
items: [
2333
{text: 'Gas', link: '/guide/cosmwasm-core/architecture/gas'},
2434
]
@@ -29,15 +39,23 @@ export default withMermaid({
2939
sidebar: [
3040
{text: 'Welcome', link: '/guide/welcome'},
3141
{
32-
text: 'CosmWasm Core',
33-
collapsed: true,
42+
text: 'CosmWasm Core', collapsed: true,
3443
items: [
3544
{text: 'Introduction', link: '/guide/cosmwasm-core/introduction'},
3645
{text: 'Installation', link: '/guide/cosmwasm-core/installation'},
37-
{text: 'Entrypoints', link: '/guide/cosmwasm-core/entrypoints/entrypoints'},
3846
{
39-
text: 'Architecture',
40-
collapsed: true,
47+
text: 'Entrypoints', collapsed: true, link: '/guide/cosmwasm-core/entrypoints/entrypoints',
48+
items: [
49+
{text: 'Instantiate', link: '/guide/cosmwasm-core/entrypoints/instantiate'},
50+
{text: 'Execute', link: '/guide/cosmwasm-core/entrypoints/execute'},
51+
{text: 'Query', link: '/guide/cosmwasm-core/entrypoints/query'},
52+
{text: 'Migrate', link: '/guide/cosmwasm-core/entrypoints/migrate'},
53+
{text: 'Sudo', link: '/guide/cosmwasm-core/entrypoints/sudo'},
54+
{text: 'Reply', link: '/guide/cosmwasm-core/entrypoints/reply'},
55+
]
56+
},
57+
{
58+
text: 'Architecture', collapsed: true, link: '/guide/cosmwasm-core/architecture/architecture',
4159
items: [
4260
{text: 'Gas', link: '/guide/cosmwasm-core/architecture/gas'},
4361
]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Architecture
2+
3+
(TBD)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Execute
2+
3+
Execute pretty much does what it says on the tin: it executes some routine in your contract
4+
after a remote (either another contract or some client) sent a message.
5+
6+
This function is called when someone wants you to, for example, increment a counter
7+
or add a user to a lottery. Anything that might modify the state of the contract.
8+
9+
## Definition
10+
11+
::: code-group
12+
13+
```Rust [contract.rs]
14+
#[cfg_attr(not(feature = "library"), entry_point)]
15+
pub fn execute(
16+
deps: DepsMut,
17+
env: Env,
18+
info: MessageInfo,
19+
msg: ExecuteMsg,
20+
) -> StdResult<Response> {
21+
// TODO: Put your "business" logic here.
22+
Ok(Response::new())
23+
}
24+
```
25+
26+
:::
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Instantiate
2+
3+
This is one of the most fundamental entrypoints. This entrypoint is called once during the contract lifecycle,
4+
right after an address has been assigned. It essentially is there to initialise the state of your contract
5+
(for example, initialising a counter in storage, etc.).
6+
7+
You can imagine it as the constructor of your contract.
8+
9+
::: tip :bulb: Tip
10+
11+
Note that this function is called for **each instance** of your contract that you decide to create,
12+
not one time ever.
13+
14+
To equate it to object-oriented programming, your contract is a **class**, and instantiate entrypoint
15+
is the **constructor**, and you can have **multiple instances** (objects) of the same class,
16+
and the constructor must be called exactly once for every one of these instances.
17+
18+
It is **not** a singleton class.
19+
20+
:::
21+
22+
## Definition
23+
24+
::: code-group
25+
26+
```Rust [contract.rs]
27+
#[cfg_attr(not(feature = "library"), entry_point)]
28+
pub fn instantiate(
29+
deps: DepsMut,
30+
env: Env,
31+
info: MessageInfo,
32+
msg: InstantiateMsg,
33+
) -> StdResult<Response> {
34+
// TODO: Put your initialization logic here.
35+
Ok(Response::new())
36+
}
37+
```
38+
39+
:::
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# Migrate
2+
3+
This is another special entrypoint. It is, just like [`instantiate`](./instantiate), not called frequently.
4+
5+
`migrate` is only called once you upload a new version of your contract to the chain
6+
and lets you run all the required changes to the storage.
7+
8+
Let's say your storage has the following layout, expressed as JSON for simplicity:
9+
10+
::: code-group
11+
12+
```JSON [structure.json]
13+
{
14+
"user_count": 205,
15+
"call_count": 543,
16+
"balance": 43
17+
}
18+
```
19+
20+
:::
21+
22+
23+
But then you notice "Hey! Why don't I nest all the counts into an own object? That way I don't have
24+
that redundant postfix, making the keys smaller".
25+
26+
So you go ahead and rework your logic to query the data from the following structure:
27+
28+
::: code-group
29+
30+
```JSON [structure.json]
31+
{
32+
"count": {
33+
"user": 205,
34+
"call": 543
35+
},
36+
"balance": 43
37+
}
38+
```
39+
40+
:::
41+
42+
But your storage on chain still stores the old format. You need to transform it somehow.
43+
44+
That's what you do in the `migrate` entrypoint. You transform the structure of the storage.
45+
46+
## Example
47+
48+
For CosmWasm `v2.2.0` and newer, the new migrate info feature can be used:
49+
50+
::: code-group
51+
52+
```Rust [contract.rs]
53+
const MIGRATE_VERSION: u64 = 2;
54+
55+
#[cfg_attr(not(feature = "library"), entry_point)]
56+
#[migrate_version(MIGRATE_VERSION)]
57+
pub fn migrate(deps: DepsMut, env: Env, msg: MigrateMsg, migrate_info: MigrateInfo) -> StdResult<Response> {
58+
match migrate_info.old_migrate_version {
59+
Some(1) | None => {
60+
// If the old on-chain version of the contract don't use the
61+
// `migrate_version` macro, there will be no version provided here
62+
// (it's the `None` variant).
63+
64+
// Load the old data
65+
let Some(old_data) = deps.storage.get(b"persisted_data") else {
66+
return Err(StdError::generic_err("Data not found"));
67+
};
68+
// Deserialize it from the old format
69+
let old_data: OldData = cosmwasm_std::from_json(&old_data)?;
70+
71+
// Transform it
72+
let new_data = transform(old_data);
73+
74+
// Serialize the new data
75+
let new_data = cosmwasm_std::to_json_vec(&new_data)?;
76+
// Store the new data
77+
deps.storage.set(b"persisted_data", &new_data);
78+
}
79+
Some(x) if x >= MIGRATE_VERSION => {
80+
// Assume we don't support downgrading the contract's state version
81+
// Note that `migrate_info.old_migrate_version` is never eq to `MIGRATE_VERSION`.
82+
return Err(StdError::generic_err("Downgrades are not supported for this contract."));
83+
}
84+
_ => {
85+
return Err(StdError::generic_err("Unexpected migrate version."));
86+
}
87+
}
88+
Ok(Response::default())
89+
}
90+
```
91+
92+
:::
93+
94+
For CosmWasm versions before `v2.2.0` the old method looks like this:
95+
96+
::: code-group
97+
98+
```Rust [contract.rs]
99+
const STATE_VERSION: &str = "v2";
100+
const CONTRACT_NAME: &str = "my_contract";
101+
102+
#[cfg_attr(not(feature = "library"), entry_point)]
103+
pub fn migrate(deps: DepsMut, env: Env, msg: MigrateMsg) -> StdResult<Response> {
104+
// Check if the state version is older than the current one and update it
105+
cw2::ensure_from_older_version(deps.storage, CONTRACT_NAME, STATE_VERSION)?;
106+
107+
// Load the old data
108+
let Some(old_data) = deps.storage.get(b"persisted_data") else {
109+
return Err(StdError::generic_err("Data not found"));
110+
};
111+
// Deserialize it from the old format
112+
let old_data: OldData = cosmwasm_std::from_json(&old_data)?;
113+
114+
// Transform it
115+
let new_data = transform(old_data);
116+
117+
// Serialize the new data
118+
let new_data = cosmwasm_std::to_json_vec(&new_data)?;
119+
// Store the new data
120+
deps.storage.set(b"persisted_data", &new_data);
121+
122+
Ok(Response::default())
123+
}
124+
```
125+
126+
:::
127+
128+
## Definition
129+
130+
To get the additional migrate info, the new signature can be used (CosmWasm `v2.2.0` and newer):
131+
132+
::: code-group
133+
134+
```Rust [contract.rs]
135+
const MIGRATE_VERSION: u64 = 2;
136+
137+
#[cfg_attr(not(feature = "library"), entry_point)]
138+
#[migrate_version(MIGRATE_VERSION)]
139+
pub fn migrate(
140+
deps: DepsMut,
141+
env: Env,
142+
msg: MigrateMsg,
143+
migrate_info: MigrateInfo) -> StdResult<Response> {
144+
// TODO: Put your migration logic here.
145+
Ok(Response::default())
146+
}
147+
```
148+
149+
:::
150+
151+
The legacy CosmWasm (before version `v2.2.0`) migrate entrypoint function signature is defined like this:
152+
153+
::: code-group
154+
155+
```Rust [contract.rs]
156+
#[cfg_attr(not(feature = "library"), entry_point)]
157+
pub fn migrate(
158+
deps: DepsMut,
159+
env: Env,
160+
msg: MigrateMsg) -> StdResult<Response> {
161+
// TODO: Put your migration logic here.
162+
Ok(Response::default())
163+
}
164+
```
165+
166+
:::
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Query
2+
3+
In the previous section we talked about the [`execute`](./execute) entrypoint.
4+
The `query` entrypoint is actually pretty similar to its sibling [`execute`](./execute),
5+
but with one key difference: the storage is only accessible **immutably**.
6+
7+
This means you can only _**read**_ from the storage but not _**write**_ to it.
8+
9+
## Properly defining a message
10+
11+
When defining a message for queries, you always return some value.
12+
To properly document these return values, you'll want to define them in your schema.
13+
14+
This is where the `cosmwasm_schema::QueryResponses` derive macro comes in.
15+
16+
::: code-group
17+
18+
```Rust [contract.rs]
19+
#[cw_serde]
20+
struct GreetResponse {
21+
message: String,
22+
}
23+
24+
#[cw_serde]
25+
struct GoodbyeResponse {
26+
message: String,
27+
}
28+
29+
#[cw_serde]
30+
#[derive(QueryResponses)]
31+
enum CustomQueryMsg {
32+
#[returns(GreetResponse)]
33+
Greet,
34+
#[returns(GoodbyeResponse)]
35+
Goodbye,
36+
}
37+
```
38+
39+
:::
40+
41+
The macro then defines the required code to document the responses in your code properly,
42+
so you can easily generate, for example, TypeScript types for your contract clients.
43+
44+
## Definition
45+
46+
::: code-group
47+
48+
```Rust [contract.rs]
49+
#[cfg_attr(not(feature = "library"), entry_point)]
50+
pub fn query(
51+
deps: Deps,
52+
env: Env,
53+
msg: QueryMsg,
54+
) -> StdResult<QueryResponse> {
55+
// TODO: Prepare the response here.
56+
Ok(QueryResponse::default())
57+
}
58+
```
59+
60+
:::

0 commit comments

Comments
 (0)