mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 13:56:58 +03:00
rebase
This commit is contained in:
parent
764f116afd
commit
46774633f6
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1972,6 +1972,7 @@ dependencies = [
|
||||
"toml 0.8.12",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"ureq",
|
||||
"walkdir",
|
||||
"zip",
|
||||
]
|
||||
|
@ -64,6 +64,9 @@ default = [ ]
|
||||
ci_skip = [ "leo-compiler/ci_skip" ]
|
||||
noconfig = [ ]
|
||||
|
||||
[dependencies]
|
||||
ureq = "2.9.7"
|
||||
|
||||
[dependencies.leo-ast]
|
||||
path = "./compiler/ast"
|
||||
version = "=1.11.0"
|
||||
|
@ -383,4 +383,18 @@ create_messages!(
|
||||
msg: format!("The dependency program `{name}` was not found among the manifest's dependencies."),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
conflicting_on_chain_program_name {
|
||||
args: (first: impl Display, second: impl Display),
|
||||
msg: format!("Conflicting program names given to execute on chain: `{first}` and `{second}`."),
|
||||
help: Some("Either set `--local` to execute the local program on chain, or set `--program <PROGRAM>`.".to_string()),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
missing_on_chain_program_name {
|
||||
args: (),
|
||||
msg: "The name of the program to execute on-chain is missing.".to_string(),
|
||||
help: Some("Either set `--local` to execute the local program on chain, or set `--program <PROGRAM>`.".to_string()),
|
||||
}
|
||||
);
|
||||
|
@ -140,8 +140,8 @@ create_messages!(
|
||||
|
||||
@formatted
|
||||
failed_to_retrieve_from_endpoint {
|
||||
args: (endpoint: impl Display, error: impl ErrorArg),
|
||||
msg: format!("Failed to retrieve from endpoint `{endpoint}`. Error: {error}"),
|
||||
args: (error: impl ErrorArg),
|
||||
msg: format!("{error}"),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@ -151,4 +151,46 @@ create_messages!(
|
||||
msg: format!("Compiled file at `{path}` does not exist, cannot compile parent."),
|
||||
help: Some("If you were using the `--non-recursive` flag, remove it and try again.".to_string()),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
invalid_input_id_len {
|
||||
args: (input: impl Display, expected_type: impl Display),
|
||||
msg: format!("Invalid input: {input}."),
|
||||
help: Some(format!("Type `{expected_type}` must contain exactly 61 lowercase characters or numbers.")),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
invalid_input_id {
|
||||
args: (input: impl Display, expected_type: impl Display, expected_preface: impl Display),
|
||||
msg: format!("Invalid input: {input}."),
|
||||
help: Some(format!("Type `{expected_type}` must start with \"{expected_preface}\".")),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
invalid_numerical_input {
|
||||
args: (input: impl Display),
|
||||
msg: format!("Invalid numerical input: {input}."),
|
||||
help: Some("Input must be a valid u32.".to_string()),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
invalid_range {
|
||||
args: (),
|
||||
msg: "The range must be less than or equal to 50 blocks.".to_string(),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@backtraced
|
||||
invalid_height_or_hash {
|
||||
args: (input: impl Display),
|
||||
msg: format!("Invalid input: {input}."),
|
||||
help: Some("Input must be a valid height or hash. Valid hashes are 61 characters long, composed of only numbers and lower case letters, and be prefaced with \"ab1\".".to_string()),
|
||||
}
|
||||
|
||||
@backtraced
|
||||
invalid_field {
|
||||
args: (field: impl Display),
|
||||
msg: format!("Invalid field: {field}."),
|
||||
help: Some("Field element must be numerical string with optional \"field\" suffix.".to_string()),
|
||||
}
|
||||
);
|
||||
|
@ -36,7 +36,7 @@ pub struct CLI {
|
||||
#[clap(long, global = true, help = "Path to Leo program root folder")]
|
||||
path: Option<PathBuf>,
|
||||
|
||||
#[clap(long, global = true, help = "Path to aleo program registry.")]
|
||||
#[clap(long, global = true, help = "Path to aleo program registry")]
|
||||
pub home: Option<PathBuf>,
|
||||
}
|
||||
|
||||
@ -73,6 +73,11 @@ enum Commands {
|
||||
#[clap(flatten)]
|
||||
command: Deploy,
|
||||
},
|
||||
#[clap(about = "Query live data from the Aleo network")]
|
||||
Query {
|
||||
#[clap(flatten)]
|
||||
command: Query,
|
||||
},
|
||||
#[clap(about = "Compile the current package as a program")]
|
||||
Build {
|
||||
#[clap(flatten)]
|
||||
@ -144,6 +149,7 @@ pub fn run_with_args(cli: CLI) -> Result<()> {
|
||||
|
||||
command.try_execute(context)
|
||||
}
|
||||
Commands::Query { command } => command.try_execute(context),
|
||||
Commands::Clean { command } => command.try_execute(context),
|
||||
Commands::Deploy { command } => command.try_execute(context),
|
||||
Commands::Example { command } => command.try_execute(context),
|
||||
|
@ -35,6 +35,9 @@ pub use example::Example;
|
||||
pub mod execute;
|
||||
pub use execute::Execute;
|
||||
|
||||
pub mod query;
|
||||
pub use query::Query;
|
||||
|
||||
pub mod new;
|
||||
pub use new::New;
|
||||
|
||||
|
102
leo/cli/commands/query.rs
Normal file
102
leo/cli/commands/query.rs
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
|
||||
use leo_errors::UtilError;
|
||||
|
||||
/// Query live data from the Aleo network.
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct Query {
|
||||
#[clap(
|
||||
short,
|
||||
long,
|
||||
global = true,
|
||||
help = "Endpoint to retrieve network state from. Defaults to http://api.explorer.aleo.org/v1.",
|
||||
default_value = "http://api.explorer.aleo.org/v1"
|
||||
)]
|
||||
pub endpoint: String,
|
||||
#[clap(short, long, global = true, help = "Network to use. Defaults to testnet3.", default_value = "testnet3")]
|
||||
pub(crate) network: String,
|
||||
#[clap(subcommand)]
|
||||
command: QueryCommands,
|
||||
}
|
||||
|
||||
impl Command for Query {
|
||||
type Input = ();
|
||||
type Output = ();
|
||||
|
||||
fn log_span(&self) -> Span {
|
||||
tracing::span!(tracing::Level::INFO, "Leo")
|
||||
}
|
||||
|
||||
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
let output = match self.command {
|
||||
QueryCommands::Block { command } => command.apply(context, ())?,
|
||||
QueryCommands::Transaction { command } => command.apply(context, ())?,
|
||||
QueryCommands::Program { command } => command.apply(context, ())?,
|
||||
QueryCommands::Stateroot { command } => command.apply(context, ())?,
|
||||
QueryCommands::Committee { command } => command.apply(context, ())?,
|
||||
};
|
||||
|
||||
// Make GET request to retrieve on-chain state.
|
||||
let url = format!("{}/{}/{}", self.endpoint, self.network, output);
|
||||
let response = ureq::get(&url.clone())
|
||||
.call()
|
||||
.map_err(|err| UtilError::failed_to_retrieve_from_endpoint(err, Default::default()))?;
|
||||
if response.status() == 200 {
|
||||
tracing::info!("✅ Successfully retrieved data from '{url}'.");
|
||||
// Unescape the newlines.
|
||||
println!("{}", response.into_string().unwrap().replace("\\n", "\n"));
|
||||
Ok(())
|
||||
} else {
|
||||
Err(UtilError::network_error(url, response.status(), Default::default()).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
enum QueryCommands {
|
||||
#[clap(about = "Query block information")]
|
||||
Block {
|
||||
#[clap(flatten)]
|
||||
command: Block,
|
||||
},
|
||||
#[clap(about = "Query transaction information")]
|
||||
Transaction {
|
||||
#[clap(flatten)]
|
||||
command: Transaction,
|
||||
},
|
||||
#[clap(about = "Query program source code and live mapping values")]
|
||||
Program {
|
||||
#[clap(flatten)]
|
||||
command: Program,
|
||||
},
|
||||
#[clap(about = "Query the latest stateroot")]
|
||||
Stateroot {
|
||||
#[clap(flatten)]
|
||||
command: StateRoot,
|
||||
},
|
||||
#[clap(about = "Query the current committee")]
|
||||
Committee {
|
||||
#[clap(flatten)]
|
||||
command: Committee,
|
||||
},
|
||||
}
|
@ -23,6 +23,9 @@ pub use commands::*;
|
||||
mod helpers;
|
||||
pub use helpers::*;
|
||||
|
||||
mod query_commands;
|
||||
pub use query_commands::*;
|
||||
|
||||
pub(crate) type CurrentNetwork = snarkvm::prelude::MainnetV0;
|
||||
pub(crate) const SNARKVM_COMMAND: &str = "snarkvm";
|
||||
|
||||
|
93
leo/cli/query_commands/block.rs
Normal file
93
leo/cli/query_commands/block.rs
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
|
||||
use crate::cli::context::Context;
|
||||
use clap::Parser;
|
||||
|
||||
// Query on-chain information related to blocks.
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct Block {
|
||||
#[clap(help = "Fetch a block by specifying its height or hash", required_unless_present_any = &["latest", "latest_hash", "latest_height", "range"])]
|
||||
pub(crate) id: Option<String>,
|
||||
#[arg(short, long, help = "Get the latest block", default_value = "false", conflicts_with_all(["latest_hash", "latest_height", "range", "transactions", "to_height"]))]
|
||||
pub(crate) latest: bool,
|
||||
#[arg(short, long, help = "Get the latest block hash", default_value = "false", conflicts_with_all(["latest", "latest_height", "range", "transactions", "to_height"]))]
|
||||
pub(crate) latest_hash: bool,
|
||||
#[arg(short, long, help = "Get the latest block height", default_value = "false", conflicts_with_all(["latest", "latest_hash", "range", "transactions", "to_height"]))]
|
||||
pub(crate) latest_height: bool,
|
||||
#[arg(short, long, help = "Get up to 50 consecutive blocks", number_of_values = 2, value_names = &["START_HEIGHT", "END_HEIGHT"], conflicts_with_all(["latest", "latest_hash", "latest_height", "transactions", "to_height"]))]
|
||||
pub(crate) range: Option<Vec<String>>,
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = "Get all transactions at the specified block height",
|
||||
conflicts_with("to_height"),
|
||||
default_value = "false"
|
||||
)]
|
||||
pub(crate) transactions: bool,
|
||||
#[arg(short, long, help = "Lookup the block height corresponding to a hash value", default_value = "false")]
|
||||
pub(crate) to_height: bool,
|
||||
}
|
||||
|
||||
impl Command for Block {
|
||||
type Input = ();
|
||||
type Output = String;
|
||||
|
||||
fn log_span(&self) -> Span {
|
||||
tracing::span!(tracing::Level::INFO, "Leo")
|
||||
}
|
||||
|
||||
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply(self, _context: Context, _input: Self::Input) -> Result<Self::Output> {
|
||||
// Build custom url to fetch from based on the flags and user's input.
|
||||
let url = if self.latest_height {
|
||||
"block/height/latest".to_string()
|
||||
} else if self.latest_hash {
|
||||
"block/hash/latest".to_string()
|
||||
} else if self.latest {
|
||||
"block/latest".to_string()
|
||||
} else if let Some(range) = self.range {
|
||||
// Make sure the range is composed of valid numbers.
|
||||
is_valid_numerical_input(&range[0])?;
|
||||
is_valid_numerical_input(&range[1])?;
|
||||
|
||||
// Make sure the range is not too large.
|
||||
if range[1].parse::<u32>().unwrap() - range[0].parse::<u32>().unwrap() > 50 {
|
||||
return Err(UtilError::invalid_range().into());
|
||||
}
|
||||
format!("blocks?start={}&end={}", range[0], range[1])
|
||||
} else if self.transactions {
|
||||
is_valid_numerical_input(&self.id.clone().unwrap())?;
|
||||
format!("block/{}/transactions", self.id.unwrap()).to_string()
|
||||
} else if self.to_height {
|
||||
let id = self.id.unwrap();
|
||||
is_valid_hash(&id)?;
|
||||
format!("height/{}", id).to_string()
|
||||
} else if let Some(id) = self.id {
|
||||
is_valid_height_or_hash(&id)?;
|
||||
format!("block/{}", id)
|
||||
} else {
|
||||
unreachable!("All cases are covered")
|
||||
};
|
||||
|
||||
Ok(url)
|
||||
}
|
||||
}
|
40
leo/cli/query_commands/committee.rs
Normal file
40
leo/cli/query_commands/committee.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
/// Query the committee.
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct Committee {}
|
||||
|
||||
impl Command for Committee {
|
||||
type Input = ();
|
||||
type Output = String;
|
||||
|
||||
fn log_span(&self) -> Span {
|
||||
tracing::span!(tracing::Level::INFO, "Leo")
|
||||
}
|
||||
|
||||
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
Ok("/committee/latest".to_string())
|
||||
}
|
||||
}
|
99
leo/cli/query_commands/mod.rs
Normal file
99
leo/cli/query_commands/mod.rs
Normal file
@ -0,0 +1,99 @@
|
||||
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
pub use super::*;
|
||||
|
||||
pub mod block;
|
||||
pub use block::Block;
|
||||
|
||||
pub mod program;
|
||||
pub use program::Program;
|
||||
|
||||
pub mod state_root;
|
||||
pub use state_root::StateRoot;
|
||||
|
||||
pub mod committee;
|
||||
pub mod transaction;
|
||||
pub use committee::Committee;
|
||||
|
||||
pub use transaction::Transaction;
|
||||
|
||||
use crate::cli::helpers::context::*;
|
||||
use leo_errors::{LeoError, Result, UtilError};
|
||||
|
||||
use tracing::span::Span;
|
||||
|
||||
// A valid hash is 61 characters long, with preface "ab1" and all characters lowercase or numbers.
|
||||
pub fn is_valid_hash(hash: &str) -> Result<(), LeoError> {
|
||||
if hash.len() != 61 {
|
||||
Err(UtilError::invalid_input_id_len(hash, "hash").into())
|
||||
} else if !hash.starts_with("ab1") && hash.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit()) {
|
||||
Err(UtilError::invalid_input_id(hash, "hash", "ab1").into())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// A valid transaction id is 61 characters long, with preface "at1" and all characters lowercase or numbers.
|
||||
pub fn is_valid_transaction_id(transaction: &str) -> Result<(), LeoError> {
|
||||
if transaction.len() != 61 {
|
||||
Err(UtilError::invalid_input_id_len(transaction, "transaction").into())
|
||||
} else if !transaction.starts_with("at1")
|
||||
&& transaction.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit())
|
||||
{
|
||||
Err(UtilError::invalid_input_id(transaction, "transaction", "at1").into())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// A valid transition id is 61 characters long, with preface "au1" and all characters lowercase or numbers.
|
||||
pub fn is_valid_transition_id(transition: &str) -> Result<(), LeoError> {
|
||||
if transition.len() != 61 {
|
||||
Err(UtilError::invalid_input_id_len(transition, "transition").into())
|
||||
} else if !transition.starts_with("au1") && transition.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit())
|
||||
{
|
||||
Err(UtilError::invalid_input_id(transition, "transition", "au1").into())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// A valid numerical input is a u32.
|
||||
pub fn is_valid_numerical_input(num: &str) -> Result<(), LeoError> {
|
||||
if num.parse::<u32>().is_err() { Err(UtilError::invalid_numerical_input(num).into()) } else { Ok(()) }
|
||||
}
|
||||
|
||||
// A valid height or hash.
|
||||
pub fn is_valid_height_or_hash(input: &str) -> Result<(), LeoError> {
|
||||
match (is_valid_hash(input), is_valid_numerical_input(input)) {
|
||||
(Ok(_), _) | (_, Ok(_)) => Ok(()),
|
||||
_ => Err(UtilError::invalid_height_or_hash(input).into()),
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if the string is a valid field, allowing for optional `field` suffix.
|
||||
pub fn is_valid_field(field: &str) -> Result<String, LeoError> {
|
||||
let split = field.split("field").collect::<Vec<&str>>();
|
||||
|
||||
if split.len() == 1 && split[0].chars().all(|c| c.is_numeric()) {
|
||||
Ok(format!("{}field", field))
|
||||
} else if split.len() == 2 && split[0].chars().all(|c| c.is_numeric()) && split[1].is_empty() {
|
||||
Ok(field.to_string())
|
||||
} else {
|
||||
Err(UtilError::invalid_field(field).into())
|
||||
}
|
||||
}
|
64
leo/cli/query_commands/program.rs
Normal file
64
leo/cli/query_commands/program.rs
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
/// Query program source code and live mapping values.
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct Program {
|
||||
#[clap(name = "NAME", help = "The name of the program to fetch")]
|
||||
pub(crate) name: String,
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = "Get all mappings defined in the program",
|
||||
default_value = "false",
|
||||
conflicts_with = "mapping_value"
|
||||
)]
|
||||
pub(crate) mappings: bool,
|
||||
#[arg(short, long, help = "Get the value corresponding to the specified mapping and key.", number_of_values = 2, value_names = &["MAPPING", "KEY"], conflicts_with = "mappings")]
|
||||
pub(crate) mapping_value: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl Command for Program {
|
||||
type Input = ();
|
||||
type Output = String;
|
||||
|
||||
fn log_span(&self) -> Span {
|
||||
tracing::span!(tracing::Level::INFO, "Leo")
|
||||
}
|
||||
|
||||
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// TODO: Validate program name.
|
||||
// Build custom url to fetch from based on the flags and user's input.
|
||||
let url = if let Some(mapping_info) = self.mapping_value {
|
||||
// TODO: Validate mapping name.
|
||||
format!("program/{}/mapping/{}/{}", self.name, mapping_info[0], mapping_info[1])
|
||||
} else if self.mappings {
|
||||
format!("program/{}/mappings", self.name)
|
||||
} else {
|
||||
format!("program/{}", self.name)
|
||||
};
|
||||
|
||||
Ok(url)
|
||||
}
|
||||
}
|
40
leo/cli/query_commands/state_root.rs
Normal file
40
leo/cli/query_commands/state_root.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
/// Query the latest stateroot.
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct StateRoot {}
|
||||
|
||||
impl Command for StateRoot {
|
||||
type Input = ();
|
||||
type Output = String;
|
||||
|
||||
fn log_span(&self) -> Span {
|
||||
tracing::span!(tracing::Level::INFO, "Leo")
|
||||
}
|
||||
|
||||
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
Ok("/stateRoot/latest".to_string())
|
||||
}
|
||||
}
|
68
leo/cli/query_commands/transaction.rs
Normal file
68
leo/cli/query_commands/transaction.rs
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright (C) 2019-2023 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
/// Query transaction information.
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct Transaction {
|
||||
#[clap(name = "ID", help = "The id of the transaction to fetch", required_unless_present_any = &["from_program", "from_transition", "from_io", "range"])]
|
||||
pub(crate) id: Option<String>,
|
||||
#[arg(short, long, help = "Get the transaction only if it has been confirmed", default_value = "false", conflicts_with_all(["from_io", "from_transition", "from_program"]))]
|
||||
pub(crate) confirmed: bool,
|
||||
#[arg(value_name = "INPUT_OR_OUTPUT_ID", short, long, help = "Get the transition id that an input or output id occurred in", conflicts_with_all(["from_program", "from_transition", "confirmed", "id"]))]
|
||||
pub(crate) from_io: Option<String>,
|
||||
#[arg(value_name = "TRANSITION_ID", short, long, help = "Get the id of the transaction containing the specified transition", conflicts_with_all(["from_io", "from_program", "confirmed", "id"]))]
|
||||
pub(crate) from_transition: Option<String>,
|
||||
#[arg(value_name = "PROGRAM", short, long, help = "Get the id of the transaction id that the specified program was deployed in", conflicts_with_all(["from_io", "from_transition", "confirmed", "id"]))]
|
||||
pub(crate) from_program: Option<String>,
|
||||
}
|
||||
|
||||
impl Command for Transaction {
|
||||
type Input = ();
|
||||
type Output = String;
|
||||
|
||||
fn log_span(&self) -> Span {
|
||||
tracing::span!(tracing::Level::INFO, "Leo")
|
||||
}
|
||||
|
||||
fn prelude(&self, _context: Context) -> Result<Self::Input> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// Build custom url to fetch from based on the flags and user's input.
|
||||
let url = if let Some(io_id) = self.from_io {
|
||||
let field = is_valid_field(&io_id)?;
|
||||
format!("find/transitionID/{field}")
|
||||
} else if let Some(transition) = self.from_transition {
|
||||
is_valid_transition_id(&transition)?;
|
||||
format!("find/transactionID/{transition}")
|
||||
} else if let Some(program) = self.from_program {
|
||||
// TODO: Validate program name.
|
||||
format!("find/transactionID/deployment/{program}")
|
||||
} else if let Some(id) = self.id {
|
||||
is_valid_transaction_id(&id)?;
|
||||
if self.confirmed { format!("transaction/confirmed/{}", id) } else { format!("transaction/{}", id) }
|
||||
} else {
|
||||
unreachable!("All command paths covered.")
|
||||
};
|
||||
|
||||
Ok(url)
|
||||
}
|
||||
}
|
@ -508,7 +508,7 @@ fn fetch_from_network(endpoint: &String, program: &String, network: Network) ->
|
||||
let url = format!("{}/{}/program/{}", endpoint, network.clone(), program);
|
||||
let response = ureq::get(&url.clone())
|
||||
.call()
|
||||
.map_err(|err| UtilError::failed_to_retrieve_from_endpoint(url.clone(), err, Default::default()))?;
|
||||
.map_err(|err| UtilError::failed_to_retrieve_from_endpoint(err, Default::default()))?;
|
||||
if response.status() == 200 {
|
||||
Ok(response.into_string().unwrap())
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user