1use super::*;
2
3pub mod balances;
4pub mod decode;
5pub mod env;
6pub mod epochs;
7pub mod find;
8pub mod index;
9pub mod list;
10pub mod parse;
11pub mod runes;
12pub mod server;
13mod settings;
14pub mod subsidy;
15pub mod supply;
16pub mod teleburn;
17pub mod traits;
18pub mod verify;
19pub mod wallet;
20pub mod wallets;
21
22#[derive(Debug, Parser)]
23pub(crate) enum Subcommand {
24 #[command(about = "List all rune balances")]
25 Balances,
26 #[command(about = "Decode a transaction")]
27 Decode(decode::Decode),
28 #[command(about = "Start a regtest ord and bitcoind instance")]
29 Env(env::Env),
30 #[command(about = "List the first satoshis of each reward epoch")]
31 Epochs,
32 #[command(about = "Find a satoshi's current location")]
33 Find(find::Find),
34 #[command(subcommand, about = "Index commands")]
35 Index(index::IndexSubcommand),
36 #[command(about = "List the satoshis in an output")]
37 List(list::List),
38 #[command(about = "Parse a satoshi from ordinal notation")]
39 Parse(parse::Parse),
40 #[command(about = "List all runes")]
41 Runes,
42 #[command(about = "Run the explorer server")]
43 Server(server::Server),
44 #[command(about = "Display settings")]
45 Settings,
46 #[command(about = "Display information about a block's subsidy")]
47 Subsidy(subsidy::Subsidy),
48 #[command(about = "Display Bitcoin supply information")]
49 Supply,
50 #[command(about = "Generate teleburn addresses")]
51 Teleburn(teleburn::Teleburn),
52 #[command(about = "Display satoshi traits")]
53 Traits(traits::Traits),
54 #[command(about = "Verify BIP322 signature")]
55 Verify(verify::Verify),
56 #[command(about = "Wallet commands")]
57 Wallet(wallet::WalletCommand),
58 #[command(about = "List all Bitcoin Core wallets")]
59 Wallets,
60}
61
62impl Subcommand {
63 pub(crate) fn run(self, settings: Settings) -> SubcommandResult {
64 match self {
65 Self::Balances => balances::run(settings),
66 Self::Decode(decode) => decode.run(settings),
67 Self::Env(env) => env.run(),
68 Self::Epochs => epochs::run(),
69 Self::Find(find) => find.run(settings),
70 Self::Index(index) => index.run(settings),
71 Self::List(list) => list.run(settings),
72 Self::Parse(parse) => parse.run(),
73 Self::Runes => runes::run(settings),
74 Self::Server(server) => {
75 let index = Arc::new(Index::open(&settings)?);
76 let handle = axum_server::Handle::new();
77 LISTENERS.lock().unwrap().push(handle.clone());
78 server.run(settings, index, handle, None)
79 }
80 Self::Settings => settings::run(settings),
81 Self::Subsidy(subsidy) => subsidy.run(),
82 Self::Supply => supply::run(),
83 Self::Teleburn(teleburn) => teleburn.run(),
84 Self::Traits(traits) => traits.run(),
85 Self::Verify(verify) => verify.run(),
86 Self::Wallet(wallet) => wallet.run(settings),
87 Self::Wallets => wallets::run(settings),
88 }
89 }
90}
91
92#[derive(clap::ValueEnum, Debug, Clone, Copy, Serialize, Deserialize, Default)]
93pub enum OutputFormat {
94 #[default]
95 Json,
96 Yaml,
97 Minify,
98}
99
100pub trait Output: Send {
101 fn print(&self, format: OutputFormat);
102}
103
104impl<T> Output for T
105where
106 T: Serialize + Send,
107{
108 fn print(&self, format: OutputFormat) {
109 match format {
110 OutputFormat::Json => serde_json::to_writer_pretty(io::stdout(), self).ok(),
111 OutputFormat::Yaml => serde_yaml::to_writer(io::stdout(), self).ok(),
112 OutputFormat::Minify => serde_json::to_writer(io::stdout(), self).ok(),
113 };
114 println!();
115 }
116}
117
118pub(crate) type SubcommandResult = Result<Option<Box<dyn Output>>>;