diff --git a/Cargo.lock b/Cargo.lock index 8e2b584dd..f510b5531 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2007,6 +2007,7 @@ dependencies = [ "reth-primitives", "serde", "serde_json", + "simple-nft-module", "sov-accounts", "sov-bank", "sov-blob-storage", @@ -7977,8 +7978,11 @@ version = "0.2.0" dependencies = [ "anyhow", "borsh", + "clap 4.4.6", "jsonrpsee 0.18.2", + "schemars", "serde", + "serde_json", "simple-nft-module", "sov-modules-api", "sov-rollup-interface", diff --git a/examples/demo-prover/benches/prover_bench.rs b/examples/demo-prover/benches/prover_bench.rs index da19fb691..cb3afe448 100644 --- a/examples/demo-prover/benches/prover_bench.rs +++ b/examples/demo-prover/benches/prover_bench.rs @@ -31,6 +31,7 @@ const GENESIS_PATHS: GenesisPaths<&str> = GenesisPaths { value_setter_genesis_path: "../test-data/genesis/demo-tests/value_setter.json", accounts_genesis_path: "../test-data/genesis/demo-tests/accounts.json", chain_state_genesis_path: "../test-data/genesis/demo-tests/chain_state.json", + nft_path: "../test-data/genesis/demo-tests/nft.json", #[cfg(feature = "experimental")] evm_genesis_path: "../test-data/genesis/demo-tests/evm.json", }; diff --git a/examples/demo-prover/methods/guest-celestia/Cargo.lock b/examples/demo-prover/methods/guest-celestia/Cargo.lock index da5807d78..a600d34b4 100644 --- a/examples/demo-prover/methods/guest-celestia/Cargo.lock +++ b/examples/demo-prover/methods/guest-celestia/Cargo.lock @@ -306,6 +306,7 @@ dependencies = [ "borsh", "hex", "serde", + "simple-nft-module", "sov-accounts", "sov-bank", "sov-blob-storage", @@ -1270,6 +1271,17 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +[[package]] +name = "simple-nft-module" +version = "0.2.0" +dependencies = [ + "anyhow", + "borsh", + "serde", + "sov-modules-api", + "sov-state", +] + [[package]] name = "sov-accounts" version = "0.2.0" diff --git a/examples/demo-prover/methods/guest-mock/Cargo.lock b/examples/demo-prover/methods/guest-mock/Cargo.lock index db5de049c..b61772d6d 100644 --- a/examples/demo-prover/methods/guest-mock/Cargo.lock +++ b/examples/demo-prover/methods/guest-mock/Cargo.lock @@ -257,6 +257,7 @@ dependencies = [ "borsh", "hex", "serde", + "simple-nft-module", "sov-accounts", "sov-bank", "sov-blob-storage", @@ -856,6 +857,17 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +[[package]] +name = "simple-nft-module" +version = "0.2.0" +dependencies = [ + "anyhow", + "borsh", + "serde", + "sov-modules-api", + "sov-state", +] + [[package]] name = "sov-accounts" version = "0.2.0" diff --git a/examples/demo-prover/src/main.rs b/examples/demo-prover/src/main.rs index 80725a834..b38bf6d36 100644 --- a/examples/demo-prover/src/main.rs +++ b/examples/demo-prover/src/main.rs @@ -14,6 +14,7 @@ const GENESIS_PATHS: GenesisPaths<&str> = GenesisPaths { value_setter_genesis_path: "../test-data/genesis/demo-tests/value_setter.json", accounts_genesis_path: "../test-data/genesis/demo-tests/accounts.json", chain_state_genesis_path: "../test-data/genesis/demo-tests/chain_state.json", + nft_path: "../test-data/genesis/demo-tests/nft.json", #[cfg(feature = "experimental")] evm_genesis_path: "../test-data/genesis/demo-tests/evm.json", }; diff --git a/examples/demo-rollup/benches/rollup_bench.rs b/examples/demo-rollup/benches/rollup_bench.rs index 243db48fb..c5d549982 100644 --- a/examples/demo-rollup/benches/rollup_bench.rs +++ b/examples/demo-rollup/benches/rollup_bench.rs @@ -25,6 +25,7 @@ const TEST_GENESIS_PATHS: GenesisPaths<&str> = GenesisPaths { value_setter_genesis_path: "../test-data/genesis/integration-tests/value_setter.json", accounts_genesis_path: "../test-data/genesis/integration-tests/accounts.json", chain_state_genesis_path: "../test-data/genesis/integration-tests/chain_state.json", + nft_path: "../test-data/genesis/integration-tests/nft.json", #[cfg(feature = "experimental")] evm_genesis_path: "../test-data/genesis/integration-tests/evm.json", }; diff --git a/examples/demo-rollup/benches/rollup_coarse_measure.rs b/examples/demo-rollup/benches/rollup_coarse_measure.rs index 05c6a3ea5..41289f731 100644 --- a/examples/demo-rollup/benches/rollup_coarse_measure.rs +++ b/examples/demo-rollup/benches/rollup_coarse_measure.rs @@ -31,6 +31,7 @@ const TEST_GENESIS_PATHS: GenesisPaths<&str> = GenesisPaths { value_setter_genesis_path: "../test-data/genesis/integration-tests/value_setter.json", accounts_genesis_path: "../test-data/genesis/integration-tests/accounts.json", chain_state_genesis_path: "../test-data/genesis/integration-tests/chain_state.json", + nft_path: "../test-data/genesis/integration-tests/nft.json", #[cfg(feature = "experimental")] evm_genesis_path: "../test-data/genesis/integration-tests/evm.json", }; diff --git a/examples/demo-rollup/src/main.rs b/examples/demo-rollup/src/main.rs index b354d3fc8..ff13e498d 100644 --- a/examples/demo-rollup/src/main.rs +++ b/examples/demo-rollup/src/main.rs @@ -13,6 +13,7 @@ const DEMO_GENESIS_PATHS: GenesisPaths<&str> = GenesisPaths { value_setter_genesis_path: "../test-data/genesis/demo-tests/value_setter.json", accounts_genesis_path: "../test-data/genesis/demo-tests/accounts.json", chain_state_genesis_path: "../test-data/genesis/demo-tests/chain_state.json", + nft_path: "../test-data/genesis/demo-tests/nft.json", #[cfg(feature = "experimental")] evm_genesis_path: "../test-data/genesis/demo-tests/evm.json", }; @@ -23,6 +24,7 @@ const TEST_GENESIS_PATHS: GenesisPaths<&str> = GenesisPaths { value_setter_genesis_path: "../test-data/genesis/integration-tests/value_setter.json", accounts_genesis_path: "../test-data/genesis/integration-tests/accounts.json", chain_state_genesis_path: "../test-data/genesis/integration-tests/chain_state.json", + nft_path: "../test-data/genesis/integration-tests/nft.json", #[cfg(feature = "experimental")] evm_genesis_path: "../test-data/genesis/integration-tests/evm.json", }; diff --git a/examples/demo-rollup/tests/bank/mod.rs b/examples/demo-rollup/tests/bank/mod.rs index 0d13ffc08..3dd6ef5af 100644 --- a/examples/demo-rollup/tests/bank/mod.rs +++ b/examples/demo-rollup/tests/bank/mod.rs @@ -25,6 +25,7 @@ const TEST_GENESIS_PATHS: GenesisPaths<&str> = GenesisPaths { value_setter_genesis_path: "../test-data/genesis/integration-tests/value_setter.json", accounts_genesis_path: "../test-data/genesis/integration-tests/accounts.json", chain_state_genesis_path: "../test-data/genesis/integration-tests/chain_state.json", + nft_path: "../test-data/genesis/integration-tests/nft.json", #[cfg(feature = "experimental")] evm_genesis_path: "../test-data/genesis/integration-tests/evm.json", }; diff --git a/examples/demo-rollup/tests/evm/mod.rs b/examples/demo-rollup/tests/evm/mod.rs index 4c503f17c..7595d0a2c 100644 --- a/examples/demo-rollup/tests/evm/mod.rs +++ b/examples/demo-rollup/tests/evm/mod.rs @@ -29,6 +29,7 @@ const TEST_GENESIS_PATHS: GenesisPaths<&str> = GenesisPaths { value_setter_genesis_path: "../test-data/genesis/integration-tests/value_setter.json", accounts_genesis_path: "../test-data/genesis/integration-tests/accounts.json", chain_state_genesis_path: "../test-data/genesis/integration-tests/chain_state.json", + nft_path: "../test-data/genesis/integration-tests/nft.json", #[cfg(feature = "experimental")] evm_genesis_path: "../test-data/genesis/integration-tests/evm.json", }; diff --git a/examples/demo-stf/Cargo.toml b/examples/demo-stf/Cargo.toml index 28a93152e..bbaec1fe7 100644 --- a/examples/demo-stf/Cargo.toml +++ b/examples/demo-stf/Cargo.toml @@ -30,6 +30,7 @@ sov-sequencer-registry = { path = "../../module-system/module-implementations/so sov-blob-storage = { path = "../../module-system/module-implementations/sov-blob-storage" } sov-bank = { path = "../../module-system/module-implementations/sov-bank" } sov-nft-module = { path = "../../module-system/module-implementations/sov-nft-module" } +simple-nft-module = { path = "../simple-nft-module" } sov-chain-state = { path = "../../module-system/module-implementations/sov-chain-state" } sov-modules-stf-template = { path = "../../module-system/sov-modules-stf-template" } @@ -57,6 +58,7 @@ native = [ "sov-stf-runner/native", "sov-bank/native", "sov-nft-module/native", + "simple-nft-module/native", "sov-cli", "sov-accounts/native", "sov-sequencer-registry/native", diff --git a/examples/demo-stf/src/genesis_config.rs b/examples/demo-stf/src/genesis_config.rs index b6f997220..29f9e41b1 100644 --- a/examples/demo-stf/src/genesis_config.rs +++ b/examples/demo-stf/src/genesis_config.rs @@ -30,6 +30,7 @@ pub struct GenesisPaths> { pub value_setter_genesis_path: P, pub accounts_genesis_path: P, pub chain_state_genesis_path: P, + pub nft_path: P, #[cfg(feature = "experimental")] pub evm_genesis_path: P, } @@ -92,8 +93,7 @@ fn create_genesis_config>( read_json_file(&genesis_paths.value_setter_genesis_path)?; let accounts_config: AccountConfig = read_json_file(&genesis_paths.accounts_genesis_path)?; - - let nft_config: NonFungibleTokenConfig = NonFungibleTokenConfig {}; + let nft_config: NonFungibleTokenConfig = read_json_file(&genesis_paths.nft_path)?; let chain_state_config: ChainStateConfig = read_json_file(&genesis_paths.chain_state_genesis_path)?; diff --git a/examples/demo-stf/src/tests/mod.rs b/examples/demo-stf/src/tests/mod.rs index df89b5e46..95242a7e5 100644 --- a/examples/demo-stf/src/tests/mod.rs +++ b/examples/demo-stf/src/tests/mod.rs @@ -21,6 +21,7 @@ const TEST_GENESIS_PATHS: GenesisPaths<&str> = GenesisPaths { value_setter_genesis_path: "../test-data/genesis/integration-tests/value_setter.json", accounts_genesis_path: "../test-data/genesis/integration-tests/accounts.json", chain_state_genesis_path: "../test-data/genesis/integration-tests/chain_state.json", + nft_path: "../test-data/genesis/integration-tests/nft.json", #[cfg(feature = "experimental")] evm_genesis_path: "../test-data/genesis/integration-tests/evm.json", }; diff --git a/examples/simple-nft-module/Cargo.toml b/examples/simple-nft-module/Cargo.toml index 651b9b034..4d15d87d1 100644 --- a/examples/simple-nft-module/Cargo.toml +++ b/examples/simple-nft-module/Cargo.toml @@ -17,6 +17,9 @@ serde = { workspace = true } sov-modules-api = { path = "../../module-system/sov-modules-api" } sov-state = { path = "../../module-system/sov-state" } +clap = { workspace = true, optional = true, features = ["derive"] } +schemars = { workspace = true, optional = true } +serde_json = { workspace = true, optional = true } jsonrpsee = { workspace = true, features = ["macros", "client-core", "server"], optional = true } [dev-dependencies] @@ -27,5 +30,5 @@ simple-nft-module = { version = "*", features = ["native"], path = "." } [features] default = [] -native = ["sov-state/native", "sov-modules-api/native", "jsonrpsee"] +native = ["sov-state/native", "sov-modules-api/native", "jsonrpsee", "schemars", "serde_json", "clap"] test = ["native"] diff --git a/examples/simple-nft-module/src/call.rs b/examples/simple-nft-module/src/call.rs index 59133c268..09cd5d9b3 100644 --- a/examples/simple-nft-module/src/call.rs +++ b/examples/simple-nft-module/src/call.rs @@ -1,4 +1,6 @@ use anyhow::{bail, Result}; +#[cfg(feature = "native")] +use sov_modules_api::macros::CliWalletArg; use sov_modules_api::{CallResponse, Context, WorkingSet}; use crate::NonFungibleToken; @@ -6,7 +8,10 @@ use crate::NonFungibleToken; #[cfg_attr( feature = "native", derive(serde::Serialize), - derive(serde::Deserialize) + derive(serde::Deserialize), + derive(CliWalletArg), + derive(schemars::JsonSchema), + schemars(bound = "C::Address: ::schemars::JsonSchema", rename = "CallMessage") )] #[derive(borsh::BorshDeserialize, borsh::BorshSerialize, Debug, PartialEq, Clone)] /// A transaction handled by the NFT module. Mints, Transfers, or Burns an NFT by id diff --git a/examples/simple-nft-module/src/lib.rs b/examples/simple-nft-module/src/lib.rs index 16bce9c15..00a7f44cd 100644 --- a/examples/simple-nft-module/src/lib.rs +++ b/examples/simple-nft-module/src/lib.rs @@ -2,6 +2,8 @@ #![doc = include_str!("../README.md")] mod call; +#[cfg(test)] +mod tests; pub use call::CallMessage; mod genesis; #[cfg(feature = "native")] @@ -11,6 +13,7 @@ pub use query::*; use serde::{Deserialize, Serialize}; use sov_modules_api::{CallResponse, Context, Error, Module, ModuleInfo, WorkingSet}; +#[cfg_attr(feature = "native", derive(sov_modules_api::ModuleCallJsonSchema))] #[derive(ModuleInfo, Clone)] /// Module for non-fungible tokens (NFT). /// Each token is represented by a unique ID. @@ -30,7 +33,7 @@ pub struct NonFungibleToken { /// Config for the NonFungibleToken module. /// Sets admin and existing owners. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] pub struct NonFungibleTokenConfig { /// Admin of the NonFungibleToken module. pub admin: C::Address, diff --git a/examples/simple-nft-module/src/tests.rs b/examples/simple-nft-module/src/tests.rs new file mode 100644 index 000000000..f7349ea4a --- /dev/null +++ b/examples/simple-nft-module/src/tests.rs @@ -0,0 +1,27 @@ +use sov_modules_api::default_context::DefaultContext; +use sov_modules_api::utils::generate_address as gen_addr_generic; +use sov_modules_api::Spec; + +use crate::NonFungibleTokenConfig; + +#[test] +fn test_config_serialization() { + let address: ::Address = gen_addr_generic::("admin"); + let owner: ::Address = gen_addr_generic::("owner"); + + let config = NonFungibleTokenConfig:: { + admin: address, + owners: vec![(0, owner)], + }; + + let data = r#" + { + "admin":"sov1335hded4gyzpt00fpz75mms4m7ck02wgw07yhw9grahj4dzg4yvqk63pml", + "owners":[ + [0,"sov1fsgzj6t7udv8zhf6zj32mkqhcjcpv52yph5qsdcl0qt94jgdckqsczjm2y"] + ] + }"#; + + let parsed_config: NonFungibleTokenConfig = serde_json::from_str(data).unwrap(); + assert_eq!(config, parsed_config) +} diff --git a/examples/test-data/genesis/demo-tests/nft.json b/examples/test-data/genesis/demo-tests/nft.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/examples/test-data/genesis/demo-tests/nft.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/examples/test-data/genesis/integration-tests/nft.json b/examples/test-data/genesis/integration-tests/nft.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/examples/test-data/genesis/integration-tests/nft.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/module-system/module-implementations/sov-nft-module/src/lib.rs b/module-system/module-implementations/sov-nft-module/src/lib.rs index b1d26129b..bbe0370bd 100644 --- a/module-system/module-implementations/sov-nft-module/src/lib.rs +++ b/module-system/module-implementations/sov-nft-module/src/lib.rs @@ -5,6 +5,8 @@ mod call; pub use call::CallMessage; mod address; mod genesis; +#[cfg(test)] +mod tests; pub use address::*; mod collection; use collection::*; @@ -42,7 +44,7 @@ pub struct NonFungibleToken { /// Config for the NonFungibleToken module. /// Sets admin and existing owners. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] pub struct NonFungibleTokenConfig {} impl Module for NonFungibleToken { diff --git a/module-system/module-implementations/sov-nft-module/src/tests.rs b/module-system/module-implementations/sov-nft-module/src/tests.rs new file mode 100644 index 000000000..edfaed034 --- /dev/null +++ b/module-system/module-implementations/sov-nft-module/src/tests.rs @@ -0,0 +1,14 @@ +use crate::NonFungibleTokenConfig; + +#[test] +fn test_config_serialization() { + let config = NonFungibleTokenConfig {}; + + let data = r#" + { + + }"#; + + let parsed_config: NonFungibleTokenConfig = serde_json::from_str(data).unwrap(); + assert_eq!(config, parsed_config) +}