Skip to main content
Glama

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
NameRequiredDescriptionDefault
invoiceYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • 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)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Bortlesboat/bitcoin-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server