Understanding Lightning Invoices

The Spark Service Provider enables trustless Lightning interoperability. To send and receive Lightning payments, you can generate and pay Lightning invoices. A Lightning invoice (also called a payment request) is a specially formatted string that contains all the information needed to make a Lightning Network payment:

  • Amount: How many satoshis to send (can be omitted for zero-amount invoices)
  • Destination: The recipient’s node public key
  • Payment Hash: A unique identifier for the payment
  • Description: Optional memo describing the payment
  • Expiry: How long the invoice is valid for (default 24 hours)

Lightning invoices start with “ln” followed by the network identifier (bc for mainnet) and typically look like this: lnbc1...

Mainnet invoice Example: lnbc2500n1pj0ytfcpp5qqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqdx40shp5jqp3qymd6qgpy99ppk0jqjzylqg5t7fhqhpl6s4kxmqgmrn59w5k0z0cqqqqqqzqqqqq9qsqqqqqq9qqqqqqgq9qsqxl9l55y5cwa9s2h8nvdh4h7h43tcwjdcysf7v0fprz5uh6vshs4n0tvhgzz2xgcqpg8yqv7

Receiving Lightning Payments

To receive a payment, generate a lightning invoice then share it with the sender.

// Generate invoice with amount
const invoice = await wallet.createLightningInvoice({
  amountSats: 100, // amount in satoshis
  memo: "test invoice", // optional description
});
console.log("Invoice:", invoice);
Spark does not currently support Zero amount invoices. But support is coming soon!

Get payment status

To check the status of a Lightning payment, you can use the getLightningReceiveRequest

  const lightningPaymentStatus = await wallet.getLightningReceiveRequest(
    invoice.id,
  );
  console.log("Lightning Payment Status:", lightningPaymentStatus);

Sending Lightning Payments

To send a payment, you’ll need a Lightning invoice from the recipient and the maximum amount of fees to pay. We recommend setting the maximum routing fee to whichever is greater 5 sats or 17 bps * transaction amount.

const payment_response = await wallet.payLightningInvoice({
  invoice:
    "lnbc1u1pnm7ammpp4v84f05tl0kzt6g95g056athdpp8f8azvg6d7epz74z562ymer9jqsp5nc50gazvp0e98u42jlu653rw0eutcl067nqq924hf89q4la4kd9sxq9z0rgqnp4qdnmwu8v22cvq9xsv2l05cn9rre7xlcgdtntxawf8m0zxq3qemgzqrzjqtr2vd60g57hu63rdqk87u3clac6jlfhej4kldrrjvfcw3mphcw8sqqqqrj0q7ew45qqqqqqqqqqqqqq9qcqzpgdq5w3jhxapqd9h8vmmfvdjs9qyyssqj7lf2w4m587g04n4t0ferdv0vnwftzca0xuc9yxycng78cnhrvmyw2mzaa8t76jskpypqnwqhp9xh0vnwxz90jytd34vrmhcngsnl8qplz7ylk",
  maxFeeSats: 5,
});
console.log("Payment Response:", payment_response);

Checking Balance

You can use getBalance() to check a Wallet balance after sending or receiving payments.

The getBalance() method returns a Promise resolving to an object containing:

  • balance: A bigint representing the total amount in satoshis
  • tokenBalances: A Map of token balances, where each entry contains:
    • balance: A bigint representing the token amount

Additionally, you can listen for balance update events.

wallet.on("transfer:claimed", (transferId: string, balance: number) => {
  console.log(
    `Transfer ${transferId} claimed. New balance: ${balance}`,
  );

Best Practices

  • Always verify invoice amounts before paying
  • Keep track of invoice ids to match balance changes to created invoices
  • Set appropriate expiry times for invoices if necesary
  • Monitor payment status for confirmation

Next Steps

Now that you can send and receive Lightning payments, you might want to:

Need Help?