forked from payjoin/rust-payjoin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmod.rs
More file actions
150 lines (123 loc) · 5.16 KB
/
mod.rs
File metadata and controls
150 lines (123 loc) · 5.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use std::path::PathBuf;
use clap::{value_parser, Parser, Subcommand};
use payjoin::bitcoin::amount::ParseAmountError;
use payjoin::bitcoin::{Amount, FeeRate};
use payjoin::Url;
use serde::Deserialize;
#[derive(Debug, Clone, Deserialize, Parser)]
pub struct Flags {
#[arg(long = "bip77", help = "Use BIP77 (v2) protocol (default)", action = clap::ArgAction::SetTrue)]
pub bip77: Option<bool>,
#[arg(long = "bip78", help = "Use BIP78 (v1) protocol", action = clap::ArgAction::SetTrue)]
pub bip78: Option<bool>,
}
#[derive(Debug, Parser)]
#[command(
version = env!("CARGO_PKG_VERSION"),
about = "Payjoin - bitcoin scaling, savings, and privacy by default",
long_about = None,
subcommand_required = true
)]
pub struct Cli {
#[command(flatten)]
pub flags: Flags,
#[command(subcommand)]
pub command: Commands,
#[arg(long, short = 'd', help = "Sets a custom database path")]
pub db_path: Option<PathBuf>,
#[arg(long = "max-fee-rate", short = 'f', help = "The maximum fee rate to accept in sat/vB")]
pub max_fee_rate: Option<FeeRate>,
#[arg(
long,
short = 'r',
num_args(1),
help = "The URL of the Bitcoin RPC host, e.g. regtest default is http://localhost:18443"
)]
pub rpchost: Option<Url>,
#[arg(
long = "cookie-file",
short = 'c',
num_args(1),
help = "Path to the cookie file of the bitcoin node"
)]
pub cookie_file: Option<PathBuf>,
#[arg(long = "rpcuser", num_args(1), help = "The username for the bitcoin node")]
pub rpcuser: Option<String>,
#[arg(long = "rpcpassword", num_args(1), help = "The password for the bitcoin node")]
pub rpcpassword: Option<String>,
#[cfg(feature = "v1")]
#[arg(long = "port", help = "The local port to listen on")]
pub port: Option<u16>,
#[cfg(feature = "v1")]
#[arg(long = "pj-endpoint", help = "The `pj=` endpoint to receive the payjoin request", value_parser = value_parser!(Url))]
pub pj_endpoint: Option<Url>,
#[cfg(feature = "v2")]
#[arg(long = "ohttp-relays", help = "One or more ohttp relay URLs, comma-separated", value_parser = value_parser!(Url), value_delimiter = ',', action = clap::ArgAction::Append)]
pub ohttp_relays: Option<Vec<Url>>,
#[cfg(feature = "v2")]
#[arg(long = "ohttp-keys", help = "The ohttp key config file path", value_parser = value_parser!(PathBuf))]
pub ohttp_keys: Option<PathBuf>,
#[cfg(feature = "v2")]
#[arg(long = "pj-directory", help = "The directory to store payjoin requests", value_parser = value_parser!(Url))]
pub pj_directory: Option<Url>,
#[cfg(feature = "_manual-tls")]
#[arg(long = "root-certificate", help = "Specify a TLS certificate to be added as a root", value_parser = value_parser!(PathBuf))]
pub root_certificate: Option<PathBuf>,
#[cfg(feature = "_manual-tls")]
#[arg(long = "certificate-key", help = "Specify the certificate private key", value_parser = value_parser!(PathBuf))]
pub certificate_key: Option<PathBuf>,
}
#[derive(Subcommand, Debug)]
pub enum Commands {
/// Send a payjoin payment
Send {
/// The `bitcoin:...` payjoin uri to send to
#[arg(required = true)]
bip21: String,
/// Fee rate in sat/vB
#[arg(required = true, short, long = "fee-rate", value_parser = parse_fee_rate_in_sat_per_vb)]
fee_rate: FeeRate,
},
/// Receive a payjoin payment
Receive {
/// The amount to receive in satoshis
#[arg(required = true, value_parser = parse_amount_in_sat)]
amount: Amount,
/// The maximum effective fee rate the receiver is willing to pay (in sat/vB)
#[arg(short, long = "max-fee-rate", value_parser = parse_fee_rate_in_sat_per_vb)]
max_fee_rate: Option<FeeRate>,
#[cfg(feature = "v1")]
/// The local port to listen on
#[arg(short, long = "port")]
port: Option<u16>,
#[cfg(feature = "v1")]
/// The `pj=` endpoint to receive the payjoin request
#[arg(long = "pj-endpoint", value_parser = parse_boxed_url)]
pj_endpoint: Option<Box<Url>>,
#[cfg(feature = "v2")]
/// The directory to store payjoin requests
#[arg(long = "pj-directory", value_parser = parse_boxed_url)]
pj_directory: Option<Box<Url>>,
#[cfg(feature = "v2")]
/// The path to the ohttp keys file
#[arg(long = "ohttp-keys", value_parser = value_parser!(PathBuf))]
ohttp_keys: Option<PathBuf>,
},
/// Resume pending payjoins (BIP77/v2 only)
#[cfg(feature = "v2")]
Resume,
#[cfg(feature = "v2")]
/// Show payjoin session history
History,
}
pub fn parse_amount_in_sat(s: &str) -> Result<Amount, ParseAmountError> {
Amount::from_str_in(s, payjoin::bitcoin::Denomination::Satoshi)
}
pub fn parse_fee_rate_in_sat_per_vb(s: &str) -> Result<FeeRate, std::num::ParseFloatError> {
let fee_rate_sat_per_vb: f32 = s.parse()?;
let fee_rate_sat_per_kwu = fee_rate_sat_per_vb * 250.0_f32;
Ok(FeeRate::from_sat_per_kwu(fee_rate_sat_per_kwu.ceil() as u64))
}
fn parse_boxed_url(s: &str) -> Result<Box<Url>, String> {
s.parse::<Url>().map(Box::new).map_err(|e| e.to_string())
}