-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'nightly' into feature/rename_address_trait
- Loading branch information
Showing
24 changed files
with
1,239 additions
and
317 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
module-system/module-implementations/examples/sov-vec-setter/Cargo.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
[package] | ||
name = "sov-vec-setter" | ||
description = "A Sovereign SDK example module for setting/reading vectors from state" | ||
authors = { workspace = true } | ||
edition = { workspace = true } | ||
homepage = { workspace = true } | ||
license = { workspace = true } | ||
repository = { workspace = true } | ||
rust-version = { workspace = true } | ||
version = { workspace = true } | ||
readme = "README.md" | ||
resolver = "2" | ||
publish = false | ||
|
||
[dev-dependencies] | ||
sov-modules-api = { path = "../../../sov-modules-api" } | ||
tempfile = { workspace = true } | ||
|
||
[dependencies] | ||
anyhow = { workspace = true } | ||
sov-modules-api = { path = "../../../sov-modules-api", default-features = false, features = ["macros"] } | ||
sov-state = { path = "../../../sov-state", default-features = false } | ||
sov-rollup-interface = { path = "../../../../rollup-interface" } | ||
schemars = { workspace = true, optional = true } | ||
serde = { workspace = true, optional = true } | ||
serde_json = { workspace = true, optional = true } | ||
thiserror = { workspace = true } | ||
borsh = { workspace = true, features = ["rc"] } | ||
jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } | ||
clap = { workspace = true, optional = true } | ||
|
||
[features] | ||
default = ["native"] | ||
serde = ["dep:serde", "dep:serde_json"] | ||
native = ["serde", "sov-modules-api/native", "dep:jsonrpsee", "dep:schemars", "dep:clap"] |
16 changes: 16 additions & 0 deletions
16
module-system/module-implementations/examples/sov-vec-setter/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# An example of a `SOV-MODULE` | ||
|
||
It demonstrates the following concepts: | ||
|
||
### 1. Module structure: | ||
|
||
- `lib.rs` contains `VecSetter` module definition and `sov_modules_api::Module` trait implementation for `VecSetter`. | ||
- `genesis.rs` contains the module initialization logic. | ||
- `call.rs` contains methods that change module state in response to `CallMessage`. | ||
- `query.rs` contains functions for querying the module state. | ||
|
||
### 2. Functionality: | ||
|
||
The `admin` (specified in the `VecSetter` genesis) can update a single `u32` value by creating `CallMessage::SetValue(new_value)` message. Anyone can query the module state by calling the `vecSetter_queryValue` endpoint. | ||
|
||
For implementation details, please check comments in the `genesis.rs, call.rs & query.rs`. |
151 changes: 151 additions & 0 deletions
151
module-system/module-implementations/examples/sov-vec-setter/src/call.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
use std::fmt::Debug; | ||
|
||
use anyhow::Result; | ||
#[cfg(feature = "native")] | ||
use sov_modules_api::macros::CliWalletArg; | ||
use sov_modules_api::CallResponse; | ||
use sov_state::WorkingSet; | ||
use thiserror::Error; | ||
|
||
use super::VecSetter; | ||
|
||
/// This enumeration represents the available call messages for interacting with the `sov-vec-setter` module. | ||
#[cfg_attr( | ||
feature = "native", | ||
derive(serde::Serialize), | ||
derive(serde::Deserialize), | ||
derive(CliWalletArg), | ||
derive(schemars::JsonSchema) | ||
)] | ||
#[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, PartialEq, Clone)] | ||
pub enum CallMessage { | ||
/// value to push | ||
PushValue(u32), | ||
/// value to set | ||
SetValue { | ||
/// index to set | ||
index: usize, | ||
/// value to set | ||
value: u32, | ||
}, | ||
/// values to set | ||
SetAllValues(Vec<u32>), | ||
/// Pop | ||
PopValue, | ||
} | ||
|
||
/// Example of a custom error. | ||
#[derive(Debug, Error)] | ||
enum SetValueError { | ||
#[error("Only admin can change the value")] | ||
WrongSender, | ||
} | ||
|
||
impl<C: sov_modules_api::Context> VecSetter<C> { | ||
/// Pushes `value` field to the `vector`, only admin is authorized to call this method. | ||
pub(crate) fn push_value( | ||
&self, | ||
new_value: u32, | ||
context: &C, | ||
working_set: &mut WorkingSet<C::Storage>, | ||
) -> Result<sov_modules_api::CallResponse> { | ||
// If admin is not then early return: | ||
let admin = self.admin.get_or_err(working_set)?; | ||
|
||
if &admin != context.sender() { | ||
// Here we use a custom error type. | ||
Err(SetValueError::WrongSender)?; | ||
} | ||
|
||
// This is how we push a new value to vector: | ||
self.vector.push(&new_value, working_set); | ||
|
||
let new_length = self.vector.len(working_set); | ||
|
||
working_set.add_event( | ||
"push", | ||
&format!("value_push: {new_value:?}, new length: {new_length:?}"), | ||
); | ||
|
||
Ok(CallResponse::default()) | ||
} | ||
|
||
/// Sets `value` field to the given index of `vector`, only admin is authorized to call this method. | ||
pub(crate) fn set_value( | ||
&self, | ||
index: usize, | ||
new_value: u32, | ||
context: &C, | ||
working_set: &mut WorkingSet<C::Storage>, | ||
) -> Result<sov_modules_api::CallResponse> { | ||
// If admin is not then early return: | ||
let admin = self.admin.get_or_err(working_set)?; | ||
|
||
if &admin != context.sender() { | ||
// Here we use a custom error type. | ||
Err(SetValueError::WrongSender)?; | ||
} | ||
|
||
// This is how we set a new value: | ||
self.vector.set(index, &new_value, working_set)?; | ||
|
||
working_set.add_event( | ||
"set", | ||
&format!("value_set: {new_value:?} for index: {index:?}"), | ||
); | ||
|
||
Ok(CallResponse::default()) | ||
} | ||
|
||
/// Sets `values` completely to the `vector`, only admin is authorized to call this method. | ||
pub(crate) fn set_all_values( | ||
&self, | ||
values: Vec<u32>, | ||
context: &C, | ||
working_set: &mut WorkingSet<C::Storage>, | ||
) -> Result<sov_modules_api::CallResponse> { | ||
// If admin is not then early return: | ||
let admin = self.admin.get_or_err(working_set)?; | ||
|
||
if &admin != context.sender() { | ||
// Here we use a custom error type. | ||
Err(SetValueError::WrongSender)?; | ||
} | ||
|
||
// This is how we set all the vector: | ||
self.vector.set_all(values, working_set); | ||
|
||
let new_length = self.vector.len(working_set); | ||
|
||
working_set.add_event("set_all", &format!("new length: {new_length:?}")); | ||
|
||
Ok(CallResponse::default()) | ||
} | ||
|
||
/// Pops last value from the `vector`, only admin is authorized to call this method. | ||
pub(crate) fn pop_value( | ||
&self, | ||
context: &C, | ||
working_set: &mut WorkingSet<C::Storage>, | ||
) -> Result<sov_modules_api::CallResponse> { | ||
// If admin is not then early return: | ||
let admin = self.admin.get_or_err(working_set)?; | ||
|
||
if &admin != context.sender() { | ||
// Here we use a custom error type. | ||
Err(SetValueError::WrongSender)?; | ||
} | ||
|
||
// This is how we pop last value value: | ||
let pop_value = self.vector.pop(working_set); | ||
|
||
let new_length = self.vector.len(working_set); | ||
|
||
working_set.add_event( | ||
"pop", | ||
&format!("value_pop: {pop_value:?}, new length: {new_length:?}"), | ||
); | ||
|
||
Ok(CallResponse::default()) | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
module-system/module-implementations/examples/sov-vec-setter/src/genesis.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
use anyhow::Result; | ||
use sov_state::WorkingSet; | ||
|
||
use super::VecSetter; | ||
|
||
impl<C: sov_modules_api::Context> VecSetter<C> { | ||
/// Initializes module with the `admin` role. | ||
pub(crate) fn init_module( | ||
&self, | ||
admin_config: &<Self as sov_modules_api::Module>::Config, | ||
working_set: &mut WorkingSet<C::Storage>, | ||
) -> Result<()> { | ||
self.admin.set(&admin_config.admin, working_set); | ||
Ok(()) | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
module-system/module-implementations/examples/sov-vec-setter/src/lib.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#![deny(missing_docs)] | ||
#![doc = include_str!("../README.md")] | ||
mod call; | ||
mod genesis; | ||
|
||
#[cfg(feature = "native")] | ||
mod query; | ||
|
||
pub use call::CallMessage; | ||
#[cfg(feature = "native")] | ||
pub use query::{VecSetterRpcImpl, VecSetterRpcServer}; | ||
use sov_modules_api::{Error, ModuleInfo}; | ||
use sov_state::WorkingSet; | ||
|
||
/// Initial configuration for sov-vec-setter module. | ||
pub struct VecSetterConfig<C: sov_modules_api::Context> { | ||
/// Admin of the module. | ||
pub admin: C::Address, | ||
} | ||
|
||
/// A new module: | ||
/// - Must derive `ModuleInfo` | ||
/// - Must contain `[address]` field | ||
/// - Can contain any number of ` #[state]` or `[module]` fields | ||
#[cfg_attr(feature = "native", derive(sov_modules_api::ModuleCallJsonSchema))] | ||
#[derive(ModuleInfo)] | ||
pub struct VecSetter<C: sov_modules_api::Context> { | ||
/// Address of the module. | ||
#[address] | ||
pub address: C::Address, | ||
|
||
/// Some vector kept in the state. | ||
#[state] | ||
pub vector: sov_state::StateVec<u32>, | ||
|
||
/// Holds the address of the admin user who is allowed to update the vector. | ||
#[state] | ||
pub admin: sov_state::StateValue<C::Address>, | ||
} | ||
|
||
impl<C: sov_modules_api::Context> sov_modules_api::Module for VecSetter<C> { | ||
type Context = C; | ||
|
||
type Config = VecSetterConfig<C>; | ||
|
||
type CallMessage = call::CallMessage; | ||
|
||
fn genesis( | ||
&self, | ||
config: &Self::Config, | ||
working_set: &mut WorkingSet<C::Storage>, | ||
) -> Result<(), Error> { | ||
// The initialization logic | ||
Ok(self.init_module(config, working_set)?) | ||
} | ||
|
||
fn call( | ||
&self, | ||
msg: Self::CallMessage, | ||
context: &Self::Context, | ||
working_set: &mut WorkingSet<C::Storage>, | ||
) -> Result<sov_modules_api::CallResponse, Error> { | ||
match msg { | ||
call::CallMessage::PushValue(new_value) => { | ||
Ok(self.push_value(new_value, context, working_set)?) | ||
} | ||
call::CallMessage::SetValue { index, value } => { | ||
Ok(self.set_value(index, value, context, working_set)?) | ||
} | ||
call::CallMessage::SetAllValues(values) => { | ||
Ok(self.set_all_values(values, context, working_set)?) | ||
} | ||
call::CallMessage::PopValue => Ok(self.pop_value(context, working_set)?), | ||
} | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
module-system/module-implementations/examples/sov-vec-setter/src/query.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#![allow(missing_docs)] | ||
use jsonrpsee::core::RpcResult; | ||
use sov_modules_api::macros::rpc_gen; | ||
use sov_state::WorkingSet; | ||
|
||
use super::VecSetter; | ||
|
||
/// Response returned from the vecSetter_queryVec endpoint. | ||
#[derive(serde::Serialize, serde::Deserialize, Debug, Eq, PartialEq, Clone)] | ||
pub struct QueryResponse { | ||
/// Value saved in the module's state vector. | ||
pub value: Option<u32>, | ||
} | ||
|
||
/// Response returned from the vecSetter_lenVec endpoint | ||
#[derive(serde::Serialize, serde::Deserialize, Debug, Eq, PartialEq, Clone)] | ||
pub struct LenResponse { | ||
/// Length of the vector | ||
pub value: usize, | ||
} | ||
|
||
#[rpc_gen(client, server, namespace = "vecSetter")] | ||
impl<C: sov_modules_api::Context> VecSetter<C> { | ||
/// Queries the state vector of the module. | ||
#[rpc_method(name = "queryVec")] | ||
pub fn query_vec( | ||
&self, | ||
index: usize, | ||
working_set: &mut WorkingSet<C::Storage>, | ||
) -> RpcResult<QueryResponse> { | ||
Ok(QueryResponse { | ||
value: self.vector.get(index, working_set), | ||
}) | ||
} | ||
/// Queries the length of the vector | ||
#[rpc_method(name = "lenVec")] | ||
pub fn len_vec(&self, working_set: &mut WorkingSet<C::Storage>) -> RpcResult<LenResponse> { | ||
Ok(LenResponse { | ||
value: self.vector.len(working_set), | ||
}) | ||
} | ||
} |
Oops, something went wrong.