1use anyhow::Result;
2use args::{AuthArgs, AuthBlob, FeeKey};
3use auth_fee::estimate_cost;
4use clap::{Args, Subcommand};
5use rand::SeedableRng;
6use rand_chacha::ChaChaRng;
7use snarkvm::synthesizer::{process::deployment_cost, Process};
8
9use crate::{Key, Network};
10
11pub mod args;
12pub mod auth_deploy;
13pub mod auth_fee;
14pub mod auth_id;
15pub mod auth_program;
16pub mod execute;
17pub mod query;
18
19pub fn rng_from_seed(seed: Option<u64>) -> ChaChaRng {
20 if let Some(seed) = seed {
21 ChaChaRng::seed_from_u64(seed)
22 } else {
23 ChaChaRng::from_entropy()
24 }
25}
26
27#[derive(Debug, Subcommand)]
30pub enum AuthCommand<N: Network> {
31 Execute(execute::Execute<N>),
32 Program(AuthProgramCommand<N>),
33 Fee(auth_fee::AuthorizeFee<N>),
34 Id(AuthArgs<N>),
36 Cost(CostCommand<N>),
37 Deploy(AuthDeployCommand<N>),
38}
39
40#[derive(Debug, Args)]
43pub struct CostCommand<N: Network> {
44 #[clap(long)]
46 query: Option<String>,
47 #[clap(flatten)]
48 auth: AuthArgs<N>,
49}
50
51#[derive(Debug, Args)]
53pub struct AuthProgramCommand<N: Network> {
54 #[clap(flatten)]
55 pub key: Key<N>,
56 #[clap(flatten)]
57 pub fee_key: FeeKey<N>,
58 #[clap(long)]
60 pub skip_fee: bool,
61 #[clap(flatten)]
62 pub fee_opts: auth_fee::AuthFeeOptions<N>,
63 #[clap(flatten)]
64 pub program_opts: auth_program::AuthProgramOptions<N>,
65 #[clap(long)]
67 pub seed: Option<u64>,
68}
69
70#[derive(Debug, Args)]
72pub struct AuthDeployCommand<N: Network> {
73 #[clap(flatten)]
74 pub key: Key<N>,
75 #[clap(flatten)]
76 pub fee_key: FeeKey<N>,
77 #[clap(long)]
79 pub skip_fee: bool,
80 #[clap(flatten)]
81 pub fee_opts: auth_fee::AuthFeeOptions<N>,
82 #[clap(flatten)]
83 pub deploy_opts: auth_deploy::AuthDeployOptions<N>,
84 #[clap(long)]
86 pub seed: Option<u64>,
87}
88
89impl<N: Network> AuthCommand<N> {
90 pub(crate) fn parse(self) -> Result<()> {
91 match self {
92 AuthCommand::Execute(command) => command.parse(),
94 AuthCommand::Fee(fee) => {
97 println!("{}", serde_json::to_string(&fee.parse()?)?);
98 Ok(())
99 }
100 AuthCommand::Id(args) => {
103 let id = match args.pick()? {
104 AuthBlob::Program { auth, fee_auth } => {
105 let auth = auth.into();
106 let fee_auth = fee_auth.map(Into::into);
107
108 auth_id::auth_tx_id(&auth, fee_auth.as_ref())?
110 }
111 AuthBlob::Deploy {
112 deployment,
113 fee_auth,
114 ..
115 } => auth_id::deploy_tx_id(&deployment, fee_auth.map(Into::into).as_ref())?,
117 };
118 println!("{id}");
119 Ok(())
120 }
121 AuthCommand::Cost(CostCommand { query, auth }) => {
122 let cost = match auth.pick()? {
123 AuthBlob::Program { auth, .. } => {
124 let auth = auth.into();
125
126 let mut process = Process::load()?;
130 if let Some(query) = query.as_deref() {
131 let programs = query::get_programs_from_auth(&auth);
132 query::add_many_programs_to_process(&mut process, programs, query)?;
133 }
134
135 estimate_cost(&process, &auth)?
136 }
137 AuthBlob::Deploy { deployment, .. } => deployment_cost(&deployment)?.0,
138 };
139 println!("{cost}");
140 Ok(())
141 }
142 AuthCommand::Program(AuthProgramCommand {
143 key,
144 skip_fee,
145 fee_key,
146 program_opts,
147 fee_opts,
148 seed,
149 }) => {
150 let query = program_opts.query.clone();
151
152 let (auth, cost) = auth_program::AuthorizeProgram {
154 key: key.clone(),
155 options: program_opts,
156 seed,
157 }
158 .parse()?;
159
160 if skip_fee {
161 println!("{}", serde_json::to_string(&auth)?);
162 return Ok(());
163 };
164
165 let fee_auth = auth_fee::AuthorizeFee {
167 key: fee_key.as_key().unwrap_or(key),
168 auth: None,
169 options: fee_opts,
170 deployment: None,
171 query,
172 id: Some(auth.to_execution_id()?),
173 cost: Some(cost),
174 seed,
175 }
176 .parse()?;
177
178 println!(
179 "{}",
180 serde_json::to_string(&AuthBlob::Program {
181 auth: auth.into(),
182 fee_auth: fee_auth.map(Into::into),
183 })?
184 );
185 Ok(())
186 }
187 AuthCommand::Deploy(AuthDeployCommand {
188 key,
189 skip_fee,
190 fee_key,
191 deploy_opts,
192 fee_opts,
193 seed,
194 }) => {
195 let AuthBlob::Deploy {
197 deployment, owner, ..
198 } = auth_deploy::AuthorizeDeploy {
199 key: key.clone(),
200 options: deploy_opts,
201 seed,
202 }
203 .parse()?
204 else {
205 unreachable!("authorize deploy never returns a program auth")
206 };
207
208 if skip_fee {
209 println!(
210 "{}",
211 serde_json::to_string(&AuthBlob::Deploy {
212 deployment,
213 owner,
214 fee_auth: None
215 })?
216 );
217 return Ok(());
218 };
219
220 let fee_auth = auth_fee::AuthorizeFee {
222 key: fee_key.as_key().unwrap_or(key),
223 auth: None,
224 options: fee_opts,
225 deployment: None,
226 query: None,
227 id: Some(deployment.to_deployment_id()?),
228 cost: Some(deployment_cost(&deployment)?.0),
229 seed,
230 }
231 .parse()?
232 .map(Into::into);
233
234 println!(
235 "{}",
236 serde_json::to_string(&AuthBlob::Deploy {
237 deployment,
238 fee_auth,
239 owner,
240 })?
241 );
242 Ok(())
243 }
244 }
245 }
246}