mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 01:43:36 +01:00
bkpr: command to calculate some APYs/stats on channel routing fees
Computes some stats from the net routed fees etc ``` { "channel_apys": [ { "account": "7de277250f8003c35378c1eb20aacf8fa6a69dd4bb22077266329a9ad812cd5d", "routed_out": "2000msat", "routed_in": "125100101msat", "lease_fee_paid": "0msat", "lease_fee_earned": "670000msat", "pushed_out": "0msat", "pushed_in": "0msat", "our_start_balance": "100670000msat", "channel_start_balance": "1100670000msat", "fees_out": "0msat", "fees_in": "10100101msat", "utilization_out": "0.0002%", "utilization_out_initial": "0.0020%", "utilization_in": "11.3658%", "utilization_in_initial": "12.5100%", "apy_out": "0.0000%", "apy_out_initial": "0.0000%", "apy_in": "3203.3924%", "apy_in_initial": "3525.8779%", "apy_total": "3203.3924%", "apy_total_initial": "3203.3924%", "apy_lease": "8.7014%" }, { "account": "b71937a02eb7694d946c311297ca2da454057c5c3e97ac67500739cc2afbc0c5", "routed_out": "110000000msat", "routed_in": "0msat", "lease_fee_paid": "670000msat", "lease_fee_earned": "0msat", "pushed_out": "0msat", "pushed_in": "0msat", "our_start_balance": "4000000000msat", "channel_start_balance": "4100670000msat", "fees_out": "10100101msat", "fees_in": "0msat", "utilization_out": "2.6825%", "utilization_out_initial": "2.7500%", "utilization_in": "0.0000%", "utilization_in_initial": "0.0000%", "apy_out": "2579.4892%", "apy_out_initial": "2644.4084%", "apy_in": "0.0000%", "apy_in_initial": "0.0000%", "apy_total": "2579.4892%", "apy_total_initial": "2579.4892%" }, { "account": "net", "routed_out": "110002000msat", "routed_in": "125100101msat", "lease_fee_paid": "670000msat", "lease_fee_earned": "670000msat", "pushed_out": "0msat", "pushed_in": "0msat", "our_start_balance": "4100670000msat", "channel_start_balance": "5201340000msat", "fees_out": "10100101msat", "fees_in": "10100101msat", "utilization_out": "2.1149%", "utilization_out_initial": "2.6825%", "utilization_in": "2.4052%", "utilization_in_initial": "11.3658%", "apy_out": "677.8788%", "apy_out_initial": "859.8297%", "apy_in": "677.8788%", "apy_in_initial": "3203.3924%", "apy_total": "1355.7575%", "apy_total_initial": "1355.7575%", "apy_lease": "0.2122%" } ] } ```
This commit is contained in:
parent
c05900c676
commit
ee47715a1b
@ -6,6 +6,7 @@ BOOKKEEPER_PLUGIN_SRC := \
|
||||
plugins/bkpr/bookkeeper.c \
|
||||
plugins/bkpr/chain_event.c \
|
||||
plugins/bkpr/channel_event.c \
|
||||
plugins/bkpr/channelsapy.c \
|
||||
plugins/bkpr/db.c \
|
||||
plugins/bkpr/incomestmt.c \
|
||||
plugins/bkpr/onchain_fee.c \
|
||||
@ -21,6 +22,7 @@ BOOKKEEPER_HEADER := \
|
||||
plugins/bkpr/account_entry.h \
|
||||
plugins/bkpr/chain_event.h \
|
||||
plugins/bkpr/channel_event.h \
|
||||
plugins/bkpr/channelsapy.h \
|
||||
plugins/bkpr/db.h \
|
||||
plugins/bkpr/incomestmt.h \
|
||||
plugins/bkpr/onchain_fee.h \
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <plugins/bkpr/account_entry.h>
|
||||
#include <plugins/bkpr/chain_event.h>
|
||||
#include <plugins/bkpr/channel_event.h>
|
||||
#include <plugins/bkpr/channelsapy.h>
|
||||
#include <plugins/bkpr/db.h>
|
||||
#include <plugins/bkpr/incomestmt.h>
|
||||
#include <plugins/bkpr/onchain_fee.h>
|
||||
@ -41,6 +42,55 @@ static struct fee_sum *find_sum_for_txid(struct fee_sum **sums,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct command_result *json_channel_apy(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
struct json_stream *res;
|
||||
struct channel_apy **apys, *net_apys;
|
||||
u64 *start_time, *end_time;
|
||||
|
||||
if (!param(cmd, buf, params,
|
||||
p_opt_def("start_time", param_u64, &start_time, 0),
|
||||
p_opt_def("end_time", param_u64, &end_time, SQLITE_MAX_UINT),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
/* Get the income events */
|
||||
db_begin_transaction(db);
|
||||
apys = compute_channel_apys(cmd, db, *start_time, *end_time,
|
||||
/* FIXME: current blockheight */
|
||||
1414);
|
||||
db_commit_transaction(db);
|
||||
|
||||
/* Setup the net_apys entry */
|
||||
net_apys = new_channel_apy(cmd);
|
||||
net_apys->end_blockheight = 0;
|
||||
net_apys->start_blockheight = UINT_MAX;
|
||||
net_apys->our_start_bal = AMOUNT_MSAT(0);
|
||||
net_apys->total_start_bal = AMOUNT_MSAT(0);
|
||||
|
||||
res = jsonrpc_stream_success(cmd);
|
||||
json_array_start(res, "channel_apys");
|
||||
for (size_t i = 0; i < tal_count(apys); i++) {
|
||||
json_add_channel_apy(res, apys[i]);
|
||||
|
||||
/* Add to net/rollup APY */
|
||||
if (!channel_apy_sum(net_apys, apys[i]))
|
||||
return command_fail(cmd, PLUGIN_ERROR,
|
||||
"Overflow adding APYs net");
|
||||
}
|
||||
|
||||
/* Append a net/rollup entry */
|
||||
if (!amount_msat_zero(net_apys->total_start_bal)) {
|
||||
net_apys->acct_name = tal_fmt(net_apys, "net");
|
||||
json_add_channel_apy(res, net_apys);
|
||||
}
|
||||
json_array_end(res);
|
||||
|
||||
return command_finished(cmd, res);
|
||||
}
|
||||
|
||||
static struct command_result *param_csv_format(struct command *cmd, const char *name,
|
||||
const char *buffer, const jsmntok_t *tok,
|
||||
struct csv_fmt **csv_fmt)
|
||||
@ -1385,6 +1435,13 @@ static const struct plugin_command commands[] = {
|
||||
" (default: true)",
|
||||
json_dump_income
|
||||
},
|
||||
{
|
||||
"channelsapy",
|
||||
"bookkeeping",
|
||||
"Stats on channel fund usage",
|
||||
"Print out stats on chanenl fund usage",
|
||||
json_channel_apy
|
||||
},
|
||||
};
|
||||
|
||||
static const char *init(struct plugin *p, const char *b, const jsmntok_t *t)
|
||||
|
413
plugins/bkpr/channelsapy.c
Normal file
413
plugins/bkpr/channelsapy.c
Normal file
@ -0,0 +1,413 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/asort/asort.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/json_stream.h>
|
||||
#include <common/lease_rates.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <db/bindings.h>
|
||||
#include <db/common.h>
|
||||
#include <db/exec.h>
|
||||
#include <db/utils.h>
|
||||
#include <plugins/bkpr/account.h>
|
||||
#include <plugins/bkpr/account_entry.h>
|
||||
#include <plugins/bkpr/chain_event.h>
|
||||
#include <plugins/bkpr/channel_event.h>
|
||||
#include <plugins/bkpr/channelsapy.h>
|
||||
#include <plugins/bkpr/onchain_fee.h>
|
||||
#include <plugins/bkpr/recorder.h>
|
||||
|
||||
#define BLOCK_YEAR 52364
|
||||
|
||||
static int cmp_channel_event_acct(struct channel_event *const *ev1,
|
||||
struct channel_event *const *ev2,
|
||||
void *unused UNUSED)
|
||||
{
|
||||
if ((*ev1)->acct_db_id < (*ev2)->acct_db_id)
|
||||
return -1;
|
||||
else if ((*ev1)->acct_db_id > (*ev2)->acct_db_id)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmp_acct(struct account *const *a1,
|
||||
struct account *const *a2,
|
||||
void *unused UNUSED)
|
||||
{
|
||||
if ((*a1)->db_id < (*a2)->db_id)
|
||||
return -1;
|
||||
else if ((*a1)->db_id > (*a2)->db_id)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct channel_apy *new_channel_apy(const tal_t *ctx)
|
||||
{
|
||||
struct channel_apy *apy = tal(ctx, struct channel_apy);
|
||||
|
||||
apy->routed_in = AMOUNT_MSAT(0);
|
||||
apy->routed_out = AMOUNT_MSAT(0);
|
||||
apy->fees_in = AMOUNT_MSAT(0);
|
||||
apy->fees_out = AMOUNT_MSAT(0);
|
||||
apy->push_in = AMOUNT_MSAT(0);
|
||||
apy->push_out = AMOUNT_MSAT(0);
|
||||
apy->lease_in = AMOUNT_MSAT(0);
|
||||
apy->lease_out = AMOUNT_MSAT(0);
|
||||
return apy;
|
||||
}
|
||||
|
||||
bool channel_apy_sum(struct channel_apy *sum_apy,
|
||||
const struct channel_apy *entry)
|
||||
{
|
||||
bool ok;
|
||||
ok = amount_msat_add(&sum_apy->routed_in,
|
||||
sum_apy->routed_in,
|
||||
entry->routed_in);
|
||||
ok &= amount_msat_add(&sum_apy->routed_out,
|
||||
sum_apy->routed_out,
|
||||
entry->routed_out);
|
||||
ok &= amount_msat_add(&sum_apy->fees_in,
|
||||
sum_apy->fees_in,
|
||||
entry->fees_in);
|
||||
ok &= amount_msat_add(&sum_apy->fees_out,
|
||||
sum_apy->fees_out,
|
||||
entry->fees_out);
|
||||
ok &= amount_msat_add(&sum_apy->push_in,
|
||||
sum_apy->push_in,
|
||||
entry->push_in);
|
||||
ok &= amount_msat_add(&sum_apy->push_out,
|
||||
sum_apy->push_out,
|
||||
entry->push_out);
|
||||
ok &= amount_msat_add(&sum_apy->lease_in,
|
||||
sum_apy->lease_in,
|
||||
entry->lease_in);
|
||||
ok &= amount_msat_add(&sum_apy->lease_out,
|
||||
sum_apy->lease_out,
|
||||
entry->lease_out);
|
||||
|
||||
ok &= amount_msat_add(&sum_apy->our_start_bal,
|
||||
sum_apy->our_start_bal,
|
||||
entry->our_start_bal);
|
||||
|
||||
ok &= amount_msat_add(&sum_apy->total_start_bal,
|
||||
sum_apy->total_start_bal,
|
||||
entry->total_start_bal);
|
||||
|
||||
if (sum_apy->start_blockheight > entry->start_blockheight)
|
||||
sum_apy->start_blockheight = entry->start_blockheight;
|
||||
|
||||
if (sum_apy->end_blockheight < entry->end_blockheight)
|
||||
sum_apy->end_blockheight = entry->end_blockheight;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static struct account *search_account(struct account **accts, u64 acct_id)
|
||||
{
|
||||
for (size_t i = 0; i < tal_count(accts); i++) {
|
||||
if (accts[i]->db_id == acct_id)
|
||||
return accts[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void fillin_apy_acct_details(struct db *db,
|
||||
const struct account *acct,
|
||||
u32 current_blockheight,
|
||||
struct channel_apy *apy)
|
||||
{
|
||||
struct chain_event *ev;
|
||||
bool ok;
|
||||
|
||||
apy->acct_name = tal_strdup(apy, acct->name);
|
||||
|
||||
assert(acct->open_event_db_id);
|
||||
ev = find_chain_event_by_id(acct, db, *acct->open_event_db_id);
|
||||
assert(ev);
|
||||
|
||||
apy->start_blockheight = ev->blockheight;
|
||||
apy->our_start_bal = ev->credit;
|
||||
apy->total_start_bal = ev->output_value;
|
||||
|
||||
/* if this account is closed, add closing blockheight */
|
||||
if (acct->closed_event_db_id) {
|
||||
ev = find_chain_event_by_id(acct, db,
|
||||
*acct->closed_event_db_id);
|
||||
assert(ev);
|
||||
apy->end_blockheight = ev->blockheight;
|
||||
} else
|
||||
apy->end_blockheight = current_blockheight;
|
||||
|
||||
/* If there is any push_out or lease_fees_out, we subtract
|
||||
* from starting balance */
|
||||
ok = amount_msat_sub(&apy->our_start_bal, apy->our_start_bal,
|
||||
apy->push_out);
|
||||
assert(ok);
|
||||
ok = amount_msat_sub(&apy->our_start_bal, apy->our_start_bal,
|
||||
apy->lease_out);
|
||||
assert(ok);
|
||||
|
||||
/* we add values in to starting balance */
|
||||
ok = amount_msat_add(&apy->our_start_bal, apy->our_start_bal,
|
||||
apy->push_in);
|
||||
assert(ok);
|
||||
ok = amount_msat_add(&apy->our_start_bal, apy->our_start_bal,
|
||||
apy->lease_in);
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
struct channel_apy **compute_channel_apys(const tal_t *ctx, struct db *db,
|
||||
u64 start_time,
|
||||
u64 end_time,
|
||||
u32 current_blockheight)
|
||||
{
|
||||
struct channel_event **evs;
|
||||
struct channel_apy *apy, **apys;
|
||||
struct account *acct, **accts;
|
||||
|
||||
evs = list_channel_events_timebox(ctx, db, start_time, end_time);
|
||||
accts = list_accounts(ctx, db);
|
||||
|
||||
apys = tal_arr(ctx, struct channel_apy *, 0);
|
||||
|
||||
/* Sort events by acct_name */
|
||||
asort(evs, tal_count(evs), cmp_channel_event_acct, NULL);
|
||||
/* Sort accounts by name also */
|
||||
asort(accts, tal_count(accts), cmp_acct, NULL);
|
||||
|
||||
acct = NULL;
|
||||
apy = new_channel_apy(apys);
|
||||
for (size_t i = 0; i < tal_count(evs); i++) {
|
||||
struct channel_event *ev = evs[i];
|
||||
bool ok;
|
||||
|
||||
if (!acct || acct->db_id != ev->acct_db_id) {
|
||||
if (acct && is_channel_account(acct)) {
|
||||
fillin_apy_acct_details(db, acct,
|
||||
current_blockheight,
|
||||
apy);
|
||||
/* Save current apy, make new */
|
||||
tal_arr_expand(&apys, apy);
|
||||
apy = new_channel_apy(apys);
|
||||
}
|
||||
acct = search_account(accts, ev->acct_db_id);
|
||||
assert(acct);
|
||||
}
|
||||
|
||||
/* No entry for external or wallet accts */
|
||||
if (!is_channel_account(acct))
|
||||
continue;
|
||||
|
||||
/* Accumulate routing stats */
|
||||
if (streq("routed", ev->tag)
|
||||
|| streq("invoice", ev->tag)) {
|
||||
ok = amount_msat_add(&apy->routed_in,
|
||||
apy->routed_in,
|
||||
ev->credit);
|
||||
assert(ok);
|
||||
ok = amount_msat_add(&apy->routed_out,
|
||||
apy->routed_out,
|
||||
ev->debit);
|
||||
assert(ok);
|
||||
|
||||
/* No fees for invoices */
|
||||
if (streq("invoice", ev->tag))
|
||||
continue;
|
||||
|
||||
if (!amount_msat_zero(ev->credit))
|
||||
ok = amount_msat_add(&apy->fees_in,
|
||||
apy->fees_in,
|
||||
ev->fees);
|
||||
else
|
||||
ok = amount_msat_add(&apy->fees_out,
|
||||
apy->fees_out,
|
||||
ev->fees);
|
||||
assert(ok);
|
||||
}
|
||||
else if (streq("pushed", ev->tag)) {
|
||||
ok = amount_msat_add(&apy->push_in,
|
||||
apy->push_in,
|
||||
ev->credit);
|
||||
assert(ok);
|
||||
ok = amount_msat_add(&apy->push_out,
|
||||
apy->push_out,
|
||||
ev->debit);
|
||||
assert(ok);
|
||||
} else if (streq("lease_fee", ev->tag)) {
|
||||
ok = amount_msat_add(&apy->lease_in,
|
||||
apy->lease_in,
|
||||
ev->credit);
|
||||
assert(ok);
|
||||
ok = amount_msat_add(&apy->lease_out,
|
||||
apy->lease_out,
|
||||
ev->debit);
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
/* Note: we ignore 'journal_entry's because there's no
|
||||
* relevant fee data attached to them */
|
||||
}
|
||||
|
||||
if (acct && is_channel_account(acct)) {
|
||||
fillin_apy_acct_details(db, acct,
|
||||
current_blockheight,
|
||||
apy);
|
||||
/* Save current apy, make new */
|
||||
tal_arr_expand(&apys, apy);
|
||||
}
|
||||
|
||||
return apys;
|
||||
}
|
||||
|
||||
WARN_UNUSED_RESULT static bool calc_apy(struct amount_msat earned,
|
||||
struct amount_msat capital,
|
||||
u32 blocks_elapsed,
|
||||
double *result)
|
||||
{
|
||||
double apy;
|
||||
|
||||
assert(!amount_msat_zero(capital));
|
||||
assert(blocks_elapsed > 0);
|
||||
|
||||
apy = amount_msat_ratio(earned, capital) * BLOCK_YEAR / blocks_elapsed;
|
||||
|
||||
/* convert to percent */
|
||||
apy *= 100;
|
||||
|
||||
/* If mantissa is < 64 bits, a naive "if (scaled >
|
||||
* UINT64_MAX)" doesn't work. Stick to powers of 2. */
|
||||
if (apy >= (double)((u64)1 << 63) * 2)
|
||||
return false;
|
||||
|
||||
*result = apy;
|
||||
return true;
|
||||
}
|
||||
|
||||
void json_add_channel_apy(struct json_stream *res,
|
||||
const struct channel_apy *apy)
|
||||
{
|
||||
bool ok;
|
||||
u32 blocks_elapsed;
|
||||
double apy_result, utilization;
|
||||
struct amount_msat total_fees, their_start_bal;
|
||||
|
||||
ok = amount_msat_sub(&their_start_bal, apy->total_start_bal,
|
||||
apy->our_start_bal);
|
||||
assert(ok);
|
||||
|
||||
json_object_start(res, NULL);
|
||||
|
||||
json_add_string(res, "account", apy->acct_name);
|
||||
|
||||
json_add_amount_msat_only(res, "routed_out", apy->routed_out);
|
||||
json_add_amount_msat_only(res, "routed_in", apy->routed_in);
|
||||
json_add_amount_msat_only(res, "lease_fee_paid", apy->lease_out);
|
||||
json_add_amount_msat_only(res, "lease_fee_earned", apy->lease_in);
|
||||
json_add_amount_msat_only(res, "pushed_out", apy->push_out);
|
||||
json_add_amount_msat_only(res, "pushed_in", apy->push_in);
|
||||
|
||||
json_add_amount_msat_only(res, "our_start_balance", apy->our_start_bal);
|
||||
json_add_amount_msat_only(res, "channel_start_balance",
|
||||
apy->total_start_bal);
|
||||
|
||||
ok = amount_msat_add(&total_fees, apy->fees_in, apy->fees_out);
|
||||
assert(ok);
|
||||
json_add_amount_msat_only(res, "fees_out", apy->fees_out);
|
||||
json_add_amount_msat_only(res, "fees_in", apy->fees_in);
|
||||
|
||||
/* utilization (out): routed_out/total_balance */
|
||||
assert(!amount_msat_zero(apy->total_start_bal));
|
||||
utilization = amount_msat_ratio(apy->routed_out, apy->total_start_bal);
|
||||
json_add_string(res, "utilization_out",
|
||||
tal_fmt(apy, "%.4f%%", utilization * 100));
|
||||
|
||||
if (!amount_msat_zero(apy->our_start_bal)) {
|
||||
utilization = amount_msat_ratio(apy->routed_out,
|
||||
apy->our_start_bal);
|
||||
json_add_string(res, "utilization_out_initial",
|
||||
tal_fmt(apy, "%.4f%%", utilization * 100));
|
||||
}
|
||||
|
||||
/* utilization (in): routed_in/total_balance */
|
||||
utilization = amount_msat_ratio(apy->routed_in, apy->total_start_bal);
|
||||
json_add_string(res, "utilization_in",
|
||||
tal_fmt(apy, "%.4f%%", utilization * 100));
|
||||
|
||||
if (!amount_msat_zero(their_start_bal)) {
|
||||
utilization = amount_msat_ratio(apy->routed_in,
|
||||
their_start_bal);
|
||||
json_add_string(res, "utilization_in_initial",
|
||||
tal_fmt(apy, "%.4f%%", utilization * 100));
|
||||
}
|
||||
|
||||
blocks_elapsed = apy->end_blockheight - apy->start_blockheight;
|
||||
assert(blocks_elapsed > 0);
|
||||
|
||||
/* APY (outbound) */
|
||||
ok = calc_apy(apy->fees_out, apy->total_start_bal,
|
||||
blocks_elapsed, &apy_result);
|
||||
assert(ok);
|
||||
json_add_string(res, "apy_out", tal_fmt(apy, "%.4f%%", apy_result));
|
||||
|
||||
/* APY (outbound, initial) */
|
||||
if (!amount_msat_zero(apy->our_start_bal)) {
|
||||
ok = calc_apy(apy->fees_out, apy->our_start_bal,
|
||||
blocks_elapsed, &apy_result);
|
||||
assert(ok);
|
||||
json_add_string(res, "apy_out_initial",
|
||||
tal_fmt(apy, "%.4f%%", apy_result));
|
||||
}
|
||||
|
||||
/* APY (inbound) */
|
||||
ok = calc_apy(apy->fees_in, apy->total_start_bal,
|
||||
blocks_elapsed, &apy_result);
|
||||
assert(ok);
|
||||
json_add_string(res, "apy_in", tal_fmt(apy, "%.4f%%", apy_result));
|
||||
|
||||
if (!amount_msat_zero(their_start_bal)) {
|
||||
ok = calc_apy(apy->fees_in, their_start_bal,
|
||||
blocks_elapsed, &apy_result);
|
||||
assert(ok);
|
||||
json_add_string(res, "apy_in_initial",
|
||||
tal_fmt(apy, "%.4f%%", apy_result));
|
||||
}
|
||||
|
||||
/* APY (total) */
|
||||
ok = calc_apy(total_fees, apy->total_start_bal,
|
||||
blocks_elapsed, &apy_result);
|
||||
assert(ok);
|
||||
json_add_string(res, "apy_total", tal_fmt(apy, "%.4f%%", apy_result));
|
||||
|
||||
if (!amount_msat_zero(apy->our_start_bal)) {
|
||||
ok = calc_apy(total_fees, apy->total_start_bal,
|
||||
blocks_elapsed, &apy_result);
|
||||
assert(ok);
|
||||
json_add_string(res, "apy_total_initial",
|
||||
tal_fmt(apy, "%.4f%%", apy_result));
|
||||
}
|
||||
|
||||
/* If you earned fees for leasing funds, calculate APY
|
||||
* Note that this is a bit higher than it *should* be,
|
||||
* given that the onchainfees are partly covered here */
|
||||
if (!amount_msat_zero(apy->lease_in)) {
|
||||
struct amount_msat start_no_lease_in;
|
||||
|
||||
/* We added the lease in to the starting balance, so we
|
||||
* should subtract it out again before finding APY */
|
||||
ok = amount_msat_sub(&start_no_lease_in,
|
||||
apy->our_start_bal,
|
||||
apy->lease_in);
|
||||
assert(ok);
|
||||
ok = calc_apy(apy->lease_in, start_no_lease_in,
|
||||
/* we use the lease rate duration here! */
|
||||
LEASE_RATE_DURATION, &apy_result);
|
||||
assert(ok);
|
||||
json_add_string(res, "apy_lease",
|
||||
tal_fmt(apy, "%.4f%%", apy_result));
|
||||
}
|
||||
|
||||
json_object_end(res);
|
||||
}
|
||||
|
43
plugins/bkpr/channelsapy.h
Normal file
43
plugins/bkpr/channelsapy.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef LIGHTNING_PLUGINS_BKPR_CHANNELSAPY_H
|
||||
#define LIGHTNING_PLUGINS_BKPR_CHANNELSAPY_H
|
||||
#include "config.h"
|
||||
|
||||
#include <ccan/tal/tal.h>
|
||||
|
||||
struct channel_apy {
|
||||
char *acct_name;
|
||||
|
||||
struct amount_msat routed_in;
|
||||
struct amount_msat routed_out;
|
||||
struct amount_msat fees_in;
|
||||
struct amount_msat fees_out;
|
||||
|
||||
struct amount_msat push_in;
|
||||
struct amount_msat push_out;
|
||||
struct amount_msat lease_in;
|
||||
struct amount_msat lease_out;
|
||||
|
||||
struct amount_msat our_start_bal;
|
||||
struct amount_msat total_start_bal;
|
||||
|
||||
/* Blockheight the channel opened */
|
||||
u32 start_blockheight;
|
||||
|
||||
/* If channel_close, the channel_close event's blockheight,
|
||||
* otherwise the current blockheight */
|
||||
u32 end_blockheight;
|
||||
};
|
||||
|
||||
struct channel_apy *new_channel_apy(const tal_t *ctx);
|
||||
|
||||
WARN_UNUSED_RESULT bool channel_apy_sum(struct channel_apy *sum_apy,
|
||||
const struct channel_apy *entry);
|
||||
|
||||
struct channel_apy **compute_channel_apys(const tal_t *ctx, struct db *db,
|
||||
u64 start_time,
|
||||
u64 end_time,
|
||||
u32 current_blockheight);
|
||||
|
||||
void json_add_channel_apy(struct json_stream *res,
|
||||
const struct channel_apy *apy);
|
||||
#endif /* LIGHTNING_PLUGINS_BKPR_CHANNELSAPY_H */
|
Loading…
Reference in New Issue
Block a user