use std::{fmt::Display, net::SocketAddr, path::PathBuf};
use clap::{Args, Parser, Subcommand, ValueEnum};
use clap_complete::Shell;
#[derive(ValueEnum, Clone, Debug)]
pub enum Network {
Mainnet,
Testnet,
Regtest,
}
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct Cli {
#[structopt(short, long, default_value = "testnet", env)]
pub network: Network,
#[arg(long, env)]
pub addr: Option<SocketAddr>,
#[command(subcommand)]
pub command: CliCommand,
}
#[derive(Subcommand, Debug)]
pub enum CliCommand {
Server(ServerArgs),
Signer(SignerArgs),
Wallet(WalletArgs),
Liquidex(LiquidexArgs),
Asset(AssetArgs),
Amp2(Amp2Args),
Schema(SchemaArgs),
#[clap(hide = true)]
GenerateCompletion { shell: Shell },
#[clap(hide = true)]
#[cfg(feature = "bindings")]
Generate {
#[arg(long)]
library: String,
#[arg(long)]
language: String,
#[arg(long)]
out_dir: String,
},
}
#[allow(dead_code)] impl CliCommand {
#[cfg(not(feature = "bindings"))]
pub(crate) fn requires_server_running(&self) -> bool {
!matches!(
self,
CliCommand::Server(crate::args::ServerArgs {
command: ServerCommand::Start { .. },
}) | CliCommand::GenerateCompletion { .. }
)
}
#[cfg(feature = "bindings")]
pub(crate) fn requires_server_running(&self) -> bool {
!matches!(
self,
CliCommand::Server(crate::args::ServerArgs {
command: ServerCommand::Start { .. },
}) | CliCommand::GenerateCompletion { .. }
| CliCommand::Generate { .. }
)
}
}
#[derive(Debug, Args)]
pub struct SignerArgs {
#[command(subcommand)]
pub command: SignerCommand,
}
#[derive(Debug, Args)]
pub struct SchemaArgs {
#[command(subcommand)]
pub command: DirectionCommand,
}
#[derive(Debug, Subcommand)]
pub enum DirectionCommand {
Request(MainCommandArgs),
Response(MainCommandArgs),
}
#[derive(Debug, Args)]
pub struct MainCommandArgs {
#[command(subcommand)]
pub command: MainCommand,
}
#[derive(Debug, Subcommand)]
#[clap(disable_help_flag = true, disable_help_subcommand = true)]
pub enum MainCommand {
Server(ServerSubCommands),
Wallet(WalletSubCommands),
Signer(SignerSubCommands),
Asset(AssetSubCommands),
Amp2(Amp2SubCommands),
Schema,
}
#[derive(Debug, Args)]
pub struct ServerSubCommands {
#[command(subcommand)]
pub command: ServerSubCommandsEnum,
}
#[derive(Debug, Subcommand, ValueEnum, Clone)]
pub enum ServerSubCommandsEnum {
Scan,
Stop,
}
#[derive(Debug, Args)]
pub struct WalletSubCommands {
#[command(subcommand)]
pub command: WalletSubCommandsEnum,
}
#[derive(Debug, Subcommand, ValueEnum, Clone)]
pub enum WalletSubCommandsEnum {
Load,
Unload,
List,
Address,
Balance,
Send,
Issue,
Reissue,
MultisigDesc,
Broadcast,
Details,
Combine,
PsetDetails,
Utxos,
Txs,
SetTxMemo,
SetAddrMemo,
}
#[derive(Debug, Args)]
pub struct SignerSubCommands {
#[command(subcommand)]
pub command: SignerSubCommandsEnum,
}
#[derive(Debug, Subcommand, ValueEnum, Clone)]
pub enum SignerSubCommandsEnum {
Generate,
JadeId,
LoadSoftware,
LoadJade,
LoadExternal,
Unload,
Details,
List,
Sign,
SinglesigDesc,
Xpub,
DeriveBip85,
}
#[derive(Debug, Args)]
pub struct AssetSubCommands {
#[command(subcommand)]
pub command: AssetSubCommandsEnum,
}
#[derive(Debug, Subcommand, ValueEnum, Clone)]
pub enum AssetSubCommandsEnum {
Contract,
Details,
List,
Insert,
Remove,
Publish,
}
#[derive(Debug, Args)]
pub struct Amp2SubCommands {
#[command(subcommand)]
pub command: Amp2SubCommandsEnum,
}
#[derive(Debug, Subcommand, ValueEnum, Clone)]
pub enum Amp2SubCommandsEnum {
Descriptor,
Register,
Cosign,
}
#[derive(ValueEnum, Clone, Debug)]
pub enum SignerKind {
Software,
Serial,
External,
}
impl std::fmt::Display for SignerKind {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
SignerKind::Software => write!(f, "software"),
SignerKind::Serial => write!(f, "serial"),
SignerKind::External => write!(f, "external"),
}
}
}
#[derive(ValueEnum, Clone, Debug)]
pub enum XpubKind {
Bip84,
Bip49,
Bip87,
}
impl std::fmt::Display for XpubKind {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
XpubKind::Bip84 => write!(f, "bip84"),
XpubKind::Bip49 => write!(f, "bip49"),
XpubKind::Bip87 => write!(f, "bip87"),
}
}
}
#[derive(Debug, Subcommand)]
pub enum SignerCommand {
Generate,
JadeId {
#[arg(long)]
emulator: Option<SocketAddr>,
},
LoadSoftware {
#[arg(short, long, env)]
signer: String,
#[arg(long)]
mnemonic: String,
#[arg(long, required(true))]
persist: Option<bool>,
},
LoadJade {
#[arg(short, long, env)]
signer: String,
#[arg(long)]
id: String,
#[arg(long)]
emulator: Option<SocketAddr>,
},
LoadExternal {
#[arg(short, long, env)]
signer: String,
#[arg(long)]
fingerprint: String,
},
Details {
#[arg(short, long, env)]
signer: String,
},
Unload {
#[arg(short, long, env)]
signer: String,
},
List,
Sign {
#[arg(short, long, env)]
signer: String,
#[arg(long)]
pset: String,
},
SinglesigDesc {
#[arg(short, long, env)]
signer: String,
#[arg(long)]
descriptor_blinding_key: BlindingKeyKind,
#[arg(long)]
kind: SinglesigKind,
},
Xpub {
#[arg(short, long, env)]
signer: String,
#[arg(long)]
kind: XpubKind,
},
DeriveBip85 {
#[arg(short, long, env)]
signer: String,
#[arg(long, default_value = "0")]
index: u32,
#[arg(long, default_value = "12")]
word_count: u32,
},
RegisterMultisig {
#[arg(short, long, env)]
signer: String,
#[arg(long)]
wallet: String,
},
}
#[derive(ValueEnum, Clone, Debug)]
pub enum BlindingKeyKind {
Slip77,
Slip77Rand,
Elip151,
}
impl Display for BlindingKeyKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BlindingKeyKind::Slip77 => write!(f, "slip77"),
BlindingKeyKind::Slip77Rand => write!(f, "slip77-rand"),
BlindingKeyKind::Elip151 => write!(f, "elip151"),
}
}
}
#[derive(ValueEnum, Clone, Debug)]
pub enum SinglesigKind {
Wpkh,
Shwpkh,
}
impl Display for SinglesigKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SinglesigKind::Wpkh => write!(f, "wpkh"),
SinglesigKind::Shwpkh => write!(f, "shwpkh"),
}
}
}
#[derive(ValueEnum, Clone, Debug)]
pub enum MultisigKind {
Wsh,
}
impl Display for MultisigKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MultisigKind::Wsh => write!(f, "wsh"),
}
}
}
#[derive(Debug, Args)]
pub struct WalletArgs {
#[command(subcommand)]
pub command: WalletCommand,
}
#[derive(Debug, Subcommand)]
pub enum WalletCommand {
Load {
#[arg(short, long, env)]
wallet: String,
#[arg(short, long)]
descriptor: String,
},
Unload {
#[arg(short, long, env)]
wallet: String,
},
List,
Address {
#[arg(short, long, env)]
wallet: String,
#[arg(long)]
index: Option<u32>,
#[arg(short, long, env)]
signer: Option<String>,
#[arg(long)]
with_text_qr: bool,
#[arg(long)]
with_uri_qr: Option<u8>,
},
Balance {
#[arg(short, long, env)]
wallet: String,
#[arg(long, action)]
with_tickers: bool,
},
Send {
#[arg(short, long, env)]
wallet: String,
#[arg(long, required = true)]
recipient: Vec<String>,
#[arg(long)]
fee_rate: Option<f32>,
},
Drain {
#[arg(short, long, env)]
wallet: String,
#[arg(long)]
address: String,
#[arg(long)]
fee_rate: Option<f32>,
},
Issue {
#[arg(short, long, env)]
wallet: String,
#[arg(long)]
satoshi_asset: u64,
#[arg(long)]
address_asset: Option<String>,
#[arg(long)]
satoshi_token: u64,
#[arg(long)]
address_token: Option<String>,
#[arg(long)]
contract: Option<String>,
#[arg(long)]
fee_rate: Option<f32>,
},
Reissue {
#[arg(short, long, env)]
wallet: String,
#[arg(long)]
asset: String,
#[arg(long)]
satoshi_asset: u64,
#[arg(long)]
address_asset: Option<String>,
#[arg(long)]
fee_rate: Option<f32>,
},
Burn {
#[arg(short, long, env)]
wallet: String,
#[arg(long)]
asset: String,
#[arg(long)]
satoshi_asset: u64,
#[arg(long)]
fee_rate: Option<f32>,
},
MultisigDesc {
#[arg(long)]
descriptor_blinding_key: BlindingKeyKind,
#[arg(long)]
kind: MultisigKind,
#[arg(long)]
threshold: u32,
#[arg(long, required = true)]
keyorigin_xpub: Vec<String>,
},
Broadcast {
#[arg(short, long, env)]
wallet: String,
#[arg(long)]
dry_run: bool,
#[arg(long)]
pset: String,
},
Details {
#[arg(short, long, env)]
wallet: String,
},
Combine {
#[arg(short, long, env)]
wallet: String,
#[arg(short, long, required = true)]
pset: Vec<String>,
},
PsetDetails {
#[arg(short, long, env)]
wallet: String,
#[arg(short, long, required = true)]
pset: String,
#[arg(long, action)]
with_tickers: bool,
},
Utxos {
#[arg(short, long, env)]
wallet: String,
},
Txs {
#[arg(short, long, env)]
wallet: String,
#[arg(long, action)]
with_tickers: bool,
},
Tx {
#[arg(short, long, env)]
wallet: String,
#[arg(short, long)]
txid: String,
#[arg(long, action)]
fetch: bool,
},
SetTxMemo {
#[arg(short, long, env)]
wallet: String,
#[arg(long)]
txid: String,
#[arg(long)]
memo: String,
},
SetAddrMemo {
#[arg(short, long)]
wallet: String,
#[arg(long)]
address: String,
#[arg(long)]
memo: String,
},
}
#[derive(Debug, Args)]
pub struct LiquidexArgs {
#[command(subcommand)]
pub command: LiquidexCommand,
}
#[derive(Debug, Subcommand)]
pub enum LiquidexCommand {
Make {
#[arg(short, long, env)]
wallet: String,
#[arg(short, long, required = true)]
txid: String,
#[arg(short, long, required = true)]
vout: u32,
#[arg(short, long, required = true)]
asset: String,
#[arg(short, long, required = true)]
satoshi: u64,
},
Take {
#[arg(short, long, env)]
wallet: String,
#[arg(short, long, required = true)]
proposal: String,
},
ToProposal {
#[arg(short, long, required = true)]
pset: String,
},
}
#[derive(Debug, Args)]
pub struct AssetArgs {
#[command(subcommand)]
pub command: AssetCommand,
}
#[derive(Debug, Subcommand)]
pub enum AssetCommand {
Contract {
#[arg(long)]
domain: String,
#[arg(long)]
issuer_pubkey: String,
#[arg(long)]
name: String,
#[arg(long, default_value = "0")]
precision: u8,
#[arg(long)]
ticker: String,
#[arg(long, default_value = "0")]
version: u8,
},
Details {
#[arg(short, long)]
asset: String,
},
List,
Insert {
#[arg(short, long)]
asset: String,
#[arg(long)]
contract: String,
#[arg(long)]
issuance_tx: String,
},
Remove {
#[arg(short, long)]
asset: String,
},
FromRegistry {
#[arg(short, long)]
asset: String,
},
Publish {
#[arg(short, long)]
asset: String,
},
}
#[derive(Debug, Args)]
pub struct Amp2Args {
#[command(subcommand)]
pub command: Amp2Command,
}
#[derive(Debug, Subcommand)]
pub enum Amp2Command {
Descriptor {
#[arg(short, long, env)]
signer: String,
},
Register {
#[arg(short, long, env)]
signer: String,
},
Cosign {
#[arg(short, long)]
pset: String,
},
}
#[derive(Debug, Args)]
pub struct ServerArgs {
#[command(subcommand)]
pub command: ServerCommand,
}
#[derive(ValueEnum, Clone, Debug)]
pub enum ServerType {
Electrum,
Esplora,
Waterfalls,
}
impl std::fmt::Display for ServerType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
ServerType::Electrum => write!(f, "electrum"),
ServerType::Esplora => write!(f, "esplora"),
ServerType::Waterfalls => write!(f, "waterfalls"),
}
}
}
#[derive(Debug, Subcommand)]
pub enum ServerCommand {
Start {
#[arg(short, long)]
server_url: Option<String>,
#[arg(long, default_value = "electrum")]
server_type: ServerType,
#[arg(long)]
registry_url: Option<String>,
#[arg(long)]
datadir: Option<PathBuf>,
#[arg(long)]
timeout: Option<u64>,
#[arg(long)]
scanning_interval: Option<u64>,
},
Scan,
Stop,
}