Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: terminology #368

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 105 additions & 111 deletions crates/pop-cli/src/commands/call/parachain.rs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions crates/pop-cli/tests/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ name = "collator-01"
// Wait for the networks to initialize. Increased timeout to accommodate CI environment delays.
sleep(Duration::from_secs(50)).await;

// `pop call parachain --pallet System --extrinsic remark --args "0x11" --url
// `pop call parachain --pallet System --function remark --args "0x11" --url
// ws://127.0.0.1:random_port --suri //Alice --skip-confirm`
Command::cargo_bin("pop")
.unwrap()
Expand All @@ -142,7 +142,7 @@ name = "collator-01"
"parachain",
"--pallet",
"System",
"--extrinsic",
"--function",
"remark",
"--args",
"0x11",
Expand Down
13 changes: 7 additions & 6 deletions crates/pop-parachains/src/call/metadata/action.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

use super::{find_extrinsic_by_name, Pallet};
use super::{find_dispatchable_by_name, Pallet};
use strum::{EnumMessage as _, EnumProperty as _, VariantArray as _};
use strum_macros::{AsRefStr, Display, EnumMessage, EnumProperty, EnumString, VariantArray};

Expand Down Expand Up @@ -91,8 +91,8 @@ impl Action {
self.get_detailed_message().unwrap_or_default()
}

/// Get the extrinsic name corresponding to the action.
pub fn extrinsic_name(&self) -> &str {
/// Get the dispatchable function name corresponding to the action.
pub fn function_name(&self) -> &str {
self.get_message().unwrap_or_default()
}

Expand All @@ -109,7 +109,8 @@ impl Action {
pub fn supported_actions(pallets: &[Pallet]) -> Vec<Action> {
let mut actions = Vec::new();
for action in Action::VARIANTS.iter() {
if find_extrinsic_by_name(pallets, action.pallet_name(), action.extrinsic_name()).is_ok() {
if find_dispatchable_by_name(pallets, action.pallet_name(), action.function_name()).is_ok()
{
actions.push(action.clone());
}
}
Expand Down Expand Up @@ -162,7 +163,7 @@ mod tests {
}

#[test]
fn extrinsic_names_are_correct() {
fn function_names_are_correct() {
let pallets = HashMap::from([
(Action::CreateAsset, "create"),
(Action::MintAsset, "mint"),
Expand All @@ -175,7 +176,7 @@ mod tests {
]);

for action in Action::VARIANTS.iter() {
assert_eq!(&action.extrinsic_name(), pallets.get(action).unwrap(),);
assert_eq!(&action.function_name(), pallets.get(action).unwrap(),);
}
}

Expand Down
123 changes: 64 additions & 59 deletions crates/pop-parachains/src/call/metadata/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use subxt::{dynamic::Value, Metadata, OnlineClient, SubstrateConfig};
pub mod action;
pub mod params;

/// Represents a pallet in the blockchain, including its extrinsics.
/// Represents a pallet in the blockchain, including its dispatchable functions.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Pallet {
/// The name of the pallet.
Expand All @@ -18,8 +18,8 @@ pub struct Pallet {
pub index: u8,
/// The documentation of the pallet.
pub docs: String,
/// The extrinsics of the pallet.
pub extrinsics: Vec<Extrinsic>,
/// The dispatchable functions of the pallet.
pub functions: Vec<Function>,
}

impl Display for Pallet {
Expand All @@ -28,29 +28,30 @@ impl Display for Pallet {
}
}

/// Represents an extrinsic.
/// Represents a dispatchable function.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Extrinsic {
/// The name of the extrinsic.
pub struct Function {
/// The pallet containing the dispatchable function.
pub pallet: String,
/// The name of the function.
pub name: String,
/// The index of the extrinsic within the pallet.
/// The index of the function within the pallet.
pub index: u8,
/// The documentation of the extrinsic.
/// The documentation of the function.
pub docs: String,
/// The parameters of the extrinsic.
/// The parameters of the function.
pub params: Vec<Param>,
/// Whether this extrinsic is supported (no recursive or unsupported types like `RuntimeCall`).
/// Whether this function is supported (no recursive or unsupported types like `RuntimeCall`).
pub is_supported: bool,
}

impl Display for Extrinsic {
impl Display for Function {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name)
}
}

/// Parses the chain metadata to extract information about pallets and their extrinsics with its
/// parameters.
/// Parses the chain metadata to extract information about pallets and their dispatchable functions.
///
/// # Arguments
/// * `client`: The client to interact with the chain.
Expand All @@ -62,23 +63,24 @@ pub fn parse_chain_metadata(client: &OnlineClient<SubstrateConfig>) -> Result<Ve
let pallets = metadata
.pallets()
.map(|pallet| {
let extrinsics = pallet
let functions = pallet
.call_variants()
.map(|variants| {
variants
.iter()
.map(|variant| {
let mut is_supported = true;

// Parse parameters for the extrinsic
// Parse parameters for the dispatchable function.
let params = {
let mut parsed_params = Vec::new();
for field in &variant.fields {
match params::field_to_param(client, field) {
Ok(param) => parsed_params.push(param),
Err(_) => {
// If an error occurs while parsing the values, mark the
// extrinsic as unsupported rather than error.
// dispatchable function as unsupported rather than
// error.
is_supported = false;
parsed_params.clear();
break;
Expand All @@ -88,7 +90,8 @@ pub fn parse_chain_metadata(client: &OnlineClient<SubstrateConfig>) -> Result<Ve
parsed_params
};

Ok(Extrinsic {
Ok(Function {
pallet: pallet.name().to_string(),
name: variant.name.clone(),
index: variant.index,
docs: if is_supported {
Expand All @@ -102,21 +105,21 @@ pub fn parse_chain_metadata(client: &OnlineClient<SubstrateConfig>) -> Result<Ve
.join(" ")
} else {
// To display the message in the UI
"Extrinsic Not Supported".to_string()
"Function Not Supported".to_string()
},
params,
is_supported,
})
})
.collect::<Result<Vec<Extrinsic>, Error>>()
.collect::<Result<Vec<Function>, Error>>()
})
.unwrap_or_else(|| Ok(vec![]))?;

Ok(Pallet {
name: pallet.name().to_string(),
index: pallet.index(),
docs: pallet.docs().join(" "),
extrinsics,
functions,
})
})
.collect::<Result<Vec<Pallet>, Error>>()?;
Expand All @@ -140,31 +143,33 @@ pub fn find_pallet_by_name<'a>(
}
}

/// Finds a specific extrinsic by name and retrieves its details from metadata.
/// Finds a specific dispatchable function by name and retrieves its details from metadata.
///
/// # Arguments
/// * `pallets`: List of pallets available in the chain.
/// * `pallet_name`: The name of the pallet to find.
/// * `extrinsic_name`: Name of the extrinsic to locate.
pub fn find_extrinsic_by_name<'a>(
/// * `pallet_name`: The name of the pallet.
/// * `function_name`: Name of the dispatchable function to locate.
pub fn find_dispatchable_by_name<'a>(
pallets: &'a [Pallet],
pallet_name: &str,
extrinsic_name: &str,
) -> Result<&'a Extrinsic, Error> {
function_name: &str,
) -> Result<&'a Function, Error> {
let pallet = find_pallet_by_name(pallets, pallet_name)?;
if let Some(extrinsic) = pallet.extrinsics.iter().find(|&e| e.name == extrinsic_name) {
Ok(extrinsic)
if let Some(function) = pallet.functions.iter().find(|&e| e.name == function_name) {
Ok(function)
} else {
Err(Error::ExtrinsicNotSupported)
Err(Error::FunctionNotSupported)
}
}

/// Parses and processes raw string parameters for an extrinsic, mapping them to `Value` types.
/// Parses and processes raw string parameter values for a dispatchable function, mapping them to
/// `Value` types.
///
/// # Arguments
/// * `params`: The metadata definition for each parameter of the extrinsic.
/// * `raw_params`: A vector of raw string arguments for the extrinsic.
pub fn parse_extrinsic_arguments(
/// * `params`: The metadata definition for each parameter of the corresponding dispatchable
/// function.
/// * `raw_params`: A vector of raw string arguments for the dispatchable function.
pub fn parse_dispatchable_arguments(
params: &[Param],
raw_params: Vec<String>,
) -> Result<Vec<Value>, Error> {
Expand Down Expand Up @@ -205,22 +210,22 @@ mod tests {
assert_eq!(first_pallet.name, "System");
assert_eq!(first_pallet.index, 0);
assert_eq!(first_pallet.docs, "");
assert_eq!(first_pallet.extrinsics.len(), 11);
let first_extrinsic = first_pallet.extrinsics.first().unwrap();
assert_eq!(first_extrinsic.name, "remark");
assert_eq!(first_extrinsic.index, 0);
assert_eq!(first_pallet.functions.len(), 11);
let first_function = first_pallet.functions.first().unwrap();
assert_eq!(first_function.name, "remark");
assert_eq!(first_function.index, 0);
assert_eq!(
first_extrinsic.docs,
first_function.docs,
"Make some on-chain remark. Can be executed by every `origin`."
);
assert!(first_extrinsic.is_supported);
assert_eq!(first_extrinsic.params.first().unwrap().name, "remark");
assert_eq!(first_extrinsic.params.first().unwrap().type_name, "[u8]");
assert_eq!(first_extrinsic.params.first().unwrap().sub_params.len(), 0);
assert!(!first_extrinsic.params.first().unwrap().is_optional);
assert!(!first_extrinsic.params.first().unwrap().is_tuple);
assert!(!first_extrinsic.params.first().unwrap().is_variant);
assert!(first_extrinsic.params.first().unwrap().is_sequence);
assert!(first_function.is_supported);
assert_eq!(first_function.params.first().unwrap().name, "remark");
assert_eq!(first_function.params.first().unwrap().type_name, "[u8]");
assert_eq!(first_function.params.first().unwrap().sub_params.len(), 0);
assert!(!first_function.params.first().unwrap().is_optional);
assert!(!first_function.params.first().unwrap().is_tuple);
assert!(!first_function.params.first().unwrap().is_variant);
assert!(first_function.params.first().unwrap().is_sequence);
Ok(())
}

Expand All @@ -233,31 +238,31 @@ mod tests {
Err(Error::PalletNotFound(pallet)) if pallet == "WrongName".to_string()));
let pallet = find_pallet_by_name(&pallets, "Balances")?;
assert_eq!(pallet.name, "Balances");
assert_eq!(pallet.extrinsics.len(), 9);
assert_eq!(pallet.functions.len(), 9);
Ok(())
}

#[tokio::test]
async fn find_extrinsic_by_name_works() -> Result<()> {
async fn find_dispatchable_by_name_works() -> Result<()> {
let client = set_up_client(POP_NETWORK_TESTNET_URL).await?;
let pallets = parse_chain_metadata(&client)?;
assert!(matches!(
find_extrinsic_by_name(&pallets, "WrongName", "wrong_extrinsic"),
find_dispatchable_by_name(&pallets, "WrongName", "wrong_name"),
Err(Error::PalletNotFound(pallet)) if pallet == "WrongName".to_string()));
assert!(matches!(
find_extrinsic_by_name(&pallets, "Balances", "wrong_extrinsic"),
Err(Error::ExtrinsicNotSupported)
find_dispatchable_by_name(&pallets, "Balances", "wrong_name"),
Err(Error::FunctionNotSupported)
));
let extrinsic = find_extrinsic_by_name(&pallets, "Balances", "force_transfer")?;
assert_eq!(extrinsic.name, "force_transfer");
assert_eq!(extrinsic.docs, "Exactly as `transfer_allow_death`, except the origin must be root and the source account may be specified.");
assert_eq!(extrinsic.is_supported, true);
assert_eq!(extrinsic.params.len(), 3);
let function = find_dispatchable_by_name(&pallets, "Balances", "force_transfer")?;
assert_eq!(function.name, "force_transfer");
assert_eq!(function.docs, "Exactly as `transfer_allow_death`, except the origin must be root and the source account may be specified.");
assert_eq!(function.is_supported, true);
assert_eq!(function.params.len(), 3);
Ok(())
}

#[test]
fn parse_extrinsic_arguments_works() -> Result<()> {
fn parse_dispatchable_arguments_works() -> Result<()> {
// Values for testing from: https://docs.rs/scale-value/0.18.0/scale_value/stringify/fn.from_str.html
// and https://docs.rs/scale-value/0.18.0/scale_value/stringify/fn.from_str_custom.html
let args = [
Expand All @@ -283,7 +288,7 @@ mod tests {
.into_iter()
.map(|b| Value::u128(b as u128))
.collect();
// Define mock extrinsic parameters for testing.
// Define mock dispatchable function parameters for testing.
let params = vec![
Param { type_name: "u128".to_string(), ..Default::default() },
Param { type_name: "i128".to_string(), ..Default::default() },
Expand All @@ -297,7 +302,7 @@ mod tests {
Param { type_name: "composite".to_string(), ..Default::default() },
];
assert_eq!(
parse_extrinsic_arguments(&params, args)?,
parse_dispatchable_arguments(&params, args)?,
[
Value::u128(1),
Value::i128(-1),
Expand Down
Loading
Loading