|
|
|
|
|
|
|
|
| use clap::{Parser, Subcommand};
|
| use std::fs;
|
| use std::io::{self, Read};
|
|
|
| use crate::{sovereign_address, sovereign_address_bytes, worm_receipt, verify_address, verify_receipt};
|
|
|
| #[derive(Parser)]
|
| #[command(name = "snapaddr", about = "SnapKitty Sovereign Addressing")]
|
| pub struct Cli {
|
| #[command(subcommand)]
|
| pub command: Commands,
|
| }
|
|
|
| #[derive(Subcommand)]
|
| pub enum Commands {
|
|
|
| Encode {
|
|
|
| #[arg(value_name = "FILE")]
|
| file: Option<String>,
|
| },
|
|
|
|
|
| Bytes {
|
|
|
| #[arg(value_name = "FILE")]
|
| file: Option<String>,
|
| },
|
|
|
|
|
| Receipt {
|
|
|
| #[arg(value_name = "FILE")]
|
| file: Option<String>,
|
| },
|
|
|
|
|
| Verify {
|
|
|
| #[arg(value_name = "FILE")]
|
| file: String,
|
|
|
|
|
| #[arg(long)]
|
| address: Option<String>,
|
| },
|
|
|
|
|
| Validate {
|
|
|
| #[arg(value_name = "FILE")]
|
| file: Option<String>,
|
| },
|
| }
|
|
|
|
|
| fn read_json(file: Option<&str>) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
|
| let input = match file {
|
| Some(path) => fs::read_to_string(path)?,
|
| None => {
|
| let mut buf = String::new();
|
| io::stdin().read_to_string(&mut buf)?;
|
| buf
|
| }
|
| };
|
|
|
| Ok(serde_json::from_str(&input)?)
|
| }
|
|
|
|
|
| pub fn run() -> Result<(), Box<dyn std::error::Error>> {
|
| let cli = Cli::parse();
|
|
|
| match cli.command {
|
| Commands::Encode { file } => {
|
| let value = read_json(file.as_deref())?;
|
| let addr = sovereign_address(&value)?;
|
| println!("{}", addr);
|
| }
|
|
|
| Commands::Bytes { file } => {
|
| let value = read_json(file.as_deref())?;
|
| let bytes = sovereign_address_bytes(&value)?;
|
| for b in &bytes {
|
| print!("{:02x}", b);
|
| }
|
| println!();
|
| }
|
|
|
| Commands::Receipt { file } => {
|
| let value = read_json(file.as_deref())?;
|
| let receipt = worm_receipt(&value)?;
|
| println!("{}", serde_json::to_string_pretty(&receipt)?);
|
| }
|
|
|
| Commands::Verify { file, address } => {
|
| let value = read_json(Some(&file))?;
|
|
|
| if let Some(addr) = address {
|
| let ok = verify_address(&value, &addr)?;
|
| if ok {
|
| println!("✓ Address verified");
|
| } else {
|
| println!("✗ Address mismatch");
|
| std::process::exit(1);
|
| }
|
| } else {
|
|
|
| let receipt = worm_receipt(&value)?;
|
| let ok = verify_receipt(&receipt)?;
|
| if ok {
|
| println!("✓ Receipt verified");
|
| println!("{}", serde_json::to_string_pretty(&receipt)?);
|
| } else {
|
| println!("✗ Receipt verification failed");
|
| std::process::exit(1);
|
| }
|
| }
|
| }
|
|
|
| Commands::Validate { file } => {
|
| let value = read_json(file.as_deref())?;
|
| let result = crate::admissibility::validate_admissible(&value);
|
| match result {
|
| Ok(()) => println!("✓ JSON is admissible"),
|
| Err(e) => {
|
| println!("✗ Not admissible: {}", e);
|
| std::process::exit(1);
|
| }
|
| }
|
| }
|
| }
|
|
|
| Ok(())
|
| }
|
|
|