| Crates.io | unified_uri |
| lib.rs | unified_uri |
| version | 0.1.0 |
| created_at | 2025-10-27 09:34:07.458841+00 |
| updated_at | 2025-10-27 09:34:07.458841+00 |
| description | A Rust library for parsing unified Bitcoin URIs that support both Lightning Network invoices and Payjoin parameters, based on the BIP21 URI specification. |
| homepage | |
| repository | https://github.com/RCasatta/unified_uri |
| max_upload_size | |
| id | 1902514 |
| size | 40,910 |
A Rust library for parsing unified Bitcoin URIs that support both Lightning Network invoices and Payjoin parameters, based on the BIP21 URI specification.
This crate extends the BIP21 URI standard to support unified QR codes that contain both on-chain Bitcoin addresses and Lightning Network payment information, as well as Payjoin parameters. This enables a single QR code to work with both on-chain and Lightning wallets, eliminating the need for separate payment interfaces.
lightning parameterpj) and output substitution control (pjos)Add this to your Cargo.toml:
[dependencies]
unified_uri = "0.1"
use unified_uri::UnifiedUri;
use std::str::FromStr;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Parse a unified URI with Lightning and Payjoin support
let uri_str = "bitcoin:BC1QYLH3U67J673H6Y6ALV70M0PL2YZ53TZHVXGG7U?pj=https://payjoin.example.com/payjoin&pjos=1";
let uri = UnifiedUri::from_str(uri_str)?;
// Access the Bitcoin address
println!("Address: {}", uri.address);
// Access Lightning invoice if present
if let Some(invoice) = &uri.extras.lightning {
println!("Lightning Invoice: {:?}", invoice);
}
// Access Payjoin parameters
if let Some(pj_url) = &uri.extras.pj {
println!("Payjoin endpoint: {}", pj_url);
}
// Check if output substitution is disabled
if uri.extras.disable_output_substitution() {
println!("Payjoin output substitution is disabled");
}
Ok(())
}
use unified_uri::UnifiedUriBuilder;
use bitcoin::{Address, Amount};
use std::str::FromStr;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a valid Bitcoin address
let address: Address = "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlhfe2".parse()?;
// Build a basic on-chain URI
let basic_uri = UnifiedUriBuilder::new(address.clone()).build();
println!("{}", basic_uri); // "bitcoin:bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlhfe2"
// Build a full unified URI with all parameters
let unified_uri = UnifiedUriBuilder::new(address)
.amount(Amount::from_sat(100_000)?) // 0.001 BTC in satoshis
.label("Payment for services")
.message("Thank you for your business")
.lightning("lnbc10u1p3pj257pp5yz...") // or use lightning_invoice(parsed_invoice)
.payjoin_url("https://payjoin.example.com/payjoin")
.disable_output_substitution(true)
.build();
println!("{}", unified_uri);
// "bitcoin:bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlhfe2?amount=0.001&label=Payment%20for%20services&message=Thank%20you%20for%20your%20business&lightning=lnbc10u1p3pj257pp5yz...&pj=https://payjoin.example.com/payjoin&pjos=1"
Ok(())
}
use unified_uri::UnifiedUri;
// On-chain only (standard BIP21)
let onchain_uri = "bitcoin:1andreas3batLhQa2FawWjeyjCqyBzypd";
// With Lightning invoice
let lightning_uri = "bitcoin:BC1QYLH3U67J673H6Y6ALV70M0PL2YZ53TZHVXGG7U?lightning=LNBC10U1P3PJ257PP5YZTKWJCZ5FTL5LAXKAV23ZMZEKAW37ZK6KMV80PK4XAEV5QHTZ7QDPDWD3XGER9WD5KWM36YPRX7U3QD36KUCMGYP282ETNV3SHJCQZPGXQYZ5VQSP5USYC4LK9CHSFP53KVCNVQ456GANH60D89REYKDNGSMTJ6YW3NHVQ9QYYSSQJCEWM5CJWZ4A6RFJX77C490YCED6PEMK0UPKXHY89CMM7SCT66K8GNEANWYKZGDRWRFJE69H9U5U0W57RRCSYSAS7GADWMZXC8C6T0SPJAZUP6";
// With Payjoin parameters
let payjoin_uri = "bitcoin:BC1QYLH3U67J673H6Y6ALV70M0PL2YZ53TZHVXGG7U?pj=https://payjoin.example.com/payjoin&pjos=1";
// All three can be parsed with UnifiedUri
let unified_uri = UnifiedUri::from_str(lightning_uri)?;
| Parameter | Type | Description |
|---|---|---|
lightning |
String | BOLT11 Lightning invoice |
pj |
String | Payjoin endpoint URL |
pjos |
String | Payjoin output substitution (0 = enabled, 1 = disabled) |
This crate enables the creation and parsing of unified QR codes as described in the Unified QR Code specification. These QR codes allow a single payment request to work with:
UnifiedUri<'a>The main type for parsing unified BIP21 URIs. This is a type alias for Uri<'a, NetworkUnchecked, UnifiedExtras>.
UnifiedExtrasContains the extra parameters parsed from the URI:
lightning: Option<Bolt11Invoice> - Lightning invoice if presentpj: Option<Url> - Payjoin endpoint URL if presentpjos: Option<bool> - Payjoin output substitution settingdisable_output_substitution() -> bool - Returns true if payjoin output substitution should be disabledUnifiedUriBuilderBuilder for creating unified BIP21 URI strings with optional Lightning and Payjoin parameters.
new(address: Address) -> Self - Create a new builder instance with required Bitcoin addressamount(self, amount: Amount) -> Self - Set the payment amount in satoshislabel<S: Into<String>>(self, label: S) -> Self - Set the payment labelmessage<S: Into<String>>(self, message: S) -> Self - Set the payment messagelightning_invoice(self, invoice: Bolt11Invoice) -> Self - Set the Lightning invoice from Bolt11Invoice structlightning<S: Into<String>>(self, invoice: S) -> Self - Set the Lightning invoice from stringpayjoin_url<S: Into<String>>(self, url: S) -> Self - Set the Payjoin endpoint URL from stringpayjoin(self, url: Url) -> Self - Set the Payjoin endpoint URL from Url structdisable_output_substitution(self, disable: bool) -> Self - Set whether to disable output substitutionbuild(self) -> String - Build the final URI stringbip21 - BIP21 URI parsingbitcoin - Bitcoin address handlinglightning-invoice - BOLT11 invoice parsingurl - URL validationContributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License.