btcpay 0.3.0

Rust BTCPayServer client
Documentation
use std::collections::HashMap;

use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Invoice {
    pub url: String,
    pub pos_data: Option<String>,
    pub btc_price: Option<String>,
    pub btc_due: Option<String>,
    #[serde(default)]
    pub crypto_info: Vec<CryptoInfo>,
    pub price: f32,
    pub currency: String,
    #[serde(default)]
    pub ex_rates: Option<HashMap<String, f32>>,
    pub buyer_total_btc_amount: Option<String>,
    pub item_desc: Option<String>,
    pub item_code: Option<String>,
    pub order_id: Option<String>,
    pub guid: Option<String>,
    pub id: String,
    pub invoice_time: u64,
    pub expiration_time: u64,
    pub current_time: u64,
    pub low_fee_detected: Option<bool>,
    pub btc_paid: Option<String>,
    pub rate: f32,
    pub exception_status: bool,
    pub payment_urls: Option<PaymentUrl>,
    pub refund_address_request_pending: Option<bool>,
    pub buyer_paid_btc_miner_fee: Option<String>,
    pub bitcoin_address: Option<String>,
    pub flags: Option<InvoiceFlags>,
    pub payment_subtotals: Payment,
    pub payment_totals: Payment,
    pub amount_paid: u64,
    #[serde(default)]
    pub miner_fees: HashMap<String, MinerFees>,
    #[serde(default)]
    pub exchange_rates: HashMap<String, HashMap<String, f32>>,
    #[serde(default)]
    pub supported_transaction_currencies: HashMap<String, SupportedCurrency>,
    pub addresses: Addresses,
    pub payment_codes: PaymentCodes,
    pub buyer: Option<Buyer>,
    pub status: InvoiceStatus,
    pub checkout_type: Option<String>,
    pub token: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum InvoiceStatus {
    New,
    Expired,
    Paid,
    Confirmed,
    Completed,
    Invalid,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CryptoInfo {
    pub crypto_code: String,
    pub payment_type: String,
    pub rate: f32,
    pub ex_rates: HashMap<String, f32>,
    pub paid: String,
    pub price: String,
    pub due: String,
    pub payment_urls: PaymentUrl,
    pub address: Option<String>,
    pub url: String,
    pub total_due: String,
    pub network_fee: String,
    pub tx_count: usize,
    pub crypto_paid: String,
    pub payments: Vec<serde_json::Value>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub struct Addresses {
    #[serde(rename = "BTCLike")]
    #[serde(default)]
    pub btclike: Option<String>,
    #[serde(default)]
    pub btc_lnurlpay: Option<String>,
    #[serde(rename = "BTC_LightningLike")]
    #[serde(default)]
    pub btc_lightning_like: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub struct PaymentUrl {
    pub bip21: Option<String>,
    pub bip72: Option<String>,
    #[serde(rename = "BIP72b")]
    pub bip72b: Option<String>,
    pub bip73: Option<String>,
    pub bolt11: Option<String>,
    pub lnurlp: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct InvoiceFlags {
    pub refundable: bool,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub struct PaymentCodes {
    #[serde(rename = "BTCLike")]
    pub btclike: Option<PaymentUrl>,
    pub btc_lnurlpay: Option<PaymentUrl>,
    #[serde(rename = "BTC_LightningLike")]
    pub btc_lightning_like: Option<PaymentUrl>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub struct Payment {
    #[serde(rename = "BTCLike")]
    #[serde(default)]
    pub btclike: f32,
    #[serde(default)]
    pub btc_lnurlpay: f32,
    #[serde(rename = "BTC_LightningLike")]
    #[serde(default)]
    pub btc_lightning_like: f32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MinerFees {
    pub satoshis_per_byte: f32,
    pub total_fee: f32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Buyer {
    pub name: Option<String>,
    pub address1: Option<String>,
    pub address2: Option<String>,
    pub locality: Option<String>,
    pub region: Option<String>,
    pub postal_code: Option<String>,
    pub country: Option<String>,
    pub phone: Option<String>,
    pub email: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SupportedCurrency {
    pub enabled: bool,
    pub reason: Option<serde_json::Value>,
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_parse_invoice() {
        get_test_invoices_json().iter().for_each(|string_json| {
            let parsed: Invoice = serde_json::from_str(string_json).unwrap();
            println!("{:#?}", parsed);
        });
    }

    fn get_test_invoices_json() -> [&'static str; 2] {
        [
            r#"{"addresses":{"BTC_LNURLPAY":null,"BTC_LightningLike":"lntb37250n1pjt27akpp5dh0yfefyvek68frjl886hnxwcrkwvrkd9cdnmke8j0l4fpqf2fxqdpj2pskjepqw3hjq4r9wd6zqum5daex2gpgfaexgetjypy5gw3q9ycqzzsxqzuysp5ealwkddt9phg7vsqu7k9xh373r0mcjc6kktwjmfnrhlkmk64tmyq9qyyssqwaazrhey5kmy09j83u2x6wsvjcqs8cwrz798ka5lfzfws8w5u2s5a32yavtkw6n6hj8zpk84np7kfttvuwmjc0tgpxvdq2ak20jsevcq3ujhlp"},"amountPaid":0,"bitcoinAddress":null,"btcDue":null,"btcPaid":null,"btcPrice":null,"buyer":{"address1":null,"address2":null,"country":null,"email":null,"locality":null,"name":null,"phone":null,"postalCode":null,"region":null},"buyerPaidBtcMinerFee":null,"buyerTotalBtcAmount":null,"checkoutType":null,"cryptoInfo":[{"address":null,"cryptoCode":"BTC","cryptoPaid":"0.00000000","due":"0.00003725","exRates":{"EUR":0},"networkFee":"0.00000000","paid":"0.00000000","paymentType":"LNURLPAY","paymentUrls":{"BIP21":null,"BIP72":null,"BIP72b":null,"BIP73":null,"BOLT11":null,"LNURLP":"lightning:lnurl1dp68gurn8ghj7ar9wd6xuet59ejx2mt09e38gcmsv9uhxetjwejhytn0wfnj7sj5gvh42j2vfe24ynp0wpshjtmf9umhzvj5fpvkgvnegf2hz4mex3p8we2k2a4x2s0vlde"},"payments":[],"price":"0.00003725","rate":26850.4,"totalDue":"0.00003725","txCount":0,"url":"https://testnet.demo.btcpayserver.org/i/BTC_LNURLPAY/7q2THYd2yBUqWy4BweVWje"},{"address":"lntb37250n1pjt27akpp5dh0yfefyvek68frjl886hnxwcrkwvrkd9cdnmke8j0l4fpqf2fxqdpj2pskjepqw3hjq4r9wd6zqum5daex2gpgfaexgetjypy5gw3q9ycqzzsxqzuysp5ealwkddt9phg7vsqu7k9xh373r0mcjc6kktwjmfnrhlkmk64tmyq9qyyssqwaazrhey5kmy09j83u2x6wsvjcqs8cwrz798ka5lfzfws8w5u2s5a32yavtkw6n6hj8zpk84np7kfttvuwmjc0tgpxvdq2ak20jsevcq3ujhlp","cryptoCode":"BTC","cryptoPaid":"0.00000000","due":"0.00003725","exRates":{"EUR":0},"networkFee":"0.00000000","paid":"0.00000000","paymentType":"LightningLike","paymentUrls":{"BIP21":null,"BIP72":null,"BIP72b":null,"BIP73":null,"BOLT11":"lightning:lntb37250n1pjt27akpp5dh0yfefyvek68frjl886hnxwcrkwvrkd9cdnmke8j0l4fpqf2fxqdpj2pskjepqw3hjq4r9wd6zqum5daex2gpgfaexgetjypy5gw3q9ycqzzsxqzuysp5ealwkddt9phg7vsqu7k9xh373r0mcjc6kktwjmfnrhlkmk64tmyq9qyyssqwaazrhey5kmy09j83u2x6wsvjcqs8cwrz798ka5lfzfws8w5u2s5a32yavtkw6n6hj8zpk84np7kfttvuwmjc0tgpxvdq2ak20jsevcq3ujhlp"},"payments":[],"price":"0.00003725","rate":26850.4,"totalDue":"0.00003725","txCount":0,"url":"https://testnet.demo.btcpayserver.org/i/BTC_LightningLike/7q2THYd2yBUqWy4BweVWje"}],"currency":"EUR","currentTime":1689615287973,"exRates":null,"exceptionStatus":false,"exchangeRates":{"BTC":{"EUR":0}},"expirationTime":1689616186000,"flags":null,"guid":"0c9318b6-c197-42de-b155-dfacb72cc381","id":"7q2THYd2yBUqWy4BweVWje","invoiceTime":1689615286000,"itemCode":null,"itemDesc":null,"lowFeeDetected":false,"minerFees":{},"orderId":null,"paymentCodes":{"BTC_LNURLPAY":{"BIP21":null,"BIP72":null,"BIP72b":null,"BIP73":null,"BOLT11":null,"LNURLP":"lightning:lnurl1dp68gurn8ghj7ar9wd6xuet59ejx2mt09e38gcmsv9uhxetjwejhytn0wfnj7sj5gvh42j2vfe24ynp0wpshjtmf9umhzvj5fpvkgvnegf2hz4mex3p8we2k2a4x2s0vlde"},"BTC_LightningLike":{"BIP21":null,"BIP72":null,"BIP72b":null,"BIP73":null,"BOLT11":"lightning:lntb37250n1pjt27akpp5dh0yfefyvek68frjl886hnxwcrkwvrkd9cdnmke8j0l4fpqf2fxqdpj2pskjepqw3hjq4r9wd6zqum5daex2gpgfaexgetjypy5gw3q9ycqzzsxqzuysp5ealwkddt9phg7vsqu7k9xh373r0mcjc6kktwjmfnrhlkmk64tmyq9qyyssqwaazrhey5kmy09j83u2x6wsvjcqs8cwrz798ka5lfzfws8w5u2s5a32yavtkw6n6hj8zpk84np7kfttvuwmjc0tgpxvdq2ak20jsevcq3ujhlp"}},"paymentSubtotals":{"BTC_LNURLPAY":3725,"BTC_LightningLike":3725},"paymentTotals":{"BTC_LNURLPAY":3725,"BTC_LightningLike":3725},"paymentUrls":null,"posData":null,"price":1,"rate":0,"refundAddressRequestPending":false,"status":"new","supportedTransactionCurrencies":{"BTC":{"enabled":true,"reason":null}},"token":"5GYd8KW4QZg9Sw4iagNSk5","url":"https://testnet.demo.btcpayserver.org/invoice?id=7q2THYd2yBUqWy4BweVWje"}"#,
            r#"{"url":"https://testnet.demo.btcpayserver.org/invoice?id=3Wy4cKQEvmsBru5yccGbNn","posData":null,"status":"new","btcPrice":"0.00260930","btcDue":"0.00260930","cryptoInfo":[{"cryptoCode":"BTC","paymentType":"BTCLike","rate":7664.908,"exRates":{"USD":0},"paid":"0.00000000","price":"0.00260930","due":"0.00260930","paymentUrls":{"BIP21":"bitcoin:tb1qxzv66jwlm5pphum53alctrsdr7stfahc6hnxeg?amount=0.0026093","BIP72":null,"BIP72b":null,"BIP73":null,"BOLT11":null},"address":"tb1qxzv66jwlm5pphum53alctrsdr7stfahc6hnxeg","url":"https://testnet.demo.btcpayserver.org/i/BTC/3Wy4cKQEvmsBru5yccGbNn","totalDue":"0.00260930","networkFee":"0.00000000","txCount":0,"cryptoPaid":"0.00000000","payments":[]},{"cryptoCode":"LTC","paymentType":"BTCLike","rate":45.07576229821518,"exRates":{"USD":0},"paid":"0.00000000","price":"0.44369744","due":"0.44369744","paymentUrls":{"BIP21":"litecoin:tltc1qxzv66jwlm5pphum53alctrsdr7stfahcrl3cfp?amount=0.44369744","BIP72":null,"BIP72b":null,"BIP73":null,"BOLT11":null},"address":"tltc1qxzv66jwlm5pphum53alctrsdr7stfahcrl3cfp","url":"https://testnet.demo.btcpayserver.org/i/LTC/3Wy4cKQEvmsBru5yccGbNn","totalDue":"0.44369744","networkFee":"0.00000000","txCount":0,"cryptoPaid":"0.00000000","payments":[]}],"price":20,"currency":"USD","exRates":{"USD":0},"buyerTotalBtcAmount":null,"itemDesc":null,"itemCode":null,"orderId":null,"guid":"52ccf34a-f69f-4ccf-8027-46bec72a57c7","id":"3Wy4cKQEvmsBru5yccGbNn","invoiceTime":1587907315000,"expirationTime":1587908215000,"currentTime":1587907528578,"lowFeeDetected":false,"btcPaid":"0.00000000","rate":7664.908,"exceptionStatus":false,"paymentUrls":{"BIP21":"bitcoin:tb1qxzv66jwlm5pphum53alctrsdr7stfahc6hnxeg?amount=0.0026093","BIP72":null,"BIP72b":null,"BIP73":null,"BOLT11":null},"refundAddressRequestPending":false,"buyerPaidBtcMinerFee":null,"bitcoinAddress":"tb1qxzv66jwlm5pphum53alctrsdr7stfahc6hnxeg","token":"8byQ85L8bX4Urq68ne3Wg7","flags":{"refundable":false},"paymentSubtotals":{"BTC":260930,"LTC":44369744},"paymentTotals":{"BTC":260930,"LTC":44369744},"amountPaid":0,"minerFees":{"BTC":{"satoshisPerByte":1,"totalFee":0},"LTC":{"satoshisPerByte":25,"totalFee":0}},"exchangeRates":{"BTC":{"USD":0},"LTC":{"USD":0}},"supportedTransactionCurrencies":{"BTC":{"enabled":true,"reason":null},"LTC":{"enabled":true,"reason":null}},"addresses":{"BTC":"tb1qxzv66jwlm5pphum53alctrsdr7stfahc6hnxeg","LTC":"tltc1qxzv66jwlm5pphum53alctrsdr7stfahcrl3cfp"},"paymentCodes":{"BTC":{"BIP21":"bitcoin:tb1qxzv66jwlm5pphum53alctrsdr7stfahc6hnxeg?amount=0.0026093","BIP72":null,"BIP72b":null,"BIP73":null,"BOLT11":null},"LTC":{"BIP21":"litecoin:tltc1qxzv66jwlm5pphum53alctrsdr7stfahcrl3cfp?amount=0.44369744","BIP72":null,"BIP72b":null,"BIP73":null,"BOLT11":null}},"buyer":{"name":null,"address1":null,"address2":null,"locality":null,"region":null,"postalCode":null,"country":null,"phone":null,"email":null}}"#,
        ]
    }
}