From 70272d19f47144b4e35fa80f30e31ad86b112650 Mon Sep 17 00:00:00 2001 From: jamaljsr <1356600+jamaljsr@users.noreply.github.com> Date: Sat, 7 Dec 2019 03:34:01 -0500 Subject: [PATCH] feat(payments): implement payInvoice for LND nodes --- TODO.md | 1 - electron/lnd/lndProxyServer.ts | 18 ++++++++++++++++++ src/lib/lightning/lnd/lndProxyClient.ts | 8 ++++++++ src/lib/lightning/lnd/lndService.ts | 20 ++++++++++++++++---- src/shared/ipcChannels.ts | 2 ++ 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/TODO.md b/TODO.md index de84a96..b57ce09 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,6 @@ Small Stuff -- add Copy & Close button to CreateInvoiceModal - refactor: add redraw param to designer.syncChart() - fix pasting text in terminal - display bitcoin rpc user/pass in sidebar diff --git a/electron/lnd/lndProxyServer.ts b/electron/lnd/lndProxyServer.ts index 1d8898a..0c0312f 100644 --- a/electron/lnd/lndProxyServer.ts +++ b/electron/lnd/lndProxyServer.ts @@ -101,6 +101,22 @@ const createInvoice = async (args: { return await rpc.addInvoice(args.req); }; +const payInvoice = async (args: { + node: LndNode; + req: LND.SendRequest; +}): Promise => { + const rpc = await getRpc(args.node); + return await rpc.sendPaymentSync(args.req); +}; + +const decodeInvoice = async (args: { + node: LndNode; + req: LND.PayReqString; +}): Promise => { + const rpc = await getRpc(args.node); + return await rpc.decodePayReq(args.req); +}; + /** * A mapping of electron IPC channel names to the functions to execute when * messages are recieved @@ -118,6 +134,8 @@ const listeners: { [ipcChannels.listChannels]: listChannels, [ipcChannels.pendingChannels]: pendingChannels, [ipcChannels.createInvoice]: createInvoice, + [ipcChannels.payInvoice]: payInvoice, + [ipcChannels.decodeInvoice]: decodeInvoice, }; /** diff --git a/src/lib/lightning/lnd/lndProxyClient.ts b/src/lib/lightning/lnd/lndProxyClient.ts index 5e8a5bc..0804c97 100644 --- a/src/lib/lightning/lnd/lndProxyClient.ts +++ b/src/lib/lightning/lnd/lndProxyClient.ts @@ -55,6 +55,14 @@ class LndProxyClient { async createInvoice(node: LndNode, req: LND.Invoice): Promise { return await this.ipc(ipcChannels.createInvoice, { node, req }); } + + async payInvoice(node: LndNode, req: LND.SendRequest): Promise { + return await this.ipc(ipcChannels.payInvoice, { node, req }); + } + + async decodeInvoice(node: LndNode, req: LND.PayReqString): Promise { + return await this.ipc(ipcChannels.decodeInvoice, { node, req }); + } } export default new LndProxyClient(); diff --git a/src/lib/lightning/lnd/lndService.ts b/src/lib/lightning/lnd/lndService.ts index 5050f22..55681cb 100644 --- a/src/lib/lightning/lnd/lndService.ts +++ b/src/lib/lightning/lnd/lndService.ts @@ -120,14 +120,26 @@ class LndService implements LightningService { return res.paymentRequest; } - payInvoice( + async payInvoice( node: LightningNode, invoice: string, amount?: number, ): Promise { - throw new Error( - `payInvoice is not implemented for ${node.implementation} nodes ${invoice} ${amount}`, - ); + const req: LND.SendRequest = { + paymentRequest: invoice, + amt: amount ? amount.toString() : undefined, + }; + const res = await proxy.payInvoice(this.cast(node), req); + // handle errors manually + if (res.paymentError) throw new Error(res.paymentError); + + const payReq = await proxy.decodeInvoice(this.cast(node), { payReq: invoice }); + + return { + amount: parseInt(payReq.numSatoshis), + preimage: res.paymentPreimage.toString(), + destination: payReq.destination, + }; } /** diff --git a/src/shared/ipcChannels.ts b/src/shared/ipcChannels.ts index 5a13660..75227e0 100644 --- a/src/shared/ipcChannels.ts +++ b/src/shared/ipcChannels.ts @@ -13,4 +13,6 @@ export default { listChannels: 'list-channels', pendingChannels: 'pending-channels', createInvoice: 'create-invoice', + payInvoice: 'pay-invoice', + decodeInvoice: 'decode-invoice', };