Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin' into ddepta/multitest/helhetsdok
Browse files Browse the repository at this point in the history
  • Loading branch information
DariuszDepta committed Dec 3, 2024
2 parents 56a6684 + 0c45210 commit 81dc4fc
Show file tree
Hide file tree
Showing 16 changed files with 890 additions and 230 deletions.
424 changes: 237 additions & 187 deletions docs-test-gen/Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion docs-test-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ phf = { version = "0.11.2", features = ["macros"] }
strum = { version = "0.26.3", features = ["derive"] }

[dev-dependencies]
sylvia = "*"
sylvia = { version = "*", features = ["cosmwasm_2_0"] }
cw2 = "*"
cw-storage-plus = { version = "*", features = ["macro"] }
cw-utils = "*"
cosmwasm-schema = "*"
cosmwasm-std = { version = "*", features = [
"stargate",
Expand Down
6 changes: 4 additions & 2 deletions docs-test-gen/templates/sylvia/cw_storage_contract.tpl
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#![allow(unexpected_cfgs, dead_code, unused_variables, unused_imports)]

use sylvia::cw_std::{Addr, entry_point, Reply, SubMsg, WasmMsg, to_json_binary, DepsMut, Empty, Env, IbcChannelOpenMsg, IbcChannelOpenResponse, Response, StdError, StdResult};
use sylvia::cw_std::{Addr, Binary, Coin, entry_point, Reply, SubMsg, WasmMsg, to_json_binary, DepsMut, Empty, Env, IbcChannelOpenMsg, IbcChannelOpenResponse, Response, StdError, StdResult, SubMsgResult};
use sylvia::{contract, entry_points, interface};
use sylvia::types::{Remote, InstantiateCtx, QueryCtx, ExecCtx, ReplyCtx, SudoCtx, MigrateCtx};
use sylvia::types::Remote;
use sylvia::ctx::{InstantiateCtx, QueryCtx, ExecCtx, ReplyCtx, SudoCtx, MigrateCtx};
use sylvia::cw_schema::cw_serde;
use cw_utils::MsgInstantiateContractResponse;
use cw_storage_plus::Item;

pub mod external_contract {
Expand Down
8 changes: 5 additions & 3 deletions docs-test-gen/templates/sylvia/empty.tpl
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#![allow(unexpected_cfgs, dead_code, unused_variables, unused_imports)]

use sylvia::cw_std::{Addr, entry_point, Reply, SubMsg, WasmMsg, to_json_binary, DepsMut, Empty, Env, IbcChannelOpenMsg, IbcChannelOpenResponse, Response, StdError, StdResult};
use sylvia::cw_std::{Addr, Binary, Coin, entry_point, Reply, SubMsg, WasmMsg, to_json_binary, DepsMut, Empty, Env, IbcChannelOpenMsg, IbcChannelOpenResponse, Response, StdError, StdResult, SubMsgResult};
use sylvia::{contract, entry_points, interface};
use sylvia::types::{Remote, InstantiateCtx, QueryCtx, ExecCtx, ReplyCtx, SudoCtx, MigrateCtx};
use sylvia::types::Remote;
use sylvia::ctx::{InstantiateCtx, QueryCtx, ExecCtx, ReplyCtx, SudoCtx, MigrateCtx};
use sylvia::cw_schema::cw_serde;
use cw_utils::MsgInstantiateContractResponse;
use cw_storey::CwStorage;
use external_contract::ExternalContract;

pub mod external_contract {
use sylvia::contract;
use sylvia::types::{InstantiateCtx, ExecCtx};
use sylvia::ctx::{InstantiateCtx, ExecCtx};
use sylvia::cw_std::{Response, StdResult};

pub struct ExternalContract;
Expand Down
6 changes: 4 additions & 2 deletions docs-test-gen/templates/sylvia/storey_contract.tpl
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#![allow(unexpected_cfgs, dead_code, unused_variables, unused_imports)]

use sylvia::cw_std::{Addr, entry_point, Reply, SubMsg, WasmMsg, to_json_binary, DepsMut, Empty, Env, IbcChannelOpenMsg, IbcChannelOpenResponse, Response, StdError, StdResult};
use sylvia::cw_std::{Addr, Binary, Coin, entry_point, Reply, SubMsg, WasmMsg, to_json_binary, DepsMut, Empty, Env, IbcChannelOpenMsg, IbcChannelOpenResponse, Response, StdError, StdResult, SubMsgResult};
use sylvia::{contract, entry_points, interface};
use sylvia::types::{Remote, InstantiateCtx, QueryCtx, ExecCtx, ReplyCtx, SudoCtx, MigrateCtx};
use sylvia::types::Remote;
use sylvia::ctx::{InstantiateCtx, QueryCtx, ExecCtx, ReplyCtx, SudoCtx, MigrateCtx};
use sylvia::cw_schema::cw_serde;
use cw_utils::MsgInstantiateContractResponse;
use cw_storey::CwStorage;
use cw_storey::containers::Item;

Expand Down
58 changes: 58 additions & 0 deletions src/pages/ibc/diy-protocol/packet-lifecycle.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ using the `IbcMsg::WriteAcknowledgement` message.
Not acknowledging can lead to problems for the sender of the packet.
</Callout>

<Tabs items={['StoragePlus', 'Storey']}>
<Tabs.Tab>

```rust filename="ibc.rs" template="core"
use cw_storage_plus::Map;

Expand Down Expand Up @@ -214,6 +217,61 @@ pub fn async_ack(
const ACK_LATER: Map<&(u64, String), String> = Map::new("ack_later");
```

</Tabs.Tab>
<Tabs.Tab>

```rust filename="ibc.rs" template="core"
use cw_storey::containers::{Item, Map};
use cw_storey::CwStorage;

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn ibc_packet_receive(
deps: DepsMut,
_env: Env,
msg: IbcPacketReceiveMsg,
) -> StdResult<IbcReceiveResponse> {
// save the data we need for the async acknowledgement in contract state
// note: we are just saving a String here, but you can save any information
// you need for the acknowledgement later
ACK_LATER.access(&mut CwStorage(deps.storage))
.entry_mut(&msg.packet.sequence)
.entry_mut(&msg.packet.dest.channel_id)
.set(&"ack str".to_string())?;

// return without an acknowledgement
Ok(IbcReceiveResponse::without_ack())
}

/// Called somewhere in the contract to acknowledge the packet
pub fn async_ack(
deps: DepsMut,
env: Env,
info: MessageInfo,
packet_sequence: u64,
channel_id: String,
) -> StdResult<Response> {
// load data from contract state
let ack_str = ACK_LATER.access(&CwStorage(deps.storage))
.entry(&packet_sequence)
.entry(&channel_id)
.try_get()
.map_err(|_| StdError::generic_err("error accessing ACK_LATER"))?;

// send the acknowledgement
Ok(Response::new().add_message(IbcMsg::WriteAcknowledgement {
packet_sequence,
channel_id,
ack: IbcAcknowledgement::new(StdAck::success(ack_str.as_bytes())),
}))
}

const ACK_LATER_IX: u8 = 0;
const ACK_LATER: Map<u64, Map<String, Item<String>>> = Map::new(ACK_LATER_IX);
```

</Tabs.Tab>
</Tabs>

## Receiving a packet acknowledgement

After the packet has been received and acknowledged by chain B, the relayer will pass the
Expand Down
35 changes: 32 additions & 3 deletions src/pages/storey/containers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ For most of your needs, you can likely do what you need to with the built-in con
For more advanced use cases, you can build your own containers as described in the
[_Implementing new containers_](container-impl) section.

# Namespace
## Namespace

To construct a container, you need to provide a single byte. This byte is used to distinguish
between different "root" containers in the same storage space.
Expand All @@ -43,7 +43,33 @@ container.

To avoid key collisions, you must provide a different byte to each container.

# Composition
## Accessor

Every container has a corresponding "accessor" type that is used to perform all read/write
operations.

To get the accessor of a top-level container, the [`access` method] must be called. It takes a reference
to a storage backend.

```rust template="storage"
use cw_storey::containers::Item;
use cw_storey::CwStorage;

let item: Item<u32> = Item::new(0);

item.access(&mut CwStorage(&mut storage))
.set(&42)
.unwrap();

assert_eq!(
item.access(&CwStorage(&storage))
.get()
.unwrap(),
Some(42)
);
```

## Composition

Some containers can be composed together to create more complex data structures. Right now, the only
built-in container that supports composition is the `Map` container.
Expand Down Expand Up @@ -99,7 +125,7 @@ assert_eq!(
It's possible to define custom containers that enable composition similar to maps. If done properly,
they can be mixed with any other containers, including built-in ones.

# Encoding
## Encoding

Types like `Item` or `Column` need a way to encode values in a binary store. If you're using the
`Item` and `Column` types from `cw-storey`, the [MessagePack](https://msgpack.org/) format is used.
Expand All @@ -108,3 +134,6 @@ This is a binary encoding that should generally be a storage performance improve
If you need to use a different encoding, you can instead import the `Item`/`Column` type from the
`storey` crate and specify an alternative encoding. A guide to implementing your encoding can be
found in the [_Alternative encodings_](encodings) section.

[`access` method]:
https://docs.rs/cw-storey/latest/cw_storey/containers/type.Item.html#method.access
116 changes: 116 additions & 0 deletions src/pages/storey/containers/item.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,119 @@ tags: ["storey", "containers"]
import { Callout } from "nextra/components";

# Item

An [`Item`] is the simplest container. It stores a single value at a specific key.

An `Item` that's never been [`set`] is empty, and will return `None` upon a [`get`].

<Callout>
For a more in-depth look at the `Item` container, check out the [API documentation].
</Callout>

## Usage examples

### Saving an admin address

Quite often it is necessary for a contract to keep track of who is its "owner" or "admin". In order
to do that, we can store an admin address (usually in instantiation). Later, the address of the
caller can be matched against this address in execution endpoints.

Here's how to store and manipulate an admin address, or any other simple data.

```rust template="storage" showLineNumbers {5,9-12,14-16,19}
use cw_storey::containers::Item;
use cw_storey::CwStorage;

const ADMIN_IX: u8 = 0;

let admin: Item<String> = Item::new(ADMIN_IX);
let mut cw_storage = CwStorage(&mut storage);

assert_eq!(
admin.access(&cw_storage).get().unwrap(),
None,
);

admin.access(&mut cw_storage)
.set(&String::from("some_address"))
.unwrap();

assert_eq!(
admin.access(&cw_storage).get().unwrap(),
Some(String::from("some_address")),
);
```

- _line 5:_ Here we construct the `Item` facade. The constructor takes a key, which is the key the
data will be stored at in the underlying storage backend. See also
[_Containers - Namespace_](.#namespace).
- _lines 9-12_: This assertion is just to show you the `Item` is empty (`Option::None`) before it's
initialized.
- _lines 14-16_: Here we commit a value to storage.
- _line 19_: Here we retrieve the value from storage.

### Maintaining a config structure

It's also common to save a whole struct in an `Item`, with a variety of data. Often the struct
represents a contract's "config".

```rust template="storage" showLineNumbers {6}
use cw_storey::containers::Item;
use cw_storey::CwStorage;

const CFG_IX: u8 = 0;

#[cw_serde]
struct Config {
pub admin: String,
pub interest_rate: Decimal,
}

let item: Item<Config> = Item::new(CFG_IX);
let mut cw_storage = CwStorage(&mut storage);
let mut access = item.access(&mut cw_storage);

let cfg = Config {
admin: "some_address".to_string(),
interest_rate: Decimal::percent(5),
};

access.set(&cfg).unwrap();
assert_eq!(access.get().unwrap(), Some(cfg));
```

Note the highlighted line. The struct must be encodable. For _CosmWasm_ contracts this generally
means it implements `serde::{Serialize, Deserialize}`. The best idiomatic way to achieve that is by
using the `cosmwasm_schema::cw_serde` macro we provide.

### Default values

Sometimes you might like to read a value, but expect to receive a default if it's never been
initialized. This is a common pattern for counters or other numeric values.

```rust template="storage" showLineNumbers {10}
use cw_storey::containers::Item;
use cw_storey::CwStorage;

const COUNTER_IX: u8 = 0;

let counter: Item<u32> = Item::new(COUNTER_IX);
let mut cw_storage = CwStorage(&mut storage);
let mut access = counter.access(&mut cw_storage);

let mut total = access.get().unwrap().unwrap_or(0);

assert_eq!(total, 0);
total += 1;

access.set(&total).unwrap();
```

There's no magic here, just
[`Option::unwrap_or`](https://doc.rust-lang.org/std/option/enum.Option.html#method.unwrap_or) at the
highlighted line. This is less a feature of the framework and more a pattern you might find useful.

[`Item`]: https://docs.rs/cw-storey/latest/cw_storey/containers/type.Item.html
[API documentation]: https://docs.rs/cw-storey/latest/cw_storey/containers/type.Item.html
[`get`]: https://docs.rs/storey/latest/storey/containers/struct.ItemAccess.html#method.get
[`set`]: https://docs.rs/storey/latest/storey/containers/struct.ItemAccess.html#method.set
Loading

0 comments on commit 81dc4fc

Please sign in to comment.