leo_lang/cli/commands/common/
options.rs1use super::*;
18use leo_package::NetworkName;
19use snarkvm::prelude::ConsensusVersion;
20
21#[derive(Parser, Clone, Debug)]
24pub struct BuildOptions {
25 #[clap(long, help = "Does not recursively compile dependencies.")]
26 pub non_recursive: bool,
27 #[clap(long, help = "Enables offline mode.")]
28 pub offline: bool,
29 #[clap(long, help = "Enable spans in AST snapshots.")]
30 pub enable_ast_spans: bool,
31 #[clap(long, help = "Enables dead code elimination in the compiler.", default_value = "true")]
32 pub enable_dce: bool,
33 #[clap(long, help = "Max depth to type check nested conditionals.", default_value = "10")]
34 pub conditional_block_max_depth: usize,
35 #[clap(long, help = "Disable type checking of nested conditional branches in finalize scope.")]
36 pub disable_conditional_branch_type_checking: bool,
37 #[clap(long, help = "Write an AST snapshot immediately after parsing.")]
38 pub enable_initial_ast_snapshot: bool,
39 #[clap(long, help = "Writes all AST snapshots for the different compiler phases.")]
40 pub enable_all_ast_snapshots: bool,
41 #[clap(long, help = "Comma separated list of passes whose AST snapshots to capture.", value_delimiter = ',', num_args = 1..)]
42 pub ast_snapshots: Vec<String>,
43 #[clap(long, help = "Build tests along with the main program and dependencies.")]
44 pub build_tests: bool,
45 #[clap(long, help = "Don't use the dependency cache.")]
46 pub no_cache: bool,
47}
48
49impl Default for BuildOptions {
50 fn default() -> Self {
51 Self {
52 non_recursive: false,
53 offline: false,
54 enable_ast_spans: false,
55 enable_dce: true,
56 conditional_block_max_depth: 10,
57 disable_conditional_branch_type_checking: false,
58 enable_initial_ast_snapshot: false,
59 enable_all_ast_snapshots: false,
60 ast_snapshots: Vec::new(),
61 build_tests: false,
62 no_cache: false,
63 }
64 }
65}
66
67#[derive(Parser, Clone, Debug, Default)]
69pub struct EnvOptions {
70 #[clap(long, help = "The private key to use for the deployment. Overrides the `PRIVATE_KEY` in the `.env` file.")]
71 pub(crate) private_key: Option<String>,
72 #[clap(long, help = "The network to deploy to. Overrides the `NETWORK` in the .env file.")]
73 pub(crate) network: Option<String>,
74 #[clap(long, help = "The endpoint to deploy to. Overrides the `ENDPOINT` in the .env file.")]
75 pub(crate) endpoint: Option<String>,
76}
77
78#[derive(Parser, Clone, Debug, Default)]
80pub struct FeeOptions {
81 #[clap(
82 long,
83 help = "[UNUSED] Base fees in microcredits, delimited by `|`, and used in order. The fees must either be valid `u64` or `default`. Defaults to automatic calculation.",
84 value_delimiter = '|',
85 value_parser = parse_amount
86 )]
87 pub(crate) base_fees: Vec<Option<u64>>,
88 #[clap(
89 long,
90 help = "Priority fee in microcredits, delimited by `|`, and used in order. The fees must either be valid `u64` or `default`. Defaults to 0.",
91 value_delimiter = '|',
92 value_parser = parse_amount
93 )]
94 pub(crate) priority_fees: Vec<Option<u64>>,
95 #[clap(
96 short,
97 help = "Records to pay for fees privately, delimited by '|', and used in order. The fees must either be valid plaintext, ciphertext, or `default`. Defaults to public fees.",
98 long,
99 value_delimiter = '|',
100 value_parser = parse_record_string,
101 )]
102 fee_records: Vec<Option<String>>,
103}
104
105fn parse_amount(s: &str) -> Result<Option<u64>, String> {
107 let trimmed = s.trim();
108 if trimmed == "default" { Ok(None) } else { trimmed.parse::<u64>().map_err(|e| e.to_string()).map(Some) }
109}
110
111fn parse_record_string(s: &str) -> Result<Option<String>, String> {
113 let trimmed = s.trim();
114 if trimmed == "default" { Ok(None) } else { Ok(Some(trimmed.to_string())) }
115}
116
117fn parse_record<N: Network>(private_key: &PrivateKey<N>, record: &str) -> Result<Record<N, Plaintext<N>>> {
119 match record.starts_with("record1") {
120 true => {
121 let ciphertext = Record::<N, Ciphertext<N>>::from_str(record)?;
123 let view_key = ViewKey::try_from(private_key)?;
125 Ok(ciphertext.decrypt(&view_key)?)
127 }
128 false => Ok(Record::<N, Plaintext<N>>::from_str(record)?),
129 }
130}
131
132#[allow(clippy::type_complexity)]
134pub fn parse_fee_options<N: Network>(
135 private_key: &PrivateKey<N>,
136 fee_options: &FeeOptions,
137 k: usize,
138) -> Result<Vec<(Option<u64>, Option<u64>, Option<Record<N, Plaintext<N>>>)>> {
139 let base_fees = fee_options.base_fees.clone();
141 let priority_fees = fee_options.priority_fees.clone();
143 let parse_record = |record: &Option<String>| record.as_ref().map(|r| parse_record::<N>(private_key, r)).transpose();
145 let fee_records = fee_options.fee_records.iter().map(parse_record).collect::<Result<Vec<_>>>()?;
146
147 let base_fees = base_fees.into_iter().chain(iter::repeat(None)).take(k);
149 let priority_fees = priority_fees.into_iter().chain(iter::repeat(None)).take(k);
150 let fee_records = fee_records.into_iter().chain(iter::repeat(None)).take(k);
151
152 Ok(base_fees.zip(priority_fees).zip(fee_records).map(|((x, y), z)| (x, y, z)).collect())
153}
154
155#[derive(Parser, Clone, Debug, Default)]
157pub struct ExtraOptions {
158 #[clap(
159 short,
160 long,
161 help = "Don't ask for confirmation. DO NOT SET THIS FLAG UNLESS YOU KNOW WHAT YOU ARE DOING",
162 default_value = "false"
163 )]
164 pub(crate) yes: bool,
165 #[clap(
166 long,
167 help = "Consensus version to use. If one is not provided, the CLI will attempt to determine it from the latest block."
168 )]
169 pub(crate) consensus_version: Option<u8>,
170 #[clap(
171 long,
172 help = "Seconds to wait for a block to appear when searching for a transaction.",
173 default_value = "8"
174 )]
175 pub(crate) max_wait: usize,
176 #[clap(long, help = "Number of blocks to look at when searching for a transaction.", default_value = "12")]
177 pub(crate) blocks_to_check: usize,
178}
179
180pub fn get_consensus_version<N: Network>(
183 consensus_version: &Option<u8>,
184 endpoint: &str,
185 network: NetworkName,
186 context: &Context,
187) -> Result<ConsensusVersion> {
188 match consensus_version {
190 Some(1) => Ok(ConsensusVersion::V1),
191 Some(2) => Ok(ConsensusVersion::V2),
192 Some(3) => Ok(ConsensusVersion::V3),
193 Some(4) => Ok(ConsensusVersion::V4),
194 None => {
196 println!("Attempting to determine the consensus version from the latest block height at {endpoint}...");
197 get_latest_block_height(endpoint, network, context)
198 .and_then(|current_block_height| Ok(N::CONSENSUS_VERSION(current_block_height)?))
199 .map_err(|_| {
200 CliError::custom(
201 "Failed to get consensus version. Ensure that your endpoint is valid or provide an explicit version to use via `--consensus-version`",
202 )
203 .into()
204 })
205 }
206 Some(version) => Err(CliError::custom(format!("Invalid consensus version: {version}")).into()),
207 }
208}
209
210#[derive(Args, Clone, Debug)]
212pub struct TransactionAction {
213 #[arg(long, help = "Print the transaction to stdout.")]
214 pub print: bool,
215 #[arg(long, help = "Broadcast the transaction to the network.")]
216 pub broadcast: bool,
217 #[arg(long, help = "Save the transaction to the provided directory.")]
218 pub save: Option<String>,
219}