diff --git a/Cargo.lock b/Cargo.lock index 7a311fa87..4cc596fd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,9 +16,12 @@ dependencies = [ name = "ac-compose-macros" version = "0.4.2" dependencies = [ + "ac-node-api", "ac-primitives", + "frame-metadata 16.0.0", "log", "maybe-async", + "parity-scale-codec", ] [[package]] diff --git a/compose-macros/Cargo.toml b/compose-macros/Cargo.toml index 41b7c9e71..dc604e642 100644 --- a/compose-macros/Cargo.toml +++ b/compose-macros/Cargo.toml @@ -17,6 +17,12 @@ maybe-async = { version = "0.2.7" } # local ac-primitives = { path = "../primitives", default-features = false } +[dev-dependencies] +ac-node-api = { path = "../node-api" } +frame-metadata = { version = "16.0" } +codec = { package = "parity-scale-codec", version = "3.6.1" } + + [features] default = ["std", "sync-api"] sync-api = ["maybe-async/is_sync"] diff --git a/compose-macros/src/lib.rs b/compose-macros/src/lib.rs index 8ddd67646..4895235d4 100644 --- a/compose-macros/src/lib.rs +++ b/compose-macros/src/lib.rs @@ -37,11 +37,25 @@ mod rpc; macro_rules! compose_call { ($node_metadata: expr, $pallet: expr, $call_name: expr $(, $args: expr) *) => { { - let pallet = $node_metadata.pallet_by_name($pallet).unwrap().to_owned(); - - let call_index = pallet.call_variant_by_name($call_name).unwrap().index; + let pallet_metadata = $node_metadata.pallet_by_name($pallet).unwrap().to_owned(); + $crate::compose_call_for_pallet_metadata!(pallet_metadata, $call_name $(, ($args)) *) + } + }; +} - ([pallet.index(), call_index as u8] $(, ($args)) *) +/// Generates the extrinsic's call field for the given PalletMetadata +/// # Arguments +/// +/// * 'pallet_metadata' - This crate's parsed pallet metadata as field of the API. +/// * 'call_name' - Call name as &str +/// * 'args' - Optional sequence of arguments of the call. They are not checked against the metadata. +/// As of now the user needs to check himself that the correct arguments are supplied. +#[macro_export] +macro_rules! compose_call_for_pallet_metadata { +($pallet_metadata: expr, $call_name: expr $(, $args: expr) *) => { + { + let call_index = $pallet_metadata.call_variant_by_name($call_name).unwrap().index; + ([$pallet_metadata.index(), call_index as u8] $(, ($args)) *) } }; } @@ -143,3 +157,38 @@ macro_rules! compose_extrinsic { } }; } + +#[cfg(test)] +mod tests { + use super::*; + use ac_node_api::Metadata; + use codec::Decode; + use frame_metadata::RuntimeMetadataPrefixed; + use std::fs; + + #[test] + fn macro_compose_call_for_pallet_metadata_works() { + let encoded_metadata = fs::read("../ksm_metadata_v14.bin").unwrap(); + let runtime_metadata_prefixed = + RuntimeMetadataPrefixed::decode(&mut encoded_metadata.as_slice()).unwrap(); + let metadata = Metadata::try_from(runtime_metadata_prefixed).unwrap(); + + let pallet_metadata = metadata.pallet_by_name("Balances").unwrap(); + + let extra_parameter = 10000; + let expected_call_one = ([4, 0], extra_parameter); + let call_one = compose_call_for_pallet_metadata!( + &pallet_metadata, + "transfer_allow_death", + extra_parameter + ); + assert_eq!(expected_call_one, call_one); + let expected_call_two = ([4, 8], extra_parameter); + let call_two = compose_call_for_pallet_metadata!( + &pallet_metadata, + "force_set_balance", + extra_parameter + ); + assert_eq!(expected_call_two, call_two); + } +}