breez_sdk_liquid

Function parse

pub async fn parse(
    input: &str,
    external_input_parsers: Option<&[ExternalInputParser]>,
) -> Result<InputType, Error>
Expand description

Parses generic user input, typically pasted from clipboard or scanned from a QR.

Can optionally be provided a collection of ExternalInputParser that are used if an input is not recognized.

§Examples

§On-chain BTC addresses (incl. BIP 21 URIs)

use sdk_common::prelude::{InputType::*, parse};

#[tokio::main]
async fn main() {
    assert!(matches!( parse("1andreas3batLhQa2FawWjeyjCqyBzypd", None).await, Ok(BitcoinAddress{address: _}) ));
    assert!(matches!( parse("1andreas3batLhQa2FawWjeyjCqyBzypd?amount=0.00002000", None).await, Ok(BitcoinAddress{address: _}) ));
    assert!(matches!( parse("1andreas3batLhQa2FawWjeyjCqyBzypd?amount=0.00002000&label=Hello", None).await, Ok(BitcoinAddress{address: _}) ));
    assert!(matches!( parse("1andreas3batLhQa2FawWjeyjCqyBzypd?amount=0.00002000&label=Hello&message=Msg", None).await, Ok(BitcoinAddress{address: _}) ));

    assert!(matches!( parse("BITCOIN:1andreas3batLhQa2FawWjeyjCqyBzypd", None).await, Ok(BitcoinAddress{address: _}) ));
    assert!(matches!( parse("bitcoin:1andreas3batLhQa2FawWjeyjCqyBzypd", None).await, Ok(BitcoinAddress{address: _}) ));
    assert!(matches!( parse("bitcoin:1andreas3batLhQa2FawWjeyjCqyBzypd?amount=0.00002000", None).await, Ok(BitcoinAddress{address: _}) ));
    assert!(matches!( parse("bitcoin:1andreas3batLhQa2FawWjeyjCqyBzypd?amount=0.00002000&label=Hello", None).await, Ok(BitcoinAddress{address: _}) ));
    assert!(matches!( parse("BITCOIN:1andreas3batLhQa2FawWjeyjCqyBzypd?amount=0.00002000&label=Hello&message=Msg", None).await, Ok(BitcoinAddress{address: _}) ));
    assert!(matches!( parse("bitcoin:1andreas3batLhQa2FawWjeyjCqyBzypd?amount=0.00002000&label=Hello&message=Msg", None).await, Ok(BitcoinAddress{address: _}) ));
}

§BOLT 11 invoices

use sdk_common::prelude::{InputType::*, parse};

#[tokio::main]
async fn main() {
    let invoice = "lnbc110n1p38q3gtpp5ypz09jrd8p993snjwnm68cph4ftwp22le34xd4r8ftspwshxhmnsdqqxqyjw5qcqpxsp5htlg8ydpywvsa7h3u4hdn77ehs4z4e844em0apjyvmqfkzqhhd2q9qgsqqqyssqszpxzxt9uuqzymr7zxcdccj5g69s8q7zzjs7sgxn9ejhnvdh6gqjcy22mss2yexunagm5r2gqczh8k24cwrqml3njskm548aruhpwssq9nvrvz";
    assert!(matches!( parse(invoice, None).await, Ok(Bolt11{invoice: _}) ));
    assert!(matches!( parse( &format!("lightning:{}", invoice), None).await, Ok(Bolt11{invoice: _}) ));

    // BIP 21 with LN fallback parses to a LN invoice
    let btc_address = "1andreas3batLhQa2FawWjeyjCqyBzypd";
    assert!(matches!( parse( &format!("bitcoin:{}?lightning={}", btc_address, invoice), None).await, Ok(Bolt11{invoice: _}) ));
}

§Web URLs

use sdk_common::prelude::{InputType::*, parse};

#[tokio::main]
async fn main() {
    assert!(matches!( parse("https://breez.technology", None).await, Ok(Url{url: _}) ));
    assert!(matches!( parse("https://breez.technology/test-path", None).await, Ok(Url{url: _}) ));
    assert!(matches!( parse("https://breez.technology/test-path?arg=val", None).await, Ok(Url{url: _}) ));
}

§Web URLs with lightning query param with an LNURL value.

use sdk_common::prelude::{InputType::*, parse};

#[tokio::main]
async fn main() {
    assert!(matches!( parse("https://breez.technology?lightning=lnurl1d...", None).await, Ok(LnUrlWithdraw{data: _}) ));
}

§LNURL

Both the bech32 and the raw (non-bech32, but with specific prefixes) variants are supported.

§LNURL pay request

use sdk_common::prelude::{InputType::*, LnUrlRequestData::*, parse};
use anyhow::Result;

