decode_bolt11_invoice
Decode BOLT11 Lightning invoices to extract network, amount, and timestamp information for Bitcoin payment analysis.
Instructions
Decode a BOLT11 Lightning invoice without external dependencies.
Parses the human-readable part to extract network, amount, and timestamp. Does NOT verify the signature or parse tagged fields beyond basic extraction.
Args: invoice: BOLT11 payment request string (starts with lnbc, lntb, or lnbcrt)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| invoice | Yes |
Output Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/bitcoin_mcp/server.py:1074-1151 (handler)The 'decode_bolt11_invoice' tool handler implementation parses a BOLT11 invoice string to extract the network, amount, and timestamp, returning a JSON summary.
@mcp.tool() def decode_bolt11_invoice(invoice: str) -> str: """Decode a BOLT11 Lightning invoice without external dependencies. Parses the human-readable part to extract network, amount, and timestamp. Does NOT verify the signature or parse tagged fields beyond basic extraction. Args: invoice: BOLT11 payment request string (starts with lnbc, lntb, or lnbcrt) """ invoice = invoice.strip().lower() # Validate prefix if not invoice.startswith("ln"): return json.dumps({"error": "Not a BOLT11 invoice (must start with 'ln')"}) # Find the last '1' separator between human-readable part and data sep_idx = invoice.rfind("1") if sep_idx < 2: return json.dumps({"error": "Invalid BOLT11 format: no separator found"}) hrp = invoice[:sep_idx] data_part = invoice[sep_idx + 1:] # Parse network prefix if hrp.startswith("lnbcrt"): network = "regtest" amount_str = hrp[6:] elif hrp.startswith("lntbs"): network = "signet" amount_str = hrp[5:] elif hrp.startswith("lntb"): network = "testnet" amount_str = hrp[4:] elif hrp.startswith("lnbc"): network = "mainnet" amount_str = hrp[4:] else: network = "unknown" amount_str = "" # Parse amount with multiplier amount_btc = None multipliers = {"m": 0.001, "u": 0.000001, "n": 0.000000001, "p": 0.000000000001} if amount_str: if amount_str[-1] in multipliers: try: amount_btc = float(amount_str[:-1]) * multipliers[amount_str[-1]] except ValueError: amount_btc = None else: try: amount_btc = float(amount_str) except ValueError: amount_btc = None # Decode timestamp from data part using bech32 charset bech32_charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" charset_map = {c: i for i, c in enumerate(bech32_charset)} timestamp = None if len(data_part) >= 7: try: # First 7 chars of data = 35-bit timestamp ts_val = 0 for ch in data_part[:7]: ts_val = ts_val * 32 + charset_map[ch] timestamp = ts_val except (KeyError, ValueError): timestamp = None result = { "network": network, "hrp": hrp, "amount_btc": amount_btc, "amount_sats": round(amount_btc * 1e8) if amount_btc is not None else None, "timestamp": timestamp, "data_length": len(data_part), } return json.dumps(result)