sov-modules-macros 0.3.0

Macros for use with the Sovereign SDK module system
use clap::Parser;
use sov_modules_api::cli::JsonStringArg;
use sov_modules_api::default_context::DefaultContext;
use sov_modules_api::macros::{CliWallet, CliWalletArg, DefaultRuntime};
use sov_modules_api::{
    CallResponse, Context, DispatchCall, Error, Genesis, MessageCodec, Module, ModuleInfo, StateValue, WorkingSet
};

pub mod first_test_module {
    use super::*;

    #[derive(
        CliWalletArg,
        Debug,
        PartialEq,
        borsh::BorshDeserialize,
        borsh::BorshSerialize,
        serde::Serialize,
        serde::Deserialize,
    )]
    pub struct MyStruct {
        pub first_field: u32,
        pub str_field: String,
    }

    #[derive(ModuleInfo)]
    pub struct FirstTestStruct<C: Context> {
        #[address]
        pub address: C::Address,

        #[state]
        pub state_in_first_struct: StateValue<u8>,
    }

    impl<C: Context> Module for FirstTestStruct<C> {
        type Context = C;
        type Config = ();
        type CallMessage = MyStruct;

        fn genesis(
            &self,
            _config: &Self::Config,
            _working_set: &mut WorkingSet<C>,
        ) -> Result<(), Error> {
            Ok(())
        }

        fn call(
            &self,
            _msg: Self::CallMessage,
            _context: &Self::Context,
            _working_set: &mut WorkingSet<C>,
        ) -> Result<CallResponse, Error> {
            Ok(CallResponse::default())
        }
    }
}

pub mod second_test_module {
    use super::*;

    #[derive(ModuleInfo)]
    pub struct SecondTestStruct<Ctx: Context> {
        #[address]
        pub address: Ctx::Address,

        #[state]
        pub state_in_second_struct: StateValue<u8>,
    }

    #[derive(
        CliWalletArg,
        Debug,
        PartialEq,
        borsh::BorshDeserialize,
        borsh::BorshSerialize,
        serde::Serialize,
        serde::Deserialize,
    )]
    pub enum MyEnum {
        Foo { first_field: u32, str_field: String },
        Bar(u8),
    }

    impl<Ctx: Context> Module for SecondTestStruct<Ctx> {
        type Context = Ctx;
        type Config = ();
        type CallMessage = MyEnum;

        fn genesis(
            &self,
            _config: &Self::Config,
            _working_set: &mut WorkingSet<Ctx>,
        ) -> Result<(), Error> {
            Ok(())
        }

        fn call(
            &self,
            _msg: Self::CallMessage,
            _context: &Self::Context,
            _working_set: &mut WorkingSet<Ctx>,
        ) -> Result<CallResponse, Error> {
            Ok(CallResponse::default())
        }
    }
}

#[derive(Genesis, DispatchCall, MessageCodec, DefaultRuntime, CliWallet)]
#[serialization(borsh::BorshDeserialize, borsh::BorshSerialize)]
pub struct Runtime<C: Context> {
    pub first: first_test_module::FirstTestStruct<C>,
    pub second: second_test_module::SecondTestStruct<C>,
}

fn main() {
    let expected_foo = RuntimeCall::first(first_test_module::MyStruct {
        first_field: 1,
        str_field: "hello".to_string(),
    });
    let foo_from_cli: RuntimeSubcommand<JsonStringArg, DefaultContext> =
        <RuntimeSubcommand<JsonStringArg, DefaultContext>>::try_parse_from(&[
            "main",
            "first",
            "--json",
            r#"{"first_field": 1, "str_field": "hello"}"#,
        ])
        .expect("parsing must succed")
        .into();
    let foo_ir: RuntimeMessage<JsonStringArg, DefaultContext> = foo_from_cli.try_into().unwrap();
    assert_eq!(expected_foo, foo_ir.try_into().unwrap());

    let expected_bar = RuntimeCall::second(second_test_module::MyEnum::Bar(2));
    let bar_from_cli: RuntimeSubcommand<JsonStringArg, DefaultContext> =
        <RuntimeSubcommand<JsonStringArg, DefaultContext>>::try_parse_from(&[
            "main",
            "second",
            "--json",
            r#"{"Bar": 2}"#,
        ])
        .expect("parsing must succed")
        .into();
    let bar_ir: RuntimeMessage<JsonStringArg, DefaultContext> = bar_from_cli.try_into().unwrap();

    assert_eq!(expected_bar, bar_ir.try_into().unwrap());
}