From 56dfbec6bddf28329531d7c25f325504a1469909 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 23 Feb 2019 15:30:04 +1030 Subject: [PATCH] listpays: new command to summarize pay commands. This is to future-proof against multi-part-payments: the low-level commands will start returning multiple results once we have that, so prepare transition plan now. Closes: #2372 Signed-off-by: Rusty Russell --- CHANGELOG.md | 1 + doc/Makefile | 2 +- doc/lightning-listpays.7 | 108 +++++++++++++++++++++++++++++++++++ doc/lightning-listpays.7.txt | 49 ++++++++++++++++ doc/lightning-pay.7 | 8 +-- doc/lightning-pay.7.txt | 7 +-- plugins/pay.c | 90 +++++++++++++++++++++++++++++ 7 files changed, 255 insertions(+), 10 deletions(-) create mode 100644 doc/lightning-listpays.7 create mode 100644 doc/lightning-listpays.7.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index c9396dbd0..b01141d6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - JSON API: `fundchannel` and `withdraw` now have a new parameter `minconf` that limits coinselection to outputs that have at least `minconf` confirmations (default 1). (#2380) - JSON API: `listfunds` now displays addresses for all outputs owned by the wallet (#2387) - JSON API: `waitsendpay` and `sendpay` output field `label` as specified by `sendpay` call. +- JSON API: `listpays` command for higher-level payment view than `listpayments`, especially important with multi-part-payments coming. ### Changed diff --git a/doc/Makefile b/doc/Makefile index 78449841e..bd771ce22 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -21,6 +21,7 @@ MANPAGES := doc/lightning-cli.1 \ doc/lightning-listfunds.7 \ doc/lightning-listinvoices.7 \ doc/lightning-listpayments.7 \ + doc/lightning-listpays.7 \ doc/lightning-listpeers.7 \ doc/lightning-newaddr.7 \ doc/lightning-pay.7 \ @@ -29,7 +30,6 @@ MANPAGES := doc/lightning-cli.1 \ doc/lightning-waitanyinvoice.7 \ doc/lightning-waitsendpay.7 \ doc/lightning-withdraw.7 - doc-all: $(MANPAGES) diff --git a/doc/lightning-listpays.7 b/doc/lightning-listpays.7 new file mode 100644 index 000000000..0904b68c8 --- /dev/null +++ b/doc/lightning-listpays.7 @@ -0,0 +1,108 @@ +'\" t +.\" Title: lightning-listpays +.\" Author: [see the "AUTHOR" section] +.\" Generator: DocBook XSL Stylesheets v1.79.1 +.\" Date: 02/23/2019 +.\" Manual: \ \& +.\" Source: \ \& +.\" Language: English +.\" +.TH "LIGHTNING\-LISTPAYS" "7" "02/23/2019" "\ \&" "\ \&" +.\" ----------------------------------------------------------------- +.\" * Define some portability stuff +.\" ----------------------------------------------------------------- +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" http://bugs.debian.org/507673 +.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.\" ----------------------------------------------------------------- +.\" * MAIN CONTENT STARTS HERE * +.\" ----------------------------------------------------------------- +.SH "NAME" +lightning-listpays \- Command for querying payment status +.SH "SYNOPSIS" +.sp +\fBlistpays\fR [bolt11] +.SH "DESCRIPTION" +.sp +The \fBlistpay\fR RPC command gets the status of all \fIpay\fR commands, or a single one if \fIbolt11\fR is specified\&. +.SH "RETURN VALUE" +.sp +On success, an array of objects is returned\&. Each object contains: +.PP +\fIbolt11\fR +.RS 4 +the +\fIbolt11\fR +argument given to +\fIpay\fR +(see below for exceptions)\&. +.RE +.PP +\fIstatus\fR +.RS 4 +one of +\fIcomplete\fR, +\fIfailed\fR +or +\fIpending\fR\&. +.RE +.PP +\fIpayment_preimage\fR +.RS 4 +(if +\fIstatus\fR +is +\fIcomplete\fR) proves payment was received\&. +.RE +.PP +\fIlabel\fR +.RS 4 +optional +\fIlabel\fR, if provided to +\fIpay\fR\&. +.RE +.PP +\fIamount_sent_msat\fR +.RS 4 +total amount sent, in "NNNmsat" format\&. +.RE +.sp +For old payments (pre\-0\&.7) we didn\(cqt save the \fIbolt11\fR string, so in its place are three other fields: +.PP +\fIpayment_hash\fR +.RS 4 +the hash of the +\fIpayment_preimage\fR +which will prove payment\&. +.RE +.PP +\fIdestination\fR +.RS 4 +the final destination of the payment\&. +.RE +.PP +\fIamount_msat\fR +.RS 4 +the amount the destination received, in "NNNmsat" format\&. +.RE +.sp +These three can all be extracted from \fIbolt11\fR, hence are obsolete\&. +.SH "AUTHOR" +.sp +Rusty Russell is mainly responsible\&. +.SH "SEE ALSO" +.sp +lightning\-pay(7), lightning\-paystatus(7), lightning\-listpayments(7)\&. +.SH "RESOURCES" +.sp +Main web site: https://github\&.com/ElementsProject/lightning diff --git a/doc/lightning-listpays.7.txt b/doc/lightning-listpays.7.txt new file mode 100644 index 000000000..7155c37c7 --- /dev/null +++ b/doc/lightning-listpays.7.txt @@ -0,0 +1,49 @@ +LIGHTNING-LISTPAYS(7) +===================== +:doctype: manpage + +NAME +---- +lightning-listpays - Command for querying payment status + +SYNOPSIS +-------- +*listpays* [bolt11] + +DESCRIPTION +----------- + +The *listpay* RPC command gets the status of all 'pay' commands, or a single +one if 'bolt11' is specified. + +RETURN VALUE +------------ +On success, an array of objects is returned. Each object contains: + +'bolt11':: the 'bolt11' argument given to 'pay' (see below for exceptions). +'status':: one of 'complete', 'failed' or 'pending'. +'payment_preimage':: (if 'status' is 'complete') proves payment was received. +'label':: optional 'label', if provided to 'pay'. +'amount_sent_msat':: total amount sent, in "NNNmsat" format. + +For old payments (pre-0.7) we didn't save the 'bolt11' string, so in +its place are three other fields: + +'payment_hash':: the hash of the 'payment_preimage' which will prove payment. +'destination':: the final destination of the payment. +'amount_msat':: the amount the destination received, in "NNNmsat" format. + +These three can all be extracted from 'bolt11', hence are obsolete. +//FIXME:Enumerate errors + +AUTHOR +------ +Rusty Russell is mainly responsible. + +SEE ALSO +-------- +lightning-pay(7), lightning-paystatus(7), lightning-listpayments(7). + +RESOURCES +--------- +Main web site: https://github.com/ElementsProject/lightning diff --git a/doc/lightning-pay.7 b/doc/lightning-pay.7 index 57b3091e8..0158e6a84 100644 --- a/doc/lightning-pay.7 +++ b/doc/lightning-pay.7 @@ -40,7 +40,7 @@ The \fIlabel\fR field is used to attach a label to payments, and is returned in .sp The response will occur when the payment fails or succeeds\&. Once a payment has succeeded, calls to \fBpay\fR with the same \fIbolt11\fR will succeed immediately\&. .sp -The command will keep finding routes and retrying the payment until it succeeds, or the given \fIretry_for\fR seconds passes\&. Note that the command may stop retrying while a pending payment is ongoing, which you need to monitor with \fBlistpayments\fR or \fBwaitsendpay\fR\&. \fIretry_for\fR defaults to 60 seconds and can only be an integer\&. +The command will keep finding routes and retrying the payment until it succeeds, or the given \fIretry_for\fR seconds passes\&. Note that the command may stop retrying while a pending payment is ongoing, which you need to monitor with \fBlistpays\fR\&. \fIretry_for\fR defaults to 60 seconds and can only be an integer\&. .sp When using \fIlightning\-cli\fR, you may skip optional parameters by using \fInull\fR\&. Alternatively, use \fB\-k\fR option to provide parameters by name\&. .SH "RANDOMIZATION" @@ -102,9 +102,7 @@ The following error codes may occur: .IP \(bu 2.3 .\} 200\&. Payment timed out while a payment is in progress\&. Monitor the status of that payment with -\fIlistpayments\fR -command, or wait for that payment to complete with -\fIpay\fR +\fIlistpays\fR command\&. .RE .sp @@ -267,7 +265,7 @@ The \fIdata\fR field of errors will include statistics \fIgetroute_tries\fR and Rusty Russell is mainly responsible\&. .SH "SEE ALSO" .sp -lightning\-listpayments(7), lightning\-decodepay(7), lightning\-listinvoice(7), lightning\-delinvoice(7), lightning\-getroute(7), lightning\-invoice(7)\&. +lightning\-listpays(7), lightning\-decodepay(7), lightning\-listinvoice(7), lightning\-delinvoice(7), lightning\-getroute(7), lightning\-invoice(7)\&. .SH "RESOURCES" .sp Main web site: https://github\&.com/ElementsProject/lightning diff --git a/doc/lightning-pay.7.txt b/doc/lightning-pay.7.txt index 067dc5a65..3d2b79db3 100644 --- a/doc/lightning-pay.7.txt +++ b/doc/lightning-pay.7.txt @@ -40,7 +40,7 @@ succeed immediately. The command will keep finding routes and retrying the payment until it succeeds, or the given 'retry_for' seconds passes. Note that the command may stop retrying while a pending payment is -ongoing, which you need to monitor with *listpayments* or *waitsendpay*. +ongoing, which you need to monitor with *listpays*. 'retry_for' defaults to 60 seconds and can only be an integer. When using 'lightning-cli', you may skip optional parameters by using @@ -91,8 +91,7 @@ The following error codes may occur: * -1. Catchall nonspecific error. * 200. Payment timed out while a payment is in progress. Monitor - the status of that payment with 'listpayments' command, or - wait for that payment to complete with 'pay' command. + the status of that payment with 'listpays' command. * 201. Already paid with this 'hash' using different amount or destination. * 203. Permanent failure at destination. The 'data' field of @@ -145,7 +144,7 @@ Rusty Russell is mainly responsible. SEE ALSO -------- -lightning-listpayments(7), lightning-decodepay(7), +lightning-listpays(7), lightning-decodepay(7), lightning-listinvoice(7), lightning-delinvoice(7), lightning-getroute(7), lightning-invoice(7). diff --git a/plugins/pay.c b/plugins/pay.c index 893187fad..e36653409 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -1093,6 +1094,90 @@ static struct command_result *handle_paystatus(struct command *cmd, return command_success(cmd, ret); } +static const jsmntok_t *copy_member(char **ret, + const char *buf, + const jsmntok_t *result, + const char *membername, + const char *term) +{ + const jsmntok_t *m = json_get_member(buf, result, membername); + if (m) + tal_append_fmt(ret, "'%s': %.*s%s", + membername, + json_tok_full_len(m), json_tok_full(buf, m), + term); + return m; +} + +static struct command_result *listpayments_done(struct command *cmd, + const char *buf, + const jsmntok_t *result, + char *b11str) +{ + size_t i; + const jsmntok_t *t, *arr; + char *ret; + bool some = false; + + arr = json_get_member(buf, result, "payments"); + if (!arr || arr->type != JSMN_ARRAY) + return command_fail(cmd, LIGHTNINGD, + "Unexpected non-array result from listpayments"); + + ret = tal_fmt(cmd, "{ 'pays': ["); + json_for_each_arr(i, t, arr) { + const jsmntok_t *status; + + if (some) + tal_append_fmt(&ret, ",\n"); + some = true; + + tal_append_fmt(&ret, "{"); + /* Old payments didn't have bolt11 field */ + if (!copy_member(&ret, buf, t, "bolt11", ",")) { + if (b11str) { + /* If it's a single query, we can fake it */ + tal_append_fmt(&ret, "'bolt11': '%s',", b11str); + } else { + copy_member(&ret, buf, t, "payment_hash", ","); + copy_member(&ret, buf, t, "destination", ","); + copy_member(&ret, buf, t, "amount_msat", ","); + } + } + + status = copy_member(&ret, buf, t, "status", ","); + if (status && json_tok_streq(buf, status, "complete")) + copy_member(&ret, buf, t, "payment_preimage", ","); + copy_member(&ret, buf, t, "label", ","); + copy_member(&ret, buf, t, "amount_sent_msat", ""); + tal_append_fmt(&ret, "}"); + } + tal_append_fmt(&ret, "] }"); + return command_success(cmd, ret); +} + +static struct command_result *handle_listpays(struct command *cmd, + const char *buf, + const jsmntok_t *params) +{ + const char *b11str, *paramstr; + + /* FIXME: would be nice to parse as a bolt11 so check worked in future */ + if (!param(cmd, buf, params, + p_opt("bolt11", param_string, &b11str), + NULL)) + return NULL; + + if (b11str) + paramstr = tal_fmt(tmpctx, "'bolt11' : '%s'", b11str); + else + paramstr = ""; + return send_outreq(cmd, "listpayments", + listpayments_done, forward_error, + cast_const(char *, b11str), + "%s", paramstr); +} + static void init(struct plugin_conn *rpc) { const char *field; @@ -1117,6 +1202,11 @@ static const struct plugin_command commands[] = { { "Detail status of attempts to pay {bolt11}, or all", "Covers both old payments and current ones.", handle_paystatus + }, { + "listpays", + "List result of payment {bolt11}, or all", + "Covers old payments (failed and succeeded) and current ones.", + handle_listpays } };