radix_clis/resim/
cmd_call_method.rs1#![allow(unused_must_use)]
2
3use clap::Parser;
4use radix_common::prelude::*;
5
6use crate::resim::*;
7use crate::utils::*;
8
9#[derive(Parser, Debug)]
11pub struct CallMethod {
12 pub component_address: SimulatorComponentAddress,
14
15 pub method_name: String,
17
18 pub arguments: Vec<String>,
20
21 #[clap(short, long, multiple = true)]
23 pub proofs: Option<Vec<String>>,
24
25 #[clap(short, long)]
27 pub network: Option<String>,
28
29 #[clap(short, long)]
31 pub manifest: Option<PathBuf>,
32
33 #[clap(short, long)]
35 pub signing_keys: Option<String>,
36
37 #[clap(short, long)]
39 pub trace: bool,
40}
41
42impl CallMethod {
43 pub fn run<O: std::io::Write>(&self, out: &mut O) -> Result<(), String> {
44 let address_bech32_decoder = AddressBech32Decoder::for_simulator();
45
46 let default_account = get_default_account()?;
47 let proofs = self.proofs.clone().unwrap_or_default();
48
49 let mut builder = ManifestBuilder::new().lock_fee_from_faucet();
50 for resource_specifier in proofs {
51 builder = create_proof_from_account(
52 builder,
53 &address_bech32_decoder,
54 default_account,
55 resource_specifier,
56 )
57 .map_err(Error::FailedToBuildArguments)?
58 }
59
60 let manifest = self
61 .add_call_method_instruction_with_schema(
62 builder,
63 &address_bech32_decoder,
64 self.component_address.0,
65 self.method_name.clone(),
66 self.arguments.clone(),
67 Some(default_account),
68 )?
69 .try_deposit_entire_worktop_or_refund(default_account, None)
70 .build();
71 handle_manifest(
72 manifest.into(),
73 &self.signing_keys,
74 &self.network,
75 &self.manifest,
76 self.trace,
77 true,
78 out,
79 )
80 .map(|_| ())
81 }
82
83 pub fn add_call_method_instruction_with_schema(
91 &self,
92 builder: ManifestBuilder,
93 address_bech32_decoder: &AddressBech32Decoder,
94 component_address: ComponentAddress,
95 method_name: String,
96 args: Vec<String>,
97 account: Option<ComponentAddress>,
98 ) -> Result<ManifestBuilder, Error> {
99 let object_info = export_object_info(component_address)?;
100 let bp_info = object_info.blueprint_info;
101 let bp_id = bp_info.blueprint_id;
102 let bp_interface =
103 export_blueprint_interface(bp_id.package_address, &bp_id.blueprint_name)?;
104
105 let function_schema = bp_interface
106 .find_method(method_name.as_str())
107 .ok_or_else(|| {
108 Error::TransactionConstructionError(BuildCallInstructionError::MethodNotFound(
109 method_name.clone(),
110 ))
111 })?;
112
113 let (schema, index) = match function_schema.input {
114 BlueprintPayloadDef::Static(ScopedTypeId(schema_hash, index)) => {
115 let schema = export_schema(bp_id.package_address.as_node_id(), schema_hash)?;
116 (schema, index)
117 }
118 BlueprintPayloadDef::Generic(generic_index) => {
119 let type_subst_ref = bp_info
120 .generic_substitutions
121 .get(generic_index as usize)
122 .ok_or_else(|| Error::InstanceSchemaNot(component_address, generic_index))?;
123
124 match type_subst_ref {
125 GenericSubstitution::Local(type_id) => {
126 let schema = export_schema(bp_id.package_address.as_node_id(), type_id.0)?;
127 (schema, type_id.1)
128 }
129 GenericSubstitution::Remote(_) => {
130 return Err(Error::RemoteGenericSubstitutionNotSupported);
131 }
132 }
133 }
134 };
135
136 let (builder, built_args) = build_call_arguments(
137 builder,
138 address_bech32_decoder,
139 &schema,
140 index,
141 args,
142 account,
143 )
144 .map_err(|e| {
145 Error::TransactionConstructionError(BuildCallInstructionError::FailedToBuildArguments(
146 e,
147 ))
148 })?;
149
150 Ok(builder.call_method_raw(component_address, method_name, built_args))
151 }
152}