#[tokio::main]
async fn main() -> Result<()> {
    let lnurl_pay_url = "lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf";

    assert!(matches!( parse(lnurl_pay_url, None).await, Ok(LnUrlPay{data: _}) ));
    // assert!(matches!( parse("lnurlp://domain.com/lnurl-pay?key=val").await, Ok(LnUrlPay{data: _}) ));
    // assert!(matches!( parse("lightning@address.com").await, Ok(LnUrlPay{data: _}) ));

    if let Ok(LnUrlPay{data: pd}) = parse(lnurl_pay_url,None).await {
        assert_eq!(pd.callback, "https://localhost/lnurl-pay/callback/db945b624265fc7f5a8d77f269f7589d789a771bdfd20e91a3cf6f50382a98d7");
        assert_eq!(pd.max_sendable, 16000); // Max sendable amount, in msats
        assert_eq!(pd.max_sendable_sats(), 16); // Max sendable amount, in sats
        assert_eq!(pd.min_sendable, 4000); // Min sendable amount, in msats
        assert_eq!(pd.min_sendable_sats(), 4); // Min sendable amount, in sats
        assert_eq!(pd.comment_allowed, 0);
        assert_eq!(pd.metadata_vec()?.len(), 3);
    }

    Ok(())
}

§LNURL withdraw request

use sdk_common::prelude::{InputType::*, LnUrlRequestData::*, parse};

#[tokio::main]
async fn main() {
    let lnurl_withdraw_url = "lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4exctthd96xserjv9mn7um9wdekjmmw843xxwpexdnxzen9vgunsvfexq6rvdecx93rgdmyxcuxverrvcursenpxvukzv3c8qunsdecx33nzwpnvg6ryc3hv93nzvecxgcxgwp3h33lxk";

    assert!(matches!( parse(lnurl_withdraw_url, None).await, Ok(LnUrlWithdraw{data: _}) ));
    // assert!(matches!( parse("lnurlw://domain.com/lnurl-withdraw?key=val").await, Ok(LnUrlWithdraw{data: _} ));

    if let Ok(LnUrlWithdraw{data: wd}) = parse(lnurl_withdraw_url,None).await {
        assert_eq!(wd.callback, "https://localhost/lnurl-withdraw/callback/e464f841c44dbdd86cee4f09f4ccd3ced58d2e24f148730ec192748317b74538");
        assert_eq!(wd.k1, "37b4c919f871c090830cc47b92a544a30097f03430bc39670b8ec0da89f01a81");
        assert_eq!(wd.min_withdrawable, 3000); // Min withdrawable amount, in msats
        assert_eq!(wd.min_withdrawable_sats(), 3); // Min withdrawable amount, in sats
        assert_eq!(wd.max_withdrawable, 12000); // Max withdrawable amount, in msats
        assert_eq!(wd.max_withdrawable_sats(), 12); // Max withdrawable amount, in sats
        assert_eq!(wd.default_description, "sample withdraw");
    }
}

§LNURL auth request

use sdk_common::prelude::{InputType::*, LnUrlRequestData::*, parse};

#[tokio::main]
async fn main() {
    let lnurl_auth_url = "lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttvdankjm3lw3skw0tvdankjm3xdvcn6vtp8q6n2dfsx5mrjwtrxdjnqvtzv56rzcnyv3jrxv3sxqmkyenrvv6kve3exv6nqdtyv43nqcmzvdsnvdrzx33rsenxx5unqc3cxgeqgntfgu";

    assert!(matches!( parse(lnurl_auth_url, None).await, Ok(LnUrlAuth{data: _}) ));
    // assert!(matches!( parse("keyauth://domain.com/auth?key=val").await, Ok(LnUrlAuth{data: _}) ));

    if let Ok(LnUrlAuth{data: ad}) = parse(lnurl_auth_url,None).await {
        assert_eq!(ad.k1, "1a855505699c3e01be41bddd32007bfcc5ff93505dec0cbca64b4b8ff590b822");
    }
}

§External input parsing

use sdk_common::prelude::{InputType::*, parse, ExternalInputParser};

#[tokio::main]
async fn main() {
    let external_parser = ExternalInputParser {
        provider_id: "provider_id".to_string(),
        input_regex: "(.*)(provider.domain)(.*)".to_string(),
        parser_url: "http://external-parser-domain.com/<input>".to_string(),
    };

    let data = "151931provider.domain069135";

    // Parse will make an http GET request to http://external-parser-domain.com/151931provider.domain069135
    // The following assertion assumes the response contains a bolt11 invoice
    if let Ok(Bolt11 {invoice}) = parse(data, Some(&[external_parser])).await {
        assert_eq!(invoice.bolt11, "lnbc110n1p38q3gtpp5ypz09jrd8p993snjwnm68cph4ftwp22le34xd4r8ftspwshxhmnsdqqxqyjw5qcqpxsp5htlg8ydpywvsa7h3u4hdn77ehs4z4e844em0apjyvmqfkzqhhd2q9qgsqqqyssqszpxzxt9uuqzymr7zxcdccj5g69s8q7zzjs7sgxn9ejhnvdh6gqjcy22mss2yexunagm5r2gqczh8k24cwrqml3njskm548aruhpwssq9nvrvz");
    }
}