use std::time::SystemTime;
use bech32::u5;
-use bitcoin_hashes::Hash;
-use bitcoin_hashes::sha256;
+use bitcoin::{Address, Network, PubkeyHash, ScriptHash};
+use bitcoin::util::address::{Payload, WitnessVersion};
+use bitcoin_hashes::{Hash, sha256};
use lightning::ln::PaymentSecret;
use lightning::ln::features::InvoiceFeatures;
#[cfg(any(doc, test))]
Signet,
}
+impl From<Network> for Currency {
+ fn from(network: Network) -> Self {
+ match network {
+ Network::Bitcoin => Currency::Bitcoin,
+ Network::Testnet => Currency::BitcoinTestnet,
+ Network::Regtest => Currency::Regtest,
+ Network::Signet => Currency::Signet,
+ }
+ }
+}
+
+impl From<Currency> for Network {
+ fn from(currency: Currency) -> Self {
+ match currency {
+ Currency::Bitcoin => Network::Bitcoin,
+ Currency::BitcoinTestnet => Network::Testnet,
+ Currency::Regtest => Network::Regtest,
+ Currency::Simnet => Network::Regtest,
+ Currency::Signet => Network::Signet,
+ }
+ }
+}
+
/// Tagged field which may have an unknown tag
///
/// This is not exported to bindings users as we don't currently support TaggedField
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub struct MinFinalCltvExpiryDelta(pub u64);
-// TODO: better types instead onf byte arrays
/// Fallback address in case no LN payment is possible
#[allow(missing_docs)]
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub enum Fallback {
SegWitProgram {
- version: u5,
+ version: WitnessVersion,
program: Vec<u8>,
},
- PubKeyHash([u8; 20]),
- ScriptHash([u8; 20]),
+ PubKeyHash(PubkeyHash),
+ ScriptHash(ScriptHash),
}
/// Recoverable signature
self.signed_invoice.fallbacks()
}
+ /// Returns a list of all fallback addresses as [`Address`]es
+ pub fn fallback_addresses(&self) -> Vec<Address> {
+ self.fallbacks().iter().map(|fallback| {
+ let payload = match fallback {
+ Fallback::SegWitProgram { version, program } => {
+ Payload::WitnessProgram { version: *version, program: program.to_vec() }
+ }
+ Fallback::PubKeyHash(pkh) => {
+ Payload::PubkeyHash(*pkh)
+ }
+ Fallback::ScriptHash(sh) => {
+ Payload::ScriptHash(*sh)
+ }
+ };
+
+ Address { payload, network: self.network() }
+ }).collect()
+ }
+
/// Returns a list of all routes included in the invoice
pub fn private_routes(&self) -> Vec<&PrivateRoute> {
self.signed_invoice.private_routes()
self.signed_invoice.currency()
}
+ /// Returns the network for which the invoice was issued
+ ///
+ /// This is not exported to bindings users, see [`Self::currency`] instead.
+ pub fn network(&self) -> Network {
+ self.signed_invoice.currency().into()
+ }
+
/// Returns the amount if specified in the invoice as millisatoshis.
pub fn amount_milli_satoshis(&self) -> Option<u64> {
self.signed_invoice.amount_pico_btc().map(|v| v / 10)
fn deserialize<D>(deserializer: D) -> Result<Invoice, D::Error> where D: Deserializer<'de> {
let bolt11 = String::deserialize(deserializer)?
.parse::<Invoice>()
- .map_err(|e| D::Error::custom(format!("{:?}", e)))?;
+ .map_err(|e| D::Error::custom(alloc::format!("{:?}", e)))?;
Ok(bolt11)
}
#[cfg(test)]
mod test {
+ use bitcoin::Script;
use bitcoin_hashes::hex::FromHex;
use bitcoin_hashes::sha256;
.payee_pub_key(public_key)
.expiry_time(Duration::from_secs(54321))
.min_final_cltv_expiry_delta(144)
- .fallback(Fallback::PubKeyHash([0;20]))
+ .fallback(Fallback::PubKeyHash(PubkeyHash::from_slice(&[0;20]).unwrap()))
.private_route(route_1.clone())
.private_route(route_2.clone())
.description_hash(sha256::Hash::from_slice(&[3;32][..]).unwrap())
assert_eq!(invoice.payee_pub_key(), Some(&public_key));
assert_eq!(invoice.expiry_time(), Duration::from_secs(54321));
assert_eq!(invoice.min_final_cltv_expiry_delta(), 144);
- assert_eq!(invoice.fallbacks(), vec![&Fallback::PubKeyHash([0;20])]);
+ assert_eq!(invoice.fallbacks(), vec![&Fallback::PubKeyHash(PubkeyHash::from_slice(&[0;20]).unwrap())]);
+ let address = Address::from_script(&Script::new_p2pkh(&PubkeyHash::from_slice(&[0;20]).unwrap()), Network::Testnet).unwrap();
+ assert_eq!(invoice.fallback_addresses(), vec![address]);
assert_eq!(invoice.private_routes(), vec![&PrivateRoute(route_1), &PrivateRoute(route_2)]);
assert_eq!(
invoice.description(),