From 426df27d3084ce140095d55bfd146f85bafc0038 Mon Sep 17 00:00:00 2001 From: Tomasz Kurcz Date: Thu, 8 Aug 2024 19:41:51 +0200 Subject: [PATCH 1/4] storage-plus: document SnapshotItem --- docs-test-gen/templates/storage.tpl | 5 + src/pages/cw-storage-plus/_meta.json | 1 - .../cw-storage-plus/containers/_meta.json | 4 +- .../containers/snapshot-item.mdx | 107 ++++++++++++++++++ 4 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 src/pages/cw-storage-plus/containers/snapshot-item.mdx diff --git a/docs-test-gen/templates/storage.tpl b/docs-test-gen/templates/storage.tpl index 5c3600fa..c719e969 100644 --- a/docs-test-gen/templates/storage.tpl +++ b/docs-test-gen/templates/storage.tpl @@ -61,10 +61,15 @@ mod users { } } +fn advance_height(env: &mut Env, blocks: u64) { + env.block.height += blocks; +} + #[test] fn doctest() { #[allow(unused_variables, unused_mut)] let mut storage = cosmwasm_std::testing::MockStorage::new(); + let mut env = cosmwasm_std::testing::mock_env(); let users = cw_storage_plus::IndexedMap::::new( "uu", diff --git a/src/pages/cw-storage-plus/_meta.json b/src/pages/cw-storage-plus/_meta.json index 7cbef22b..90aa872b 100644 --- a/src/pages/cw-storage-plus/_meta.json +++ b/src/pages/cw-storage-plus/_meta.json @@ -1,6 +1,5 @@ { "basics": "Basics", "containers": "Containers", - "snapshots": "Snapshots", "multi-indexes": "Multi index collections" } diff --git a/src/pages/cw-storage-plus/containers/_meta.json b/src/pages/cw-storage-plus/containers/_meta.json index f87bc0d8..bb682c05 100644 --- a/src/pages/cw-storage-plus/containers/_meta.json +++ b/src/pages/cw-storage-plus/containers/_meta.json @@ -2,5 +2,7 @@ "item": "Item", "map": "Map", "deque": "Deque", - "indexed-map": "IndexedMap" + "indexed-map": "IndexedMap", + "snapshot-item": "SnapshotItem", + "snapshot-map": "SnapshotMap" } diff --git a/src/pages/cw-storage-plus/containers/snapshot-item.mdx b/src/pages/cw-storage-plus/containers/snapshot-item.mdx new file mode 100644 index 00000000..b950d315 --- /dev/null +++ b/src/pages/cw-storage-plus/containers/snapshot-item.mdx @@ -0,0 +1,107 @@ +--- +tags: ["storage-plus", "containers"] +--- + +import { Callout } from "nextra/components"; + +# SnapshotItem + +A `SnapshotItem` is a container that contains a single value that is potentially stored in some +storage identified by a unique key - just like an [`Item`]. It's worth familiarizing yourself with +the `Item` type first, as everything we talked about there is applicable to `SnapshotItem`. + +On top of that, `SnapshotItem` makes it a little simpler to maintain a history of values at various +block heights. This involves saving "checkpoints" at some points in time - just how that is done is +decided by the [`Strategy`] type passed to the `SnapshotItem` constructor. + +# Strategy + +There are currently 3 built-in strategies, although in the future this might be open to extension. + +- `EveryBlock` - a checkpoint is (conceptually) added at the beginning of every block, and + historical data is available for any height +- `Never` - there's never a checkpoint saved, and the `SnapshotItem` is no different from a regular + `Item` in terms of features. Any call to [`may_load_at_height`] will return `StdError::NotFound` +- `Selected` - the [`add_checkpoint`] method has to be called manually to add a checkpoint at the + given height. Keep in mind that when calling [`may_load_at_height`] later, the height has to be + the same as the one passed to [`add_checkpoint`]. If you try to load a value at a height when no + checkpoint was saved, the method will return [`StdError::NotFound`]. + +## Usage examples + +### Maintaining a price history + + + The constructor of `SnapshotItem` takes 3 "namespace" arguments: - the main namespace, similar to + the `Item` constructor - two additional unique namespaces, which are used to store the changelog + metadata + + +```rust template="storage" +use cw_storage_plus::{SnapshotItem, Strategy}; + +let price: SnapshotItem = SnapshotItem::new("p", "p1", "p2", Strategy::EveryBlock); + +price + .save(&mut storage, &Decimal::percent(81), env.block.height) + .unwrap(); + +advance_height(&mut env, 50); // fast forward 50 blocks + +price + .save(&mut storage, &Decimal::percent(92), env.block.height) + .unwrap(); + +// Before/at the first save, the price was unknown (uninitialized state) +assert_eq!( + price + .may_load_at_height(&storage, env.block.height - 60) + .unwrap(), + None +); +assert_eq!( + price + .may_load_at_height(&storage, env.block.height - 50) + .unwrap(), + None +); + +// Before/at the current block, the price was 81% +assert_eq!( + price + .may_load_at_height(&storage, env.block.height - 49) + .unwrap(), + Some(Decimal::percent(81)) +); +assert_eq!( + price + .may_load_at_height(&storage, env.block.height) + .unwrap(), + Some(Decimal::percent(81)) +); + +// After the current block, the price will come up as 92% +assert_eq!( + price + .may_load_at_height(&storage, env.block.height + 1) + .unwrap(), + Some(Decimal::percent(92)) +); +assert_eq!( + price + .may_load_at_height(&storage, env.block.height + 50) + .unwrap(), + Some(Decimal::percent(92)) +); +``` + +[`Item`]: item +[`Strategy`]: https://docs.rs/cw-storage-plus/latest/cw_storage_plus/enum.Strategy.html +[`add_checkpoint`]: + https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.SnapshotItem.html#method.add_checkpoint +[`may_load_at_height`]: + https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.SnapshotItem.html#method.may_load_at_height +[`StdError::NotFound`]: + https://docs.rs/cosmwasm-std/latest/cosmwasm_std/enum.StdError.html#variant.NotFound +[`serde`]: https://serde.rs/ +[API docs]: https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.SnapshotItem.html From c6832219b364ae766995c581b889f265a8dafe9c Mon Sep 17 00:00:00 2001 From: Tomasz Kurcz Date: Tue, 13 Aug 2024 19:08:16 +0200 Subject: [PATCH 2/4] storage-plus: don't describe prices using % in comments --- src/pages/cw-storage-plus/containers/snapshot-item.mdx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pages/cw-storage-plus/containers/snapshot-item.mdx b/src/pages/cw-storage-plus/containers/snapshot-item.mdx index b950d315..ba4c9f1d 100644 --- a/src/pages/cw-storage-plus/containers/snapshot-item.mdx +++ b/src/pages/cw-storage-plus/containers/snapshot-item.mdx @@ -37,6 +37,8 @@ There are currently 3 built-in strategies, although in the future this might be metadata +Let's say we want to keep a history of prices for a specific trading pair. + ```rust template="storage" use cw_storage_plus::{SnapshotItem, Strategy}; @@ -66,7 +68,7 @@ assert_eq!( None ); -// Before/at the current block, the price was 81% +// Before/at the current block, the price was 0.81 assert_eq!( price .may_load_at_height(&storage, env.block.height - 49) @@ -80,7 +82,7 @@ assert_eq!( Some(Decimal::percent(81)) ); -// After the current block, the price will come up as 92% +// After the current block, the price will come up as 0.92 assert_eq!( price .may_load_at_height(&storage, env.block.height + 1) From 5055cb2c0c00c45dbd8bcd7a92c39190b6e10d1f Mon Sep 17 00:00:00 2001 From: Tomasz Kurcz Date: Thu, 8 Aug 2024 20:06:54 +0200 Subject: [PATCH 3/4] storage-plus: document SnapshotMap --- .../containers/snapshot-map.mdx | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 src/pages/cw-storage-plus/containers/snapshot-map.mdx diff --git a/src/pages/cw-storage-plus/containers/snapshot-map.mdx b/src/pages/cw-storage-plus/containers/snapshot-map.mdx new file mode 100644 index 00000000..b478270b --- /dev/null +++ b/src/pages/cw-storage-plus/containers/snapshot-map.mdx @@ -0,0 +1,106 @@ +--- +tags: ["storage-plus", "containers"] +--- + +import { Callout } from "nextra/components"; + +# SnapshotMap + +A `SnapshotMap` is a key-value store like [`Map`]. It's worth familiarizing yourself with the `Map` +type first, as everything we talked about there is applicable to `SnapshotMap`. + +On top of that, `SnapshotMap` makes it a little simpler to maintain a history of values at various +block heights. This involves saving "checkpoints" at some points in time - just how that is done is +decided by the [`Strategy`] type passed to the `SnapshotMap` constructor. + +# Strategy + +There are currently 3 built-in strategies, although in the future this might be open to extension. + +- `EveryBlock` - a checkpoint is (conceptually) added at the beginning of every block, and + historical data is available for any height +- `Never` - there's never a checkpoint saved, and the `SnapshotMap` is no different from a regular + `Map` in terms of features. Any call to [`may_load_at_height`] will return `StdError::NotFound` +- `Selected` - the [`add_checkpoint`] method has to be called manually to add a checkpoint at the + given height. Keep in mind that when calling [`may_load_at_height`] later, the height has to be + the same as the one passed to [`add_checkpoint`]. If you try to load a value at a height when no + checkpoint was saved, the method will return [`StdError::NotFound`]. + +## Usage examples + +### Maintaining price histories for various trading pairs + + + The constructor of `SnapshotMap` takes 3 "namespace" arguments: - the main namespace, similar to + the `Map` constructor - two additional unique namespaces, which are used to store the changelog + metadata + + +```rust template="storage" +use cw_storage_plus::{SnapshotMap, Strategy}; + +let price: SnapshotMap<(&str, &str), Decimal> = SnapshotMap::new("p", "p1", "p2", Strategy::EveryBlock); + +price + .save(&mut storage, ("OSMO", "ATOM"), &Decimal::percent(81), env.block.height) + .unwrap(); + +advance_height(&mut env, 50); // fast forward 50 blocks + +price + .save(&mut storage, ("OSMO", "ATOM"), &Decimal::percent(92), env.block.height) + .unwrap(); + +// Before/at the first save, the price was unknown (uninitialized state) +assert_eq!( + price + .may_load_at_height(&storage, ("OSMO", "ATOM"), env.block.height - 60) + .unwrap(), + None +); +assert_eq!( + price + .may_load_at_height(&storage, ("OSMO", "ATOM"), env.block.height - 50) + .unwrap(), + None +); + +// Before/at the current block, the price was 81% +assert_eq!( + price + .may_load_at_height(&storage, ("OSMO", "ATOM"), env.block.height - 49) + .unwrap(), + Some(Decimal::percent(81)) +); +assert_eq!( + price + .may_load_at_height(&storage, ("OSMO", "ATOM"), env.block.height) + .unwrap(), + Some(Decimal::percent(81)) +); + +// After the current block, the price will come up as 92% +assert_eq!( + price + .may_load_at_height(&storage, ("OSMO", "ATOM"), env.block.height + 1) + .unwrap(), + Some(Decimal::percent(92)) +); +assert_eq!( + price + .may_load_at_height(&storage, ("OSMO", "ATOM"), env.block.height + 50) + .unwrap(), + Some(Decimal::percent(92)) +); +``` + +[`Map`]: map +[`Strategy`]: https://docs.rs/cw-storage-plus/latest/cw_storage_plus/enum.Strategy.html +[`add_checkpoint`]: + https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.SnapshotMap.html#method.add_checkpoint +[`may_load_at_height`]: + https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.SnapshotMap.html#method.may_load_at_height +[`StdError::NotFound`]: + https://docs.rs/cosmwasm-std/latest/cosmwasm_std/enum.StdError.html#variant.NotFound +[`serde`]: https://serde.rs/ +[API docs]: https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.SnapshotMap.html From 4b23901ff7acfab4be784fb6bef222dde5a24e3d Mon Sep 17 00:00:00 2001 From: Tomasz Kurcz Date: Tue, 13 Aug 2024 19:12:48 +0200 Subject: [PATCH 4/4] storage-plus: don't describe prices using % in comments --- src/pages/cw-storage-plus/containers/snapshot-map.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/cw-storage-plus/containers/snapshot-map.mdx b/src/pages/cw-storage-plus/containers/snapshot-map.mdx index b478270b..03bd13d7 100644 --- a/src/pages/cw-storage-plus/containers/snapshot-map.mdx +++ b/src/pages/cw-storage-plus/containers/snapshot-map.mdx @@ -65,7 +65,7 @@ assert_eq!( None ); -// Before/at the current block, the price was 81% +// Before/at the current block, the price was 0.81 assert_eq!( price .may_load_at_height(&storage, ("OSMO", "ATOM"), env.block.height - 49) @@ -79,7 +79,7 @@ assert_eq!( Some(Decimal::percent(81)) ); -// After the current block, the price will come up as 92% +// After the current block, the price will come up as 0.92 assert_eq!( price .may_load_at_height(&storage, ("OSMO", "ATOM"), env.block.height + 1)