### Install the project Source: https://github.com/lnbits/bolt11/blob/main/README.md Clone the repository and synchronize dependencies using uv. ```console $ git clone https://github.com/lnbits/bolt11 $ cd bolt11 $ uv sync ``` -------------------------------- ### Install git hooks Source: https://github.com/lnbits/bolt11/blob/main/README.md Configure pre-commit hooks for the repository. ```console $ uv run pre-commit install ``` -------------------------------- ### Adding Route Hints to Invoices Source: https://context7.com/lnbits/bolt11/llms.txt Demonstrates creating route hints from a list of dictionaries and attaching them to an invoice's tags. ```python from bolt11 import encode, Bolt11 from bolt11.models.tags import Tags from bolt11.models.routehint import RouteHint, Route # Create route hints from a list of dictionaries route_hint = RouteHint.from_list([ { "public_key": "029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255", "short_channel_id": "66051x263430x1800", # block x tx x output format "base_fee": 1, # Base fee in millisatoshi "ppm_fee": 20, # Fee rate in parts per million "cltv_expiry_delta": 3 # CLTV expiry delta }, { "public_key": "039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255", "short_channel_id": "197637x395016x2314", "base_fee": 2, "ppm_fee": 30, "cltv_expiry_delta": 4 } ]) # Include in invoice tags = Tags.from_dict({ "payment_hash": "0001020304050607080900010203040506070809000102030405060708090102", "payment_secret": "1111111111111111111111111111111111111111111111111111111111111111", "description_hash": "3925b6f67e2c340036ed12093dd44e0368df1b6ea26c53dbe4811f58fd5db8c1", "r": route_hint, # Add route hint }) invoice = Bolt11(currency="bc", amount_msat=2000000000, date=1496314658, tags=tags) ``` -------------------------------- ### Display CLI help Source: https://github.com/lnbits/bolt11/blob/main/README.md Show the help menu for the bolt11 CLI. ```console $ uv run bolt11 --help ``` -------------------------------- ### Run CLI commands Source: https://github.com/lnbits/bolt11/blob/main/README.md Access help or decode payment requests using the CLI. ```console $ uv run bolt11 --help $ uv run bolt11 decode ``` -------------------------------- ### Use command line interface Source: https://context7.com/lnbits/bolt11/llms.txt Decode and encode invoices directly from the terminal. ```bash # Install and run pip install bolt11 bolt11 --help ``` -------------------------------- ### Run checks and tests Source: https://github.com/lnbits/bolt11/blob/main/README.md Execute the project's test suite and quality checks. ```console $ make ``` -------------------------------- ### Constructing BOLT11 Tags Source: https://context7.com/lnbits/bolt11/llms.txt Demonstrates various ways to define invoice tags using dictionaries or programmatic addition. Note that 'description' and 'description_hash' are mutually exclusive. ```python tags = Tags.from_dict({ "p": "0001020304050607080900010203040506070809000102030405060708090102", # payment_hash "s": "1111111111111111111111111111111111111111111111111111111111111111", # payment_secret "d": "Payment for services", # description "x": 3600, # expire_time "c": 18, # min_final_cltv_expiry }) ``` ```python tags_with_hash = Tags.from_dict({ "payment_hash": "0001020304050607080900010203040506070809000102030405060708090102", "payment_secret": "1111111111111111111111111111111111111111111111111111111111111111", "description_hash": "3925b6f67e2c340036ed12093dd44e0368df1b6ea26c53dbe4811f58fd5db8c1", }) ``` ```python tags_with_metadata = Tags.from_dict({ "p": "0001020304050607080900010203040506070809000102030405060708090102", "s": "1111111111111111111111111111111111111111111111111111111111111111", "d": "payment metadata inside", "m": "01fafaf0", # metadata as hex }) ``` ```python tags = Tags() tags.add(TagChar.payment_hash, "0001020304050607080900010203040506070809000102030405060708090102") tags.add(TagChar.description, "Test payment") if tags.has(TagChar.payment_hash): tag = tags.get(TagChar.payment_hash) print(f"Payment hash: {tag.data}") ``` -------------------------------- ### Decode and access route hints Source: https://context7.com/lnbits/bolt11/llms.txt Access route hint information from a decoded payment request. ```python from bolt11 import decode decoded = decode(payment_request) if decoded.route_hints: for hint in decoded.route_hints: for route in hint.routes: print(f"Node: {route.public_key}") print(f"Channel: {route.short_channel_id}") print(f"Base fee: {route.base_fee} msat") print(f"PPM fee: {route.ppm_fee}") print(f"CLTV delta: {route.cltv_expiry_delta}") ``` -------------------------------- ### Managing Lightning Network Features Source: https://context7.com/lnbits/bolt11/llms.txt Shows how to decode existing invoice features and construct new feature sets programmatically, including custom feature bits. ```python from bolt11 import decode from bolt11.models.features import Features, Feature, FeatureState, FeatureExtra # Decode and inspect features invoice = decode("lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetp" "deessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqqsgq2a25dxl" "5hrntdtn6zvydt7d66hyzsyhqs4wdynavys42xgl6sgx9c4g7me86a27t07mdtfry458rtjr0v92cnmswpsjscgt2" "vcse3sgpz3uapa") if invoice.features: # Get human-readable features print(invoice.features.readable) # {"var_onion_optin": "required", "payment_secret": "required", "extra_49": "supported"} # Check for specific feature state = invoice.features.has_feature("payment_secret") print(f"Payment secret: {state}") # "required" # JSON representation print(invoice.features.json) # Create features programmatically feature_list = { Feature.var_onion_optin: FeatureState.required, Feature.payment_secret: FeatureState.required, Feature.basic_mpp: FeatureState.supported, FeatureExtra(49): FeatureState.supported, # Custom feature bit } features = Features.from_feature_list(feature_list) # Use in invoice from bolt11.models.tags import Tags tags = Tags.from_dict({ "payment_hash": "0001020304050607080900010203040506070809000102030405060708090102", "payment_secret": "1111111111111111111111111111111111111111111111111111111111111111", "description": "test", "features": { "var_onion_optin": "required", "payment_secret": "required", "extra_49": "supported" # Custom feature } }) ``` -------------------------------- ### Manage fallback addresses Source: https://context7.com/lnbits/bolt11/llms.txt Create and include fallback addresses in invoices to provide on-chain payment options. ```python from bolt11 import encode, Bolt11 from bolt11.models.tags import Tags from bolt11.models.fallback import Fallback # Create fallback from Bitcoin address # Supports: P2PKH, P2SH, P2WPKH, P2WSH addresses fallback_p2pkh = Fallback.from_address("1RustyRX2oai4EYYDpQGWvEL62BBGqN9T", "bc") fallback_p2sh = Fallback.from_address("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX", "bc") fallback_p2wpkh = Fallback.from_address("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", "bc") fallback_p2wsh = Fallback.from_address( "bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3", "bc" ) # Testnet address fallback_testnet = Fallback.from_address("mk2QpYatsKicvFVuTAQLBryyccRXMUaGHP", "tb") # Include in invoice tags = Tags.from_dict({ "payment_hash": "0001020304050607080900010203040506070809000102030405060708090102", "payment_secret": "1111111111111111111111111111111111111111111111111111111111111111", "description_hash": "3925b6f67e2c340036ed12093dd44e0368df1b6ea26c53dbe4811f58fd5db8c1", "f": fallback_p2wpkh, # Add fallback address }) invoice = Bolt11(currency="bc", amount_msat=2000000000, date=1496314658, tags=tags) # Decode and access fallback from bolt11 import decode decoded = decode(payment_request) if decoded.fallback: print(f"Fallback address: {decoded.fallback.address}") print(f"Witness version: {decoded.fallback.witness_version}") ``` -------------------------------- ### Handle MilliSatoshi amounts Source: https://context7.com/lnbits/bolt11/llms.txt Convert between different currency units and parse shortened BOLT11 amount strings. ```python from bolt11 import MilliSatoshi from bolt11.utils import amount_to_msat, amount_to_sat, amount_to_btc from bolt11.utils import msat_to_amount, sat_to_amount, btc_to_amount from decimal import Decimal # Create from BTC msat = MilliSatoshi.from_btc(Decimal("0.001")) print(f"Millisatoshi: {msat}") # 100000000 print(f"Satoshi: {msat.sat}") # 100000 print(f"BTC: {msat.btc}") # Decimal('0.001') # Parse shortened BOLT11 amounts print(amount_to_msat("2500u")) # 250000000 (2500 micro-BTC in msat) print(amount_to_msat("1m")) # 100000000 (1 milli-BTC in msat) print(amount_to_msat("1n")) # 100 (1 nano-BTC in msat) print(amount_to_msat("1p")) # 0.1 (1 pico-BTC in msat) print(amount_to_sat("2500u")) # 250000 satoshi print(amount_to_btc("2500u")) # Decimal('0.0025') BTC # Convert to shortened format print(msat_to_amount(250000000)) # "2500u" print(sat_to_amount(250000)) # "2500u" print(btc_to_amount(Decimal("0.0025"))) # "2500u" # Use in invoice from bolt11 import Bolt11 from bolt11.models.tags import Tags invoice = Bolt11( currency="bc", amount_msat=MilliSatoshi.from_btc(Decimal("0.0025")), # 2.5 mBTC date=1496314658, tags=Tags.from_dict({...}) ) ``` -------------------------------- ### Python Exception Handling and Validation Source: https://context7.com/lnbits/bolt11/llms.txt Demonstrates how to handle specific BOLT11 exceptions during decoding and encoding, and how to use lenient or strict validation modes. ```python from bolt11 import decode, encode, Bolt11 from bolt11.exceptions import ( Bolt11Exception, Bolt11Bech32InvalidException, Bolt11SignatureTooShortException, Bolt11SignatureVerifyException, Bolt11HrpInvalidException, Bolt11AmountInvalidException, Bolt11NoPaymentHashException, Bolt11NoPaymentSecretException, Bolt11NoSignatureException, Bolt11DescriptionException, Bolt11NoMinFinalCltvException, Bolt11InvalidDescriptionHashException, ) # Handle decoding errors try: invoice = decode("invalid_invoice_string") except Bolt11Bech32InvalidException: print("Invalid bech32 encoding") except Bolt11SignatureTooShortException: print("Invoice too short to contain signature") except Bolt11SignatureVerifyException: print("Signature verification failed") except Bolt11HrpInvalidException: print("Invalid human-readable part (prefix)") except Bolt11AmountInvalidException: print("Invalid amount format") except Bolt11Exception as e: print(f"General BOLT11 error: {e}") # Handle encoding/validation errors from bolt11.models.tags import Tags try: invoice = Bolt11( currency="bc", amount_msat=1000, date=1590000000, tags=Tags.from_dict({"description": "test"}) # Missing required fields ) encoded = encode(invoice, "private_key_here") except Bolt11NoPaymentHashException: print("Invoice must include payment_hash") except Bolt11NoPaymentSecretException: print("Invoice must include payment_secret") except Bolt11DescriptionException: print("Must include either description or description_hash, not both") except Bolt11NoSignatureException: print("Invoice must be signed (provide private_key)") except Bolt11InvalidDescriptionHashException: print("description_hash must be valid hex") # Use ignore_exceptions to skip validation invoice_lenient = decode(payment_request, ignore_exceptions=True) encoded_lenient = encode(invoice, private_key, ignore_exceptions=True) # Use strict mode for additional validation invoice_strict = decode(payment_request, strict=True) # Requires min_final_cltv_expiry ``` -------------------------------- ### Perform signature operations Source: https://context7.com/lnbits/bolt11/llms.txt Verify invoice signatures or create new ones using private keys. ```python from bolt11 import decode, encode from bolt11.models.signature import Signature # Decode and inspect signature invoice = decode(payment_request) if invoice.signature: # Signature components print(f"Signature hex: {invoice.signature.hex}") print(f"R value: {invoice.signature.r}") print(f"S value: {invoice.signature.s}") print(f"Recovery flag: {invoice.signature.recovery_flag}") # Recover public key from signature recovered_pubkey = invoice.signature.recover_public_key() print(f"Recovered pubkey: {recovered_pubkey}") # Verify signature against known payee invoice.signature.verify(invoice.payee) # Raises if invalid # Create signature from private key from bolt11 import Bolt11 from bolt11.models.tags import Tags invoice = Bolt11( currency="bc", amount_msat=1000000, date=1496314658, tags=Tags.from_dict({ "payment_hash": "0001020304050607080900010203040506070809000102030405060708090102", "payment_secret": "1111111111111111111111111111111111111111111111111111111111111111", "description": "test" }) ) private_key = "e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734" encoded = encode(invoice, private_key) # Signature created during encoding ``` -------------------------------- ### CLI Invoice Operations Source: https://context7.com/lnbits/bolt11/llms.txt Commands for interacting with BOLT11 invoices via the command line, including help, decoding, encoding, and feature flag parsing. ```bash uv run bolt11 --help ``` ```bash bolt11 decode lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu9qrsgquk0rl77nj30yxdy8j9vdx85fkpmdla2087ne0xh8nhedh8w27kyke0lp53ut353s06fv3qfegext0eh0ymjpf39tuven09sam30g4vgpfna3rh ``` ```bash bolt11 encode '{ "currency": "bc", "amount_msat": 1000, "date": 1590000000, "payment_hash": "0001020304050607080900010203040506070809000102030405060708090102", "payment_secret": "1111111111111111111111111111111111111111111111111111111111111111", "description": "description" }' e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734 ``` ```bash bolt11 decode-features 0b00001000000000000 ``` -------------------------------- ### Encode a BOLT11 Invoice Source: https://context7.com/lnbits/bolt11/llms.txt Creates a BOLT11 payment request string from a Bolt11 object. Requires a private key for signing unless the invoice is already signed. Use `ignore_exceptions=True` or `strict=True` for encoding options. ```python from bolt11 import encode, Bolt11 from bolt11.models.tags import Tags # Create invoice from scratch invoice = Bolt11( currency="bc", amount_msat=250000000, # 250,000 sats date=1496314658, # Unix timestamp tags=Tags.from_dict({ "payment_hash": "0001020304050607080900010203040506070809000102030405060708090102", "payment_secret": "1111111111111111111111111111111111111111111111111111111111111111", "description": "1 cup coffee", "expire_time": 60, # 60 seconds "features": { "var_onion_optin": "required", "payment_secret": "required" } }) ) # Sign and encode with private key private_key = "e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734" encoded = encode(invoice, private_key) print(encoded) # lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzq... # Re-encode an already signed invoice (no private key needed) decoded = decode(encoded) re_encoded = encode(decoded) assert re_encoded == encoded # Encode with options encoded_lenient = encode(invoice, private_key, ignore_exceptions=True) encoded_strict = encode(invoice, private_key, strict=True) encoded_with_payee = encode(decoded, keep_payee=True) # Preserve payee field ``` -------------------------------- ### Encode a BOLT11 string Source: https://github.com/lnbits/bolt11/blob/main/README.md Encode a JSON object into a BOLT11 payment request string using a private key. ```console $ uv run bolt11 encode '{ "currency": "bc", "amount_msat": 1000, "date": 1590000000, "payment_hash": "0001020304050607080900010203040506070809000102030405060708090102", "payment_secret": "1111111111111111111111111111111111111111111111111111111111111111", "description": "description" }' e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734 ``` -------------------------------- ### Decode a BOLT11 string Source: https://github.com/lnbits/bolt11/blob/main/README.md Decode a specific BOLT11 payment request string into JSON format. ```console $ uv run bolt11 decode lnbc20m1pvjluez..... { "currency": "bc", "amount": 2000000000, "timestamp": 1496314658, "signature": "6a6586db4e8f6d40e3a5bb92e4df5110c627e9ce493af237e20a046b4e86ea200178c59564ecf892f33a9558bf041b6ad2cb8292d7a6c351fbb7f2ae2d16b54e", "description_hash": "3925b6f67e2c340036ed12093dd44e0368df1b6ea26c53dbe4811f58fd5db8c1", "features": { "var_onion_optin": "required", "payment_secret": "required" }, "fallback": "1RustyRX2oai4EYYDpQGWvEL62BBGqN9T", "route_hints": [ { "public_key": "029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255", "short_channel_id": "66051x263430x1800", "base_fee": 1, "ppm_fee": 20, "cltv_expiry_delta": 3 }, { "public_key": "039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255", "short_channel_id": "197637x395016x2314", "base_fee": 2, "ppm_fee": 30, "cltv_expiry_delta": 4 } ], "min_final_cltv_expiry": 9, "payment_hash": "0001020304050607080900010203040506070809000102030405060708090102", "payment_secret": "1111111111111111111111111111111111111111111111111111111111111111", "payee": "03e7156ae33b0a208d0744199163177e909e80176e55d97a2f221ede0f934dd9ad" } ``` -------------------------------- ### Manage BOLT11 Invoice Tags Source: https://context7.com/lnbits/bolt11/llms.txt The `Tags` class manages tagged fields in a BOLT11 invoice, allowing specification using full field names or single-character BOLT11 tag identifiers. ```python from bolt11 import Bolt11 from bolt11.models.tags import Tags, TagChar # Create tags using full field names tags = Tags.from_dict({ "payment_hash": "0001020304050607080900010203040506070809000102030405060708090102", "payment_secret": "1111111111111111111111111111111111111111111111111111111111111111", "description": "Payment for services", "expire_time": 3600, "min_final_cltv_expiry": 18, }) ``` -------------------------------- ### Decode a BOLT11 Invoice Source: https://context7.com/lnbits/bolt11/llms.txt Parses a BOLT11 payment request string into a Bolt11 object. Use `ignore_exceptions=True` for lenient parsing or `strict=True` to enforce additional requirements. ```python from bolt11 import decode # Decode a BOLT11 invoice string payment_request = ( "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzq" "fqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu9qrsgquk0rl77nj30yxdy8j9v" "dx85fkpmdla2087ne0xh8nhedh8w27kyke0lp53ut353s06fv3qfegext0eh0ymjpf39tuven09sam30g4vgpfna3rh" ) invoice = decode(payment_request) # Access decoded fields print(f"Currency: {invoice.currency}") # "bc" (mainnet) print(f"Amount (msat): {invoice.amount_msat}") # 250000000 print(f"Payment hash: {invoice.payment_hash}") # 64-char hex string print(f"Payment secret: {invoice.payment_secret}") print(f"Description: {invoice.description}") # "1 cup coffee" print(f"Expiry: {invoice.expiry} seconds") # 60 print(f"Payee pubkey: {invoice.payee}") print(f"Timestamp: {invoice.date}") # Unix timestamp print(f"Date/Time: {invoice.date_time}") # datetime object print(f"Is expired: {invoice.has_expired()}") print(f"Is mainnet: {invoice.is_mainnet()}") # Access features if invoice.features: print(f"Features: {invoice.features.readable}") # {"var_onion_optin": "required", "payment_secret": "required"} # Get full data as dictionary or JSON print(invoice.data) # dict print(invoice.json) # JSON string # Decode with options invoice_lenient = decode(payment_request, ignore_exceptions=True) # Skip validation invoice_strict = decode(payment_request, strict=True) # Require min_final_cltv_expiry ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.