Skip to content

Feature Request: Support LUD-12 Comments When Sending to External Lightning Addresses #401

@pretyflaco

Description

@pretyflaco

Feature Request: Support LUD-12 Comments When Sending to External Lightning Addresses

Summary

Add support for LUD-12 protocol, allowing users to include a comment/message when sending payments to external Lightning Addresses that advertise commentAllowed in their LNURL-pay response.

Motivation

LUD-12 is a widely adopted extension to LNURL-pay that enables payers to attach a text comment to their payment. Many Lightning wallets and services support receiving comments (e.g., Wallet of Satoshi, Zeus, LNbits, BTCPay Server). This is useful for:

  • Adding payment references or invoice numbers
  • Sending personal messages with tips/donations
  • Providing context for business transactions
  • Enabling richer user-to-user communication

Currently, Blink API users cannot include comments when paying to external LN addresses, even when the recipient's LNURL endpoint advertises commentAllowed > 0.

Current Implementation

The GraphQL mutations lnAddressPaymentSend and lnurlPaymentSend only accept:

  • walletId
  • amount
  • lnAddress / lnurl

The LnurlPayService calls requestInvoice without a comment parameter:

// core/api/src/services/lnurl-pay/index.ts
const invoice = await requestInvoice({
  lnUrlOrAddress: lnAddressOrLnurl,
  tokens: utils.toSats(toSats(amount.amount)),
  // No comment parameter passed
})

Proposed Solution

1. Update GraphQL Input Types

Add an optional comment field to LnAddressPaymentSendInput and LnurlPaymentSendInput:

input LnAddressPaymentSendInput {
  walletId: WalletId!
  amount: SatAmount!
  lnAddress: String!
  comment: String  # Optional, max 2000 chars per LUD-12
}

input LnurlPaymentSendInput {
  walletId: WalletId!
  amount: SatAmount!
  lnurl: String!
  comment: String  # Optional, max 2000 chars per LUD-12
}

2. Update Type Definitions

// core/api/src/app/wallets/index.types.d.ts
type LnAddressPaymentSendArgs = {
  senderWalletId: WalletId
  senderAccount: Account
  lnAddress: string
  amount: number
  comment?: string  // Add optional comment
}

type LnurlPaymentSendArgs = {
  senderWalletId: WalletId
  senderAccount: Account
  lnurl: string
  amount: number
  comment?: string  // Add optional comment
}

3. Update ILnurlPayService Interface

// core/api/src/domain/bitcoin/lnurl/index.types.d.ts
interface ILnurlPayService {
  fetchInvoiceFromLnAddressOrLnurl(args: {
    amount: BtcPaymentAmount
    lnAddressOrLnurl: string
    comment?: string  // Add optional comment
  }): Promise<string | LnurlServiceError>
}

4. Pass Comment to lnurl-pay Library

The lnurl-pay npm library (v4.0.0) already supports the comment parameter in requestInvoice:

// core/api/src/services/lnurl-pay/index.ts
const fetchInvoiceFromLnAddressOrLnurl = async ({
  amount,
  lnAddressOrLnurl,
  comment,  // Add parameter
}: {
  amount: BtcPaymentAmount
  lnAddressOrLnurl: string
  comment?: string
}): Promise<string | LnurlServiceError> => {
  const invoice = await requestInvoice({
    lnUrlOrAddress: lnAddressOrLnurl,
    tokens: utils.toSats(toSats(amount.amount)),
    comment,  // Pass to library
  })
  // ...
}

Expected Behavior

  1. If comment is provided and the destination supports commentAllowed >= comment.length, the comment is included in the LNURL callback request
  2. If comment is provided but exceeds commentAllowed, return an appropriate error (the lnurl-pay library should handle this validation)
  3. If comment is provided but commentAllowed = 0, the library should ignore it or return an error (depending on desired strictness)
  4. If no comment is provided, behavior remains unchanged

Additional Considerations

  • Comment length validation: Consider adding a GraphQL scalar or input validation to cap comments at 2000 characters (LUD-12 max for GET requests)
  • Error handling: Surface clear errors when comment exceeds destination's commentAllowed limit
  • Future enhancement: Optionally expose the destination's commentAllowed value via a fee probe or metadata query so clients can inform users of the limit before sending

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions