Skip to main content

pop_chains/call/metadata/
action.rs

1// SPDX-License-Identifier: GPL-3.0
2
3use super::{Pallet, find_callable_by_name};
4use strum::{EnumMessage as _, EnumProperty as _, VariantArray as _};
5use strum_macros::{AsRefStr, Display, EnumMessage, EnumProperty, EnumString, VariantArray};
6
7/// Enum representing various predefined actions supported.
8#[derive(
9	AsRefStr,
10	Clone,
11	Debug,
12	Display,
13	EnumMessage,
14	EnumString,
15	EnumProperty,
16	Eq,
17	Hash,
18	PartialEq,
19	VariantArray,
20)]
21pub enum Action {
22	/// Transfer balance.
23	#[strum(
24		serialize = "transfer",
25		message = "transfer_allow_death",
26		detailed_message = "Transfer balance",
27		props(Pallet = "Balances")
28	)]
29	Transfer,
30	/// Create an asset.
31	#[strum(
32		serialize = "create",
33		message = "create",
34		detailed_message = "Create an asset",
35		props(Pallet = "Assets")
36	)]
37	CreateAsset,
38	/// Mint an asset.
39	#[strum(
40		serialize = "mint",
41		message = "mint",
42		detailed_message = "Mint an asset",
43		props(Pallet = "Assets")
44	)]
45	MintAsset,
46	/// Create a NFT collection.
47	#[strum(
48		serialize = "create_nft",
49		message = "create",
50		detailed_message = "Create a NFT collection",
51		props(Pallet = "Nfts")
52	)]
53	CreateCollection,
54	/// Mint a NFT.
55	#[strum(
56		serialize = "mint_nft",
57		message = "mint",
58		detailed_message = "Mint a NFT",
59		props(Pallet = "Nfts")
60	)]
61	MintNFT,
62	/// Purchase on-demand coretime.
63	#[strum(
64		serialize = "place_order_allow_death",
65		message = "place_order_allow_death",
66		detailed_message = "Purchase on-demand coretime",
67		props(Pallet = "OnDemand")
68	)]
69	PurchaseOnDemandCoretime,
70	/// Create a pure proxy.
71	#[strum(
72		serialize = "create_pure",
73		message = "create_pure",
74		detailed_message = "Create a pure proxy",
75		props(Pallet = "Proxy")
76	)]
77	PureProxy,
78	/// Reserve a parachain ID.
79	#[strum(
80		serialize = "reserve",
81		message = "reserve",
82		detailed_message = "Reserve a parachain ID",
83		props(Pallet = "Registrar")
84	)]
85	Reserve,
86	/// Register a parachain ID with genesis state and code.
87	#[strum(
88		serialize = "register",
89		message = "register",
90		detailed_message = "Register a parachain ID with genesis state and code",
91		props(Pallet = "Registrar")
92	)]
93	Register,
94	/// Make a remark.
95	#[strum(
96		serialize = "remark",
97		message = "remark_with_event",
98		detailed_message = "Make a remark",
99		props(Pallet = "System")
100	)]
101	Remark,
102	/// Register the callers account so that it can be used in contract interactions.
103	#[strum(
104		serialize = "map_account",
105		message = "map_account",
106		detailed_message = "Map account",
107		props(Pallet = "Revive")
108	)]
109	MapAccount,
110}
111
112impl Action {
113	/// Get the description of the action.
114	pub fn description(&self) -> &str {
115		self.get_detailed_message().unwrap_or_default()
116	}
117
118	/// Get the dispatchable function name corresponding to the action.
119	pub fn function_name(&self) -> &str {
120		self.get_message().unwrap_or_default()
121	}
122
123	/// Get the associated pallet name for the action.
124	pub fn pallet_name(&self) -> &str {
125		self.get_str("Pallet").unwrap_or_default()
126	}
127}
128
129/// Fetch the list of supported actions based on available pallets.
130///
131/// # Arguments
132/// * `pallets`: Supported pallets.
133pub fn supported_actions(pallets: &[Pallet]) -> Vec<Action> {
134	let mut actions = Vec::new();
135	for action in Action::VARIANTS.iter() {
136		if find_callable_by_name(pallets, action.pallet_name(), action.function_name()).is_ok() {
137			actions.push(action.clone());
138		}
139	}
140	actions
141}
142
143#[cfg(test)]
144mod tests {
145	use super::{Action::*, *};
146	use crate::{parse_chain_metadata, set_up_client};
147	use anyhow::Result;
148	use pop_common::test_env::shared_substrate_ws_url;
149	use std::collections::HashMap;
150
151	#[test]
152	fn action_descriptions_are_correct() {
153		let descriptions = HashMap::from([
154			(CreateAsset, "Create an asset"),
155			(MintAsset, "Mint an asset"),
156			(CreateCollection, "Create a NFT collection"),
157			(MintNFT, "Mint a NFT"),
158			(PurchaseOnDemandCoretime, "Purchase on-demand coretime"),
159			(PureProxy, "Create a pure proxy"),
160			(Transfer, "Transfer balance"),
161			(Register, "Register a parachain ID with genesis state and code"),
162			(Reserve, "Reserve a parachain ID"),
163			(Remark, "Make a remark"),
164			(MapAccount, "Map account"),
165		]);
166
167		for action in Action::VARIANTS.iter() {
168			assert_eq!(&action.description(), descriptions.get(action).unwrap());
169		}
170	}
171
172	#[test]
173	fn pallet_names_are_correct() {
174		let pallets = HashMap::from([
175			(CreateAsset, "Assets"),
176			(MintAsset, "Assets"),
177			(CreateCollection, "Nfts"),
178			(MintNFT, "Nfts"),
179			(PurchaseOnDemandCoretime, "OnDemand"),
180			(PureProxy, "Proxy"),
181			(Transfer, "Balances"),
182			(Register, "Registrar"),
183			(Reserve, "Registrar"),
184			(Remark, "System"),
185			(MapAccount, "Revive"),
186		]);
187
188		for action in Action::VARIANTS.iter() {
189			assert_eq!(&action.pallet_name(), pallets.get(action).unwrap(),);
190		}
191	}
192
193	#[test]
194	fn function_names_are_correct() {
195		let pallets = HashMap::from([
196			(CreateAsset, "create"),
197			(MintAsset, "mint"),
198			(CreateCollection, "create"),
199			(MintNFT, "mint"),
200			(PurchaseOnDemandCoretime, "place_order_allow_death"),
201			(PureProxy, "create_pure"),
202			(Transfer, "transfer_allow_death"),
203			(Register, "register"),
204			(Reserve, "reserve"),
205			(Remark, "remark_with_event"),
206			(MapAccount, "map_account"),
207		]);
208
209		for action in Action::VARIANTS.iter() {
210			assert_eq!(&action.function_name(), pallets.get(action).unwrap(),);
211		}
212	}
213
214	#[tokio::test]
215	async fn supported_actions_works() -> Result<()> {
216		let node_url = shared_substrate_ws_url().await;
217		// Test Local Node.
218		let client: subxt::OnlineClient<subxt::SubstrateConfig> = set_up_client(&node_url).await?;
219		let pallets = parse_chain_metadata(&client)?;
220		let actions = supported_actions(&pallets);
221		// Kitchensink runtime includes Nfts, Proxy, and Revive pallets but not OnDemand.
222		assert!(actions.contains(&Transfer));
223		assert!(actions.contains(&CreateAsset));
224		assert!(actions.contains(&MintAsset));
225		assert!(actions.contains(&CreateCollection));
226		assert!(actions.contains(&MintNFT));
227		assert!(actions.contains(&PureProxy));
228		assert!(actions.contains(&Remark));
229		assert!(actions.contains(&MapAccount));
230		assert!(!actions.contains(&PurchaseOnDemandCoretime));
231		Ok(())
232	}
233}