leo_lang/cli/commands/query/
utils.rs

1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use leo_errors::{LeoError, Result, UtilError};
18
19// A valid hash is 61 characters long, with preface "ab1" and all characters lowercase or numbers.
20pub fn is_valid_hash(hash: &str) -> Result<(), LeoError> {
21    if hash.len() != 61 {
22        Err(UtilError::invalid_input_id_len(hash, "hash").into())
23    } else if !hash.starts_with("ab1") && hash.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit()) {
24        Err(UtilError::invalid_input_id(hash, "hash", "ab1").into())
25    } else {
26        Ok(())
27    }
28}
29
30// A valid transaction id is 61 characters long, with preface "at1" and all characters lowercase or numbers.
31pub fn is_valid_transaction_id(transaction: &str) -> Result<(), LeoError> {
32    if transaction.len() != 61 {
33        Err(UtilError::invalid_input_id_len(transaction, "transaction").into())
34    } else if !transaction.starts_with("at1")
35        && transaction.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit())
36    {
37        Err(UtilError::invalid_input_id(transaction, "transaction", "at1").into())
38    } else {
39        Ok(())
40    }
41}
42
43// A valid transition id is 61 characters long, with preface "au1" and all characters lowercase or numbers.
44pub fn is_valid_transition_id(transition: &str) -> Result<(), LeoError> {
45    if transition.len() != 61 {
46        Err(UtilError::invalid_input_id_len(transition, "transition").into())
47    } else if !transition.starts_with("au1") && transition.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit())
48    {
49        Err(UtilError::invalid_input_id(transition, "transition", "au1").into())
50    } else {
51        Ok(())
52    }
53}
54
55// A valid numerical input is a u32.
56pub fn is_valid_numerical_input(num: &str) -> Result<(), LeoError> {
57    if num.parse::<u32>().is_err() { Err(UtilError::invalid_numerical_input(num).into()) } else { Ok(()) }
58}
59
60// A valid height or hash.
61pub fn is_valid_height_or_hash(input: &str) -> Result<(), LeoError> {
62    match (is_valid_hash(input), is_valid_numerical_input(input)) {
63        (Ok(_), _) | (_, Ok(_)) => Ok(()),
64        _ => Err(UtilError::invalid_height_or_hash(input).into()),
65    }
66}
67
68// Checks if the string is a valid field, allowing for optional `field` suffix.
69pub fn is_valid_field(field: &str) -> Result<String, LeoError> {
70    let split = field.split("field").collect::<Vec<&str>>();
71
72    if split.len() == 1 && split[0].chars().all(|c| c.is_numeric()) {
73        Ok(format!("{}field", field))
74    } else if split.len() == 2 && split[0].chars().all(|c| c.is_numeric()) && split[1].is_empty() {
75        Ok(field.to_string())
76    } else {
77        Err(UtilError::invalid_field(field).into())
78    }
79}