Skip to main content
Glama

ldk_pay_invoice

Pay Lightning invoices to test payment flows, with optional maximum fee settings for development validation.

Instructions

Test payment flows by paying a Lightning invoice

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
invoiceYesBOLT11 Lightning invoice to pay
maxFeeSatsNoMaximum fee in satoshis willing to pay

Implementation Reference

  • The main handler function for the 'ldk_pay_invoice' tool. It calls LightningService.payInvoice with the provided invoice and returns formatted results including payment details and example Swift code for iOS integration.
    execute: async (args: any): Promise<ToolResult> => { try { const payment = await lightningService.payInvoice(args.invoice); return { content: [{ type: 'text', text: JSON.stringify({ success: true, payment: { paymentHash: payment.paymentHash, paymentPreimage: payment.paymentPreimage, amountSats: Math.floor(payment.amountMsat / 1000), feeSats: Math.floor((payment.feeMsat || 0) / 1000), status: payment.status, timestamp: payment.timestamp }, swiftExample: ` // Swift code to handle payment in your iOS app import LightningDevKit func payInvoice(invoice: String, maxFeeSats: UInt64) async throws -> PaymentResult { let parsedInvoice = Bolt11Invoice.fromStr(s: invoice) guard let invoiceVal = parsedInvoice.getValue() else { throw PaymentError.invalidInvoice } let invoicePaymentResult = Bindings.paymentParametersFromInvoice(invoice: invoiceVal) guard invoicePaymentResult.isOk() else { throw PaymentError.invalidPaymentParams } let (paymentHash, recipientOnion, routeParams) = invoicePaymentResult.getValue()! let paymentId = invoiceVal.paymentHash()! // Set max fee routeParams.setMaxTotalFeeMsat(val: maxFeeSats * 1000) let res = channelManager.sendPayment( paymentHash: paymentHash, recipientOnion: recipientOnion, paymentId: paymentId, routeParams: routeParams, retryStrategy: .initWithTimeout(a: 15) ) if res.isOk() { // Payment initiated successfully return PaymentResult( paymentHash: paymentHash.toHex(), status: .pending ) } else { throw PaymentError.sendFailed(res.getError()!) } } // Handle payment events func handlePaymentEvent(event: Event) { if let paymentSent = event.getValueAsPaymentSent() { let paymentHash = paymentSent.getPaymentHash().toHex() let feePaidMsat = paymentSent.getFeePaidMsat()?.getValue() ?? 0 print("Payment sent successfully!") print("Payment hash: \\(paymentHash)") print("Fee paid: \\(feePaidMsat / 1000) sats") // Update UI DispatchQueue.main.async { self.updatePaymentStatus(hash: paymentHash, status: .succeeded) } } else if let paymentFailed = event.getValueAsPaymentFailed() { let paymentHash = paymentFailed.getPaymentHash().toHex() let reason = paymentFailed.getReason() print("Payment failed: \\(reason?.description ?? "Unknown")") // Update UI DispatchQueue.main.async { self.updatePaymentStatus(hash: paymentHash, status: .failed) } } }`.trim() }, null, 2) }] }; } catch (error) { return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: error instanceof Error ? error.message : 'Unknown error' }, null, 2) }], isError: true }; } }
  • Input schema defining the parameters for paying a Lightning invoice: required 'invoice' string and optional 'maxFeeSats' number.
    inputSchema: { type: 'object', properties: { invoice: { type: 'string', description: 'BOLT11 Lightning invoice to pay' }, maxFeeSats: { type: 'number', description: 'Maximum fee in satoshis willing to pay', default: 10 } }, required: ['invoice'] },
  • src/index.ts:38-62 (registration)
    Registration of the payInvoiceTool (line 40) in the central tools array used by the MCP server's ListTools and CallTool request handlers.
    const tools = [ generateInvoiceTool, payInvoiceTool, getChannelStatusTool, getNodeInfoTool, backupStateTool, keychainTestTool, backgroundTestTool, pushNotificationTool, biometricAuthTool, createChannelTool, closeChannelTool, getBalanceTool, decodeInvoiceTool, listPaymentsTool, estimateFeeTool, generateMnemonicTool, deriveAddressTool, getSwiftCodeTool, getArchitectureTool, testScenarioTool, networkGraphTool, eventHandlingTool, chainSyncTool, ];
  • Helper method in LightningService that implements the core payment logic: decodes the BOLT11 invoice, simulates successful payment, calculates fee, generates preimage, and stores the payment.
    async payInvoice(bolt11Invoice: string): Promise<Payment> { try { const decoded = bolt11.decode(bolt11Invoice); const paymentHash = decoded.tags.find(t => t.tagName === 'payment_hash')?.data as string; const amountMsat = parseInt(decoded.millisatoshis || '0'); const description = decoded.tags.find(t => t.tagName === 'description')?.data as string; const payment: Payment = { paymentHash, amountMsat, status: PaymentStatus.Succeeded, timestamp: Date.now(), description, bolt11: bolt11Invoice, feeMsat: Math.floor(amountMsat * 0.001), // 0.1% fee paymentPreimage: crypto.randomBytes(32).toString('hex') }; this.payments.set(paymentHash, payment); return payment; } catch (error) { throw new Error(`Failed to pay invoice: ${error}`); } }
  • src/index.ts:14-14 (registration)
    Import statement that brings the payInvoiceTool into the main index for registration.
    import { payInvoiceTool } from './tools/payInvoice.js';

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/StevenGeller/ldk-mcp'

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