use clap::Parser;
pub const LONG_ABOUT: &str = r#" / \
) (( )) (
(@) /|\ ))_(( /|\ (@)
|-| / | \ (/\|/\) / | \ |-|
| |---------/--|-voV---\>|</--Vov-|--\--------| |
| | '^' (o o) '^' | |
| | STELLAR DATA v0.1.5 | |
| |___________________________________________| |
|-| / /\ / ( ( \ /\ \ |-|
(@) | / V \ \ V \ | (@)
|/ _) )_ \|
'\ /'
'
Query Stellar blockchain data using RPC & Public data lake.
Downloads XDR data, decompresses it, and converts to JSON.
Examples:
stellar-data --query balance --address GG..123 --token xlm
stellar-data --query price --asset btc
stellar-data --query price --asset CB23WRD...
stellar-data --query transactions --ledger 50000000
stellar-data --query address --ledger 63864-63900 --address GABC...
stellar-data --query ttl --address CABC...
stellar-data --server --port 8080
stellar-data --help (Provides more detailed options)
For more information: https://github.com/jamesbachini/Stellar-Data"#;
#[derive(Parser, Debug)]
#[command(
author,
version,
about,
long_about = LONG_ABOUT
)]
pub struct Args {
#[arg(
short,
long,
allow_hyphen_values = true,
value_name = "LEDGER",
help = "Ledger/block number, range, or negative value for recent blocks"
)]
pub ledger: Option<String>,
#[arg(
short,
long,
default_value = "all",
value_name = "TYPE",
help = "Query type: 'all', 'transactions', 'address', 'contract', 'function', 'balance', 'price', or 'ttl'"
)]
pub query: String,
#[arg(
short,
long,
value_name = "ADDRESS",
help = "Stellar address or contract address to search for"
)]
pub address: Option<String>,
#[arg(
short = 'n',
long,
value_name = "NAME",
help = "Function name to search for (required with --query function)"
)]
pub name: Option<String>,
#[arg(
short = 't',
long,
value_name = "TOKEN",
help = "Token contract address or shortcut (xlm, usdc, kale)"
)]
pub token: Option<String>,
#[arg(
short = 'A',
long,
value_name = "ASSET",
help = "Asset symbol or contract address for price queries"
)]
pub asset: Option<String>,
#[arg(
short = 's',
long,
help = "Start API server mode"
)]
pub server: bool,
#[arg(
short = 'p',
long,
default_value = "80",
value_name = "PORT",
help = "Port number for API server"
)]
pub port: u16,
}
impl Args {
pub fn validate(&self) -> anyhow::Result<()> {
if self.server {
return Ok(());
}
match self.query.as_str() {
"address" | "contract" => {
if self.address.is_none() {
anyhow::bail!("--address is required when using --query {}", self.query);
}
if self.ledger.is_none() {
anyhow::bail!("--ledger is required when using --query {}", self.query);
}
}
"function" => {
if self.name.is_none() {
anyhow::bail!("--name is required when using --query function");
}
if self.ledger.is_none() {
anyhow::bail!("--ledger is required when using --query function");
}
}
"balance" => {
if self.address.is_none() {
anyhow::bail!("--address is required when using --query balance");
}
if self.token.is_none() {
anyhow::bail!("--token is required when using --query balance");
}
}
"price" => {
if self.asset.is_none() {
anyhow::bail!("--asset is required when using --query price");
}
}
"ttl" => {
if self.address.is_none() {
anyhow::bail!("--address is required when using --query ttl");
}
}
"all" | "transactions" => {
if self.ledger.is_none() {
anyhow::bail!("--ledger is required when using --query {}", self.query);
}
}
_ => {
anyhow::bail!(
"Unsupported query type: {}. Use 'all', 'transactions', 'address', 'contract', 'function', 'balance', 'price', or 'ttl'",
self.query
);
}
}
Ok(())
}
}