use std::net::SocketAddr;
use std::path::PathBuf;
use clap::{ArgAction, Args, Parser, Subcommand};
use paralock::EvmChain;
const ABOUT: &str = "Trustless swaps between shielded ZEC and stablecoins on EVM chains, and a Paralock market maker";
const AFTER_HELP: &str = "\
Configuration:
paralock.toml, from --config <file>, $PARALOCK_CONFIG, ./paralock.toml or
<state>/paralock.toml. Keys come from environment variables or key files
(key_env, key_file), never from the file itself unless allow_inline_keys.
Devnet:
--devnet reads devnet.json from <checkout>/.paralock inside a Paralock
checkout, else $PARALOCK_HOME, else ~/.paralock. Starting and stopping the
devnet (Zcash regtest, anvil, contracts) stays in the npm CLI:
`npx paralock dev`, `npx paralock devnet up|status|down`.
Exit codes:
0 success, 1 failure, 2 usage or configuration error, 3 a swap failed after
locking ZEC (refunded, or refundable with `paralock refund <id>`).
Experimental and not audited. The Zcash leg is transparent on chain.";
#[derive(Debug, Parser)]
#[command(name = "paralock", version, about = ABOUT, after_help = AFTER_HELP, propagate_version = true)]
pub struct Cli {
#[command(flatten)]
pub global: GlobalArgs,
#[command(subcommand)]
pub command: Command,
}
#[derive(Debug, Args)]
pub struct GlobalArgs {
#[arg(long, global = true)]
pub devnet: bool,
#[arg(long, short = 'c', global = true, value_name = "FILE")]
pub config: Option<PathBuf>,
#[arg(long, global = true)]
pub json: bool,
#[arg(long, global = true, value_name = "URL")]
pub maker_url: Option<String>,
#[arg(long, global = true, value_name = "N")]
pub evm_account: Option<usize>,
#[arg(long, global = true)]
pub lightwalletd: bool,
#[arg(long, short = 'v', global = true, action = ArgAction::Count)]
pub verbose: u8,
}
#[derive(Debug, Subcommand)]
pub enum Command {
Doctor(DoctorArgs),
Quote(QuoteArgs),
Swap(SwapArgs),
Pay(PayArgs),
Swaps(SwapsArgs),
Resume(ResumeArgs),
Refund(RefundArgs),
Maker(MakerArgs),
Version,
}
fn chain(value: &str) -> Result<EvmChain, String> {
EvmChain::parse(&value.to_ascii_lowercase())
.ok_or_else(|| "expected tempo, base, ethereum, arbitrum, robinhood or hyperevm".to_owned())
}
#[derive(Debug, Args)]
pub struct DoctorArgs {
#[arg(long)]
pub maker: bool,
}
#[derive(Debug, Args)]
#[command(group = clap::ArgGroup::new("amount").required(true).args(["zec", "usd"]))]
pub struct QuoteArgs {
#[arg(long, value_name = "ZEC")]
pub zec: Option<String>,
#[arg(long, value_name = "USD")]
pub usd: Option<String>,
#[arg(long, value_parser = chain)]
pub chain: Option<EvmChain>,
#[arg(long)]
pub private: bool,
}
#[derive(Debug, Args)]
pub struct SwapCommon {
#[arg(long, value_parser = chain)]
pub chain: Option<EvmChain>,
#[arg(long)]
pub private: bool,
#[arg(long)]
pub relay: bool,
#[arg(long)]
pub no_refund: bool,
#[arg(long, short = 'y')]
pub yes: bool,
}
#[derive(Debug, Args)]
pub struct SwapArgs {
#[arg(long, value_name = "ZEC")]
pub zec: String,
#[command(flatten)]
pub common: SwapCommon,
#[arg(long)]
pub fresh_recipient: bool,
#[arg(long)]
pub standard_only: bool,
#[arg(long, value_name = "MS")]
pub jitter: Option<u64>,
#[arg(long)]
pub refund_demo: bool,
}
#[derive(Debug, Args)]
pub struct PayArgs {
#[arg(long, value_name = "USD")]
pub usd: String,
#[arg(long, value_name = "0x…")]
pub to: String,
#[arg(long)]
pub label: Option<String>,
#[command(flatten)]
pub common: SwapCommon,
}
#[derive(Debug, Args)]
pub struct SwapsArgs {
#[arg(long)]
pub all: bool,
}
#[derive(Debug, Args)]
pub struct ResumeArgs {
pub id: String,
#[arg(long)]
pub no_relay: bool,
}
#[derive(Debug, Args)]
pub struct RefundArgs {
pub id: String,
#[arg(long)]
pub no_wait: bool,
}
#[derive(Debug, Args)]
pub struct MakerArgs {
#[arg(long, value_name = "ADDR", conflicts_with = "port")]
pub listen: Option<SocketAddr>,
#[arg(long)]
pub port: Option<u16>,
#[arg(long)]
pub no_mine: bool,
}