mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-22 08:34:20 +01:00
libplugin: update API to use json_out.
We now hand around struct json_out members, rather than using formatted strings, so plugins need to construct them properly. There's no automatic conversion between ' and " any more, so those are eliminated too. pay still uses some manual construction of elements. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
344
plugins/pay.c
344
plugins/pay.c
@@ -1,6 +1,7 @@
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <ccan/intmap/intmap.h>
|
||||
#include <ccan/json_out/json_out.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <ccan/time/time.h>
|
||||
#include <common/amount.h>
|
||||
@@ -136,12 +137,38 @@ static void attempt_failed_tok(struct pay_command *pc, const char *method,
|
||||
buf + msg->start);
|
||||
else
|
||||
attempt_failed_fmt(pc,
|
||||
"{ 'message': 'Call to %s failed', %.*s",
|
||||
"{ \"message\": \"Call to %s failed\", %.*s",
|
||||
method,
|
||||
errtok->end - errtok->start - 1,
|
||||
buf + errtok->start + 1);
|
||||
}
|
||||
|
||||
/* Helper to copy JSON object directly into a json_out */
|
||||
static void json_out_add_raw_len(struct json_out *jout,
|
||||
const char *fieldname,
|
||||
const char *jsonstr, size_t len)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = json_out_member_direct(jout, fieldname, len);
|
||||
memcpy(p, jsonstr, len);
|
||||
}
|
||||
|
||||
static void json_out_add_raw(struct json_out *jout,
|
||||
const char *fieldname,
|
||||
const char *jsonstr)
|
||||
{
|
||||
json_out_add_raw_len(jout, fieldname, jsonstr, strlen(jsonstr));
|
||||
}
|
||||
|
||||
/* Helper to add a u64. */
|
||||
static void json_out_add_u64(struct json_out *jout,
|
||||
const char *fieldname,
|
||||
u64 val)
|
||||
{
|
||||
json_out_add(jout, fieldname, false, "%"PRIu64, val);
|
||||
}
|
||||
|
||||
static struct command_result *start_pay_attempt(struct command *cmd,
|
||||
struct pay_command *pc,
|
||||
const char *fmt, ...);
|
||||
@@ -178,24 +205,23 @@ static size_t count_sendpays(const struct pay_attempt *attempts)
|
||||
static struct command_result *waitsendpay_expired(struct command *cmd,
|
||||
struct pay_command *pc)
|
||||
{
|
||||
char *errmsg, *data;
|
||||
char *errmsg;
|
||||
struct json_out *data;
|
||||
size_t num_attempts = count_sendpays(pc->ps->attempts);
|
||||
|
||||
errmsg = tal_fmt(pc, "Gave up after %zu attempt%s: see paystatus",
|
||||
num_attempts, num_attempts == 1 ? "" : "s");
|
||||
data = tal_strdup(pc, "{ 'attempts': [ ");
|
||||
data = json_out_new(NULL);
|
||||
json_out_start(data, NULL, '{');
|
||||
json_out_start(data, "attempts", '[');
|
||||
for (size_t i = 0; i < tal_count(pc->ps->attempts); i++) {
|
||||
if (pc->ps->attempts[i].route)
|
||||
tal_append_fmt(&data, "%s { 'route': %s,\n 'failure': %s\n }",
|
||||
i == 0 ? "" : ",",
|
||||
pc->ps->attempts[i].route,
|
||||
pc->ps->attempts[i].failure);
|
||||
else
|
||||
tal_append_fmt(&data, "%s { 'failure': %s\n }",
|
||||
i == 0 ? "" : ",",
|
||||
pc->ps->attempts[i].failure);
|
||||
json_out_add_raw(data, "route",
|
||||
pc->ps->attempts[i].route);
|
||||
json_out_add_raw(data, "failure", pc->ps->attempts[i].failure);
|
||||
}
|
||||
tal_append_fmt(&data, "] }");
|
||||
json_out_end(data, ']');
|
||||
json_out_end(data, '}');
|
||||
return command_done_err(cmd, PAY_STOPPED_RETRYING, errmsg, data);
|
||||
}
|
||||
|
||||
@@ -315,8 +341,8 @@ static struct command_result *sendpay_done(struct command *cmd,
|
||||
{
|
||||
return send_outreq(cmd, "waitsendpay",
|
||||
waitsendpay_done, waitsendpay_error, pc,
|
||||
"'payment_hash': '%s'",
|
||||
pc->payment_hash);
|
||||
take(json_out_obj(NULL, "payment_hash",
|
||||
pc->payment_hash)));
|
||||
}
|
||||
|
||||
/* Calculate how many millisatoshi we need at the start of this route
|
||||
@@ -375,10 +401,10 @@ static const char *join_routehint(const tal_t *ctx,
|
||||
return tal_free(ret);
|
||||
|
||||
tal_append_fmt(&ret, ", {"
|
||||
" 'id': '%s',"
|
||||
" 'channel': '%s',"
|
||||
" 'msatoshi': '%s',"
|
||||
" 'delay': %u }",
|
||||
" \"id\": \"%s\","
|
||||
" \"channel\": \"%s\","
|
||||
" \"msatoshi\": \"%s\","
|
||||
" \"delay\": %u }",
|
||||
/* pubkey of *destination* */
|
||||
route_pubkey(tmpctx, pc, routehint, i + 1),
|
||||
type_to_string(tmpctx, struct short_channel_id,
|
||||
@@ -455,10 +481,10 @@ static struct command_result *getroute_done(struct command *cmd,
|
||||
{
|
||||
struct pay_attempt *attempt = current_attempt(pc);
|
||||
const jsmntok_t *t = json_get_member(buf, result, "route");
|
||||
char *json_desc;
|
||||
struct amount_msat fee;
|
||||
u32 delay;
|
||||
double feepercent;
|
||||
struct json_out *params;
|
||||
|
||||
if (!t)
|
||||
plugin_err("getroute gave no 'route'? '%.*s'",
|
||||
@@ -469,7 +495,7 @@ static struct command_result *getroute_done(struct command *cmd,
|
||||
pc, pc->current_routehint);
|
||||
if (!attempt->route) {
|
||||
attempt_failed_fmt(pc,
|
||||
"{ 'message': 'Joining routehint gave absurd fee' }");
|
||||
"{ \"message\": \"Joining routehint gave absurd fee\" }");
|
||||
return next_routehint(cmd, pc);
|
||||
}
|
||||
} else
|
||||
@@ -497,7 +523,7 @@ static struct command_result *getroute_done(struct command *cmd,
|
||||
&& feepercent > pc->maxfeepercent) {
|
||||
const jsmntok_t *charger;
|
||||
|
||||
attempt_failed_fmt(pc, "{ 'message': 'Route wanted fee of %s' }",
|
||||
attempt_failed_fmt(pc, "{ \"message\": \"Route wanted fee of %s\" }",
|
||||
type_to_string(tmpctx, struct amount_msat,
|
||||
&fee));
|
||||
|
||||
@@ -526,7 +552,7 @@ static struct command_result *getroute_done(struct command *cmd,
|
||||
const jsmntok_t *delayer;
|
||||
|
||||
attempt_failed_fmt(pc,
|
||||
"{ 'message': 'Route wanted delay of %u blocks' }",
|
||||
"{ \"message\": \"Route wanted delay of %u blocks\" }",
|
||||
delay);
|
||||
|
||||
/* Remember this if we eliminating this causes us to have no
|
||||
@@ -549,18 +575,18 @@ static struct command_result *getroute_done(struct command *cmd,
|
||||
return next_routehint(cmd, pc);
|
||||
}
|
||||
|
||||
if (pc->label)
|
||||
json_desc = tal_fmt(pc, ", 'label': '%s'", pc->label);
|
||||
else
|
||||
json_desc = "";
|
||||
|
||||
attempt->sendpay = true;
|
||||
params = json_out_new(NULL);
|
||||
json_out_start(params, NULL, '{');
|
||||
json_out_add_raw(params, "route", attempt->route);
|
||||
json_out_add(params, "payment_hash", true, "%s", pc->payment_hash);
|
||||
json_out_add(params, "bolt11", true, "%s", pc->ps->bolt11);
|
||||
if (pc->label)
|
||||
json_out_add(params, "label", true, "%s", pc->label);
|
||||
json_out_end(params, '}');
|
||||
|
||||
return send_outreq(cmd, "sendpay", sendpay_done, sendpay_error, pc,
|
||||
"'route': %s, 'payment_hash': '%s', 'bolt11': '%s'%s",
|
||||
attempt->route,
|
||||
pc->payment_hash,
|
||||
pc->ps->bolt11,
|
||||
json_desc);
|
||||
take(params));
|
||||
|
||||
}
|
||||
|
||||
@@ -600,7 +626,6 @@ static struct command_result *start_pay_attempt(struct command *cmd,
|
||||
struct pay_command *pc,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
char *exclude;
|
||||
struct amount_msat msat;
|
||||
const char *dest;
|
||||
size_t max_hops = ROUTING_MAX_HOPS;
|
||||
@@ -608,6 +633,7 @@ static struct command_result *start_pay_attempt(struct command *cmd,
|
||||
struct pay_attempt *attempt;
|
||||
va_list ap;
|
||||
size_t n;
|
||||
struct json_out *params;
|
||||
|
||||
n = tal_count(pc->ps->attempts);
|
||||
tal_resize(&pc->ps->attempts, n+1);
|
||||
@@ -627,17 +653,6 @@ static struct command_result *start_pay_attempt(struct command *cmd,
|
||||
|
||||
/* routehint set below. */
|
||||
|
||||
if (tal_count(pc->excludes) != 0) {
|
||||
exclude = tal_strdup(tmpctx, ",'exclude': [");
|
||||
for (size_t i = 0; i < tal_count(pc->excludes); i++)
|
||||
/* JSON.org grammar doesn't allow trailing , */
|
||||
tal_append_fmt(&exclude, "%s %s",
|
||||
i == 0 ? "" : ",",
|
||||
pc->excludes[i]);
|
||||
tal_append_fmt(&exclude, "]");
|
||||
} else
|
||||
exclude = "";
|
||||
|
||||
/* If we have a routehint, try that first; we need to do extra
|
||||
* checks that it meets our criteria though. */
|
||||
if (pc->current_routehint) {
|
||||
@@ -646,7 +661,7 @@ static struct command_result *start_pay_attempt(struct command *cmd,
|
||||
attempt->routehint,
|
||||
tal_count(attempt->routehint))) {
|
||||
attempt_failed_fmt(pc,
|
||||
"{ 'message': 'Routehint absurd fee' }");
|
||||
"{ \"message\": \"Routehint absurd fee\" }");
|
||||
return next_routehint(cmd, pc);
|
||||
}
|
||||
dest = type_to_string(tmpctx, struct node_id,
|
||||
@@ -663,15 +678,24 @@ static struct command_result *start_pay_attempt(struct command *cmd,
|
||||
}
|
||||
|
||||
/* OK, ask for route to destination */
|
||||
params = json_out_new(NULL);
|
||||
json_out_start(params, NULL, '{');
|
||||
json_out_addstr(params, "id", dest);
|
||||
json_out_addstr(params, "msatoshi",
|
||||
type_to_string(tmpctx, struct amount_msat, &msat));
|
||||
json_out_add_u64(params, "cltv", cltv);
|
||||
json_out_add_u64(params, "maxhops", max_hops);
|
||||
json_out_add(params, "riskfactor", false, "%f", pc->riskfactor);
|
||||
if (tal_count(pc->excludes) != 0) {
|
||||
json_out_start(params, "exclude", '[');
|
||||
for (size_t i = 0; i < tal_count(pc->excludes); i++)
|
||||
json_out_addstr(params, NULL, pc->excludes[i]);
|
||||
json_out_end(params, ']');
|
||||
}
|
||||
json_out_end(params, '}');
|
||||
|
||||
return send_outreq(cmd, "getroute", getroute_done, getroute_error, pc,
|
||||
"'id': '%s',"
|
||||
"'msatoshi': '%s',"
|
||||
"'cltv': %u,"
|
||||
"'maxhops': %zu,"
|
||||
"'riskfactor': %f%s",
|
||||
dest,
|
||||
type_to_string(tmpctx, struct amount_msat, &msat),
|
||||
cltv, max_hops, pc->riskfactor, exclude);
|
||||
take(params));
|
||||
}
|
||||
|
||||
/* BOLT #7:
|
||||
@@ -751,7 +775,7 @@ static struct command_result *shadow_route(struct command *cmd,
|
||||
|
||||
return send_outreq(cmd, "listchannels",
|
||||
add_shadow_route, forward_error, pc,
|
||||
"'source' : '%s'", pc->shadow_dest);
|
||||
take(json_out_obj(NULL, "source", pc->shadow_dest)));
|
||||
}
|
||||
|
||||
/* gossipd doesn't know much about the current state of channels; here we
|
||||
@@ -996,10 +1020,9 @@ static struct command_result *json_pay(struct command *cmd,
|
||||
pc->routehints = filter_routehints(pc, b11->routes);
|
||||
pc->expensive_route = NULL;
|
||||
|
||||
/* Get capacities of local channels. */
|
||||
/* Get capacities of local channels (no parameters) */
|
||||
return send_outreq(cmd, "listpeers", listpeers_done, forward_error, pc,
|
||||
/* gcc doesn't like zero-length format strings! */
|
||||
" ");
|
||||
take(json_out_obj(NULL, NULL, NULL)));
|
||||
}
|
||||
|
||||
/* FIXME: Add this to ccan/time? */
|
||||
@@ -1014,7 +1037,7 @@ static void utc_timestring(const struct timeabs *time, char str[UTC_TIMELEN])
|
||||
(int) time->ts.tv_nsec / 1000000);
|
||||
}
|
||||
|
||||
static void add_attempt(char **ret,
|
||||
static void add_attempt(struct json_out *ret,
|
||||
const struct pay_status *ps,
|
||||
const struct pay_attempt *attempt)
|
||||
{
|
||||
@@ -1022,62 +1045,56 @@ static void add_attempt(char **ret,
|
||||
|
||||
utc_timestring(&attempt->start, timestr);
|
||||
|
||||
tal_append_fmt(ret, "{ 'strategy': '%s',"
|
||||
" 'start_time': '%s',"
|
||||
" 'age_in_seconds': %"PRIu64,
|
||||
attempt->why,
|
||||
timestr,
|
||||
time_to_sec(time_between(time_now(), attempt->start)));
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_addstr(ret, "strategy", attempt->why);
|
||||
json_out_addstr(ret, "start_time", timestr);
|
||||
json_out_add_u64(ret, "age_in_seconds",
|
||||
time_to_sec(time_between(time_now(), attempt->start)));
|
||||
if (attempt->result || attempt->failure) {
|
||||
utc_timestring(&attempt->end, timestr);
|
||||
tal_append_fmt(ret, ", 'end_time': '%s'"
|
||||
", 'duration_in_seconds': %"PRIu64,
|
||||
timestr,
|
||||
time_to_sec(time_between(attempt->end,
|
||||
attempt->start)));
|
||||
json_out_addstr(ret, "end_time", timestr);
|
||||
json_out_add_u64(ret, "duration_in_seconds",
|
||||
time_to_sec(time_between(attempt->end,
|
||||
attempt->start)));
|
||||
}
|
||||
if (tal_count(attempt->routehint)) {
|
||||
tal_append_fmt(ret, ", 'routehint': [");
|
||||
json_out_start(ret, "routehint", '[');
|
||||
for (size_t i = 0; i < tal_count(attempt->routehint); i++) {
|
||||
tal_append_fmt(ret, "%s{"
|
||||
" 'id': '%s',"
|
||||
" 'channel': '%s',"
|
||||
" 'fee_base_msat': %u,"
|
||||
" 'fee_proportional_millionths': %u,"
|
||||
" 'cltv_expiry_delta': %u }",
|
||||
i == 0 ? "" : ", ",
|
||||
type_to_string(tmpctx, struct node_id,
|
||||
&attempt->routehint[i].pubkey),
|
||||
type_to_string(tmpctx,
|
||||
struct short_channel_id,
|
||||
&attempt->routehint[i].short_channel_id),
|
||||
attempt->routehint[i].fee_base_msat,
|
||||
attempt->routehint[i].fee_proportional_millionths,
|
||||
attempt->routehint[i].cltv_expiry_delta);
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_addstr(ret, "id",
|
||||
type_to_string(tmpctx, struct node_id,
|
||||
&attempt->routehint[i].pubkey));
|
||||
json_out_addstr(ret, "channel",
|
||||
type_to_string(tmpctx,
|
||||
struct short_channel_id,
|
||||
&attempt->routehint[i].short_channel_id));
|
||||
json_out_add_u64(ret, "fee_base_msat",
|
||||
attempt->routehint[i].fee_base_msat);
|
||||
json_out_add_u64(ret, "fee_proportional_millionths",
|
||||
attempt->routehint[i].fee_proportional_millionths);
|
||||
json_out_add_u64(ret, "cltv_expiry_delta",
|
||||
attempt->routehint[i].cltv_expiry_delta);
|
||||
json_out_end(ret, '}');
|
||||
}
|
||||
tal_append_fmt(ret, "]");
|
||||
json_out_end(ret, ']');
|
||||
}
|
||||
if (tal_count(attempt->excludes)) {
|
||||
for (size_t i = 0; i < tal_count(attempt->excludes); i++) {
|
||||
if (i == 0)
|
||||
tal_append_fmt(ret, ", 'excluded_channels': [");
|
||||
else
|
||||
tal_append_fmt(ret, ", ");
|
||||
tal_append_fmt(ret, "'%s'", attempt->excludes[i]);
|
||||
}
|
||||
tal_append_fmt(ret, "]");
|
||||
json_out_start(ret, "excluded_channels", '[');
|
||||
for (size_t i = 0; i < tal_count(attempt->excludes); i++)
|
||||
json_out_addstr(ret, NULL, attempt->excludes[i]);
|
||||
json_out_end(ret, ']');
|
||||
}
|
||||
|
||||
if (attempt->route)
|
||||
tal_append_fmt(ret, ", 'route': %s", attempt->route);
|
||||
json_out_add_raw(ret, "route", attempt->route);
|
||||
|
||||
if (attempt->failure)
|
||||
tal_append_fmt(ret, ", 'failure': %s", attempt->failure);
|
||||
json_out_add_raw(ret, "failure", attempt->failure);
|
||||
|
||||
if (attempt->result)
|
||||
tal_append_fmt(ret, ", 'success': %s", attempt->result);
|
||||
json_out_add_raw(ret, "success", attempt->result);
|
||||
|
||||
tal_append_fmt(ret, "}");
|
||||
json_out_end(ret, '}');
|
||||
}
|
||||
|
||||
static struct command_result *json_paystatus(struct command *cmd,
|
||||
@@ -1086,71 +1103,65 @@ static struct command_result *json_paystatus(struct command *cmd,
|
||||
{
|
||||
struct pay_status *ps;
|
||||
const char *b11str;
|
||||
char *ret;
|
||||
bool some = false;
|
||||
struct json_out *ret;
|
||||
|
||||
if (!param(cmd, buf, params,
|
||||
p_opt("bolt11", param_string, &b11str),
|
||||
NULL))
|
||||
return NULL;
|
||||
|
||||
ret = tal_fmt(cmd, "{ 'pay': [");
|
||||
ret = json_out_new(NULL);
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_start(ret, "pay", '[');
|
||||
|
||||
/* FIXME: Index by bolt11 string! */
|
||||
list_for_each(&pay_status, ps, list) {
|
||||
if (b11str && !streq(b11str, ps->bolt11))
|
||||
continue;
|
||||
|
||||
if (some)
|
||||
tal_append_fmt(&ret, ",\n");
|
||||
some = true;
|
||||
|
||||
tal_append_fmt(&ret, "{ 'bolt11': '%s',"
|
||||
" 'msatoshi': %"PRIu64", "
|
||||
" 'amount_msat': '%s', "
|
||||
" 'destination': '%s'",
|
||||
ps->bolt11,
|
||||
ps->msat.millisatoshis, /* Raw: JSON */
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_addstr(ret, "bolt11", ps->bolt11);
|
||||
json_out_add_u64(ret, "msatoshi",
|
||||
ps->msat.millisatoshis); /* Raw: JSON */
|
||||
json_out_addstr(ret, "amount_msat",
|
||||
type_to_string(tmpctx, struct amount_msat,
|
||||
&ps->msat), ps->dest);
|
||||
&ps->msat));
|
||||
json_out_addstr(ret, "destination", ps->dest);
|
||||
if (ps->label)
|
||||
tal_append_fmt(&ret, ", 'label': '%s'", ps->label);
|
||||
json_out_addstr(ret, "label", ps->label);
|
||||
if (ps->routehint_modifications)
|
||||
tal_append_fmt(&ret, ", 'routehint_modifications': '%s'",
|
||||
ps->routehint_modifications);
|
||||
json_out_addstr(ret, "routehint_modifications",
|
||||
ps->routehint_modifications);
|
||||
if (ps->shadow && !streq(ps->shadow, ""))
|
||||
tal_append_fmt(&ret, ", 'shadow': '%s'", ps->shadow);
|
||||
json_out_addstr(ret, "shadow", ps->shadow);
|
||||
if (ps->exclusions)
|
||||
tal_append_fmt(&ret, ", 'local_exclusions': '%s'",
|
||||
ps->exclusions);
|
||||
json_out_addstr(ret, "local_exclusions", ps->exclusions);
|
||||
|
||||
assert(tal_count(ps->attempts));
|
||||
for (size_t i = 0; i < tal_count(ps->attempts); i++) {
|
||||
if (i == 0)
|
||||
tal_append_fmt(&ret, ", 'attempts': [");
|
||||
else
|
||||
tal_append_fmt(&ret, ",");
|
||||
|
||||
add_attempt(&ret, ps, &ps->attempts[i]);
|
||||
}
|
||||
tal_append_fmt(&ret, "] }");
|
||||
json_out_start(ret, "attempts", '[');
|
||||
for (size_t i = 0; i < tal_count(ps->attempts); i++)
|
||||
add_attempt(ret, ps, &ps->attempts[i]);
|
||||
json_out_end(ret, ']');
|
||||
json_out_end(ret, '}');
|
||||
}
|
||||
tal_append_fmt(&ret, "] }");
|
||||
json_out_end(ret, ']');
|
||||
json_out_end(ret, '}');
|
||||
|
||||
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)
|
||||
/* Copy field and member to output, if it exists: return member */
|
||||
static const jsmntok_t *copy_member(struct json_out *ret,
|
||||
const char *buf, const jsmntok_t *obj,
|
||||
const char *membername)
|
||||
{
|
||||
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);
|
||||
const jsmntok_t *m = json_get_member(buf, obj, membername);
|
||||
if (!m)
|
||||
return NULL;
|
||||
|
||||
/* Literal copy: it's already JSON escaped, and may be a string. */
|
||||
json_out_add_raw_len(ret, membername,
|
||||
json_tok_full(buf, m), json_tok_full_len(m));
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -1175,33 +1186,30 @@ static struct command_result *listsendpays_done(struct command *cmd,
|
||||
{
|
||||
size_t i;
|
||||
const jsmntok_t *t, *arr;
|
||||
char *ret;
|
||||
bool some = false;
|
||||
struct json_out *ret;
|
||||
|
||||
arr = json_get_member(buf, result, "payments");
|
||||
if (!arr || arr->type != JSMN_ARRAY)
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"Unexpected non-array result from listsendpays");
|
||||
|
||||
ret = tal_fmt(cmd, "{ 'pays': [");
|
||||
ret = json_out_new(NULL);
|
||||
json_out_start(ret, NULL, '{');
|
||||
json_out_start(ret, "pays", '[');
|
||||
json_for_each_arr(i, t, arr) {
|
||||
const jsmntok_t *status, *b11;
|
||||
|
||||
if (some)
|
||||
tal_append_fmt(&ret, ",\n");
|
||||
some = true;
|
||||
|
||||
tal_append_fmt(&ret, "{");
|
||||
json_out_start(ret, NULL, '{');
|
||||
/* Old payments didn't have bolt11 field */
|
||||
b11 = copy_member(&ret, buf, t, "bolt11", ",");
|
||||
b11 = copy_member(ret, buf, t, "bolt11");
|
||||
if (!b11) {
|
||||
if (b11str) {
|
||||
/* If it's a single query, we can fake it */
|
||||
tal_append_fmt(&ret, "'bolt11': '%s',", b11str);
|
||||
json_out_addstr(ret, "bolt11", b11str);
|
||||
} else {
|
||||
copy_member(&ret, buf, t, "payment_hash", ",");
|
||||
copy_member(&ret, buf, t, "destination", ",");
|
||||
copy_member(&ret, buf, t, "amount_msat", ",");
|
||||
copy_member(ret, buf, t, "payment_hash");
|
||||
copy_member(ret, buf, t, "destination");
|
||||
copy_member(ret, buf, t, "amount_msat");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1210,19 +1218,20 @@ static struct command_result *listsendpays_done(struct command *cmd,
|
||||
if (status) {
|
||||
if (json_tok_streq(buf, status, "failed")
|
||||
&& attempt_ongoing(buf, b11)) {
|
||||
tal_append_fmt(&ret, "'status': 'pending',");
|
||||
json_out_addstr(ret, "status", "pending");
|
||||
} else {
|
||||
copy_member(&ret, buf, t, "status", ",");
|
||||
copy_member(ret, buf, t, "status");
|
||||
if (json_tok_streq(buf, status, "complete"))
|
||||
copy_member(&ret, buf, t,
|
||||
"payment_preimage", ",");
|
||||
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, "}");
|
||||
copy_member(ret, buf, t, "label");
|
||||
copy_member(ret, buf, t, "amount_sent_msat");
|
||||
json_out_end(ret, '}');
|
||||
}
|
||||
tal_append_fmt(&ret, "] }");
|
||||
json_out_end(ret, ']');
|
||||
json_out_end(ret, '}');
|
||||
return command_success(cmd, ret);
|
||||
}
|
||||
|
||||
@@ -1230,7 +1239,7 @@ static struct command_result *json_listpays(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
const char *b11str, *paramstr;
|
||||
const char *b11str;
|
||||
|
||||
/* FIXME: would be nice to parse as a bolt11 so check worked in future */
|
||||
if (!param(cmd, buf, params,
|
||||
@@ -1238,26 +1247,25 @@ static struct command_result *json_listpays(struct command *cmd,
|
||||
NULL))
|
||||
return NULL;
|
||||
|
||||
if (b11str)
|
||||
paramstr = tal_fmt(tmpctx, "'bolt11' : '%s'", b11str);
|
||||
else
|
||||
paramstr = "";
|
||||
return send_outreq(cmd, "listsendpays",
|
||||
listsendpays_done, forward_error,
|
||||
cast_const(char *, b11str),
|
||||
"%s", paramstr);
|
||||
/* Neatly returns empty object if b11str is NULL */
|
||||
take(json_out_obj(NULL, "bolt11", b11str)));
|
||||
}
|
||||
|
||||
static void init(struct plugin_conn *rpc)
|
||||
{
|
||||
const char *field;
|
||||
|
||||
field = rpc_delve(tmpctx, "getinfo", "", rpc, ".id");
|
||||
field = rpc_delve(tmpctx, "getinfo",
|
||||
take(json_out_obj(NULL, NULL, NULL)), rpc, ".id");
|
||||
if (!node_id_from_hexstr(field, strlen(field), &my_id))
|
||||
plugin_err("getinfo didn't contain valid id: '%s'", field);
|
||||
|
||||
field = rpc_delve(tmpctx, "listconfigs",
|
||||
"'config': 'max-locktime-blocks'",
|
||||
take(json_out_obj(NULL,
|
||||
"config", "max-locktime-blocks")),
|
||||
rpc, ".max-locktime-blocks");
|
||||
maxdelay_default = atoi(field);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user