Skip to content

Instantly share code, notes, and snippets.

@fiatjaf
Last active August 16, 2020 02:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fiatjaf/e20c109af9b07a871aacac37b4102c91 to your computer and use it in GitHub Desktop.
Save fiatjaf/e20c109af9b07a871aacac37b4102c91 to your computer and use it in GitHub Desktop.
jq snippets for c-lightning
# use with:
# bash -c 'version=$(curl -s https://api.github.com/gists/e20c109af9b07a871aacac37b4102c91 | jq -rc .history[0].version); curl -s https://gist.githubusercontent.com/fiatjaf/e20c109af9b07a871aacac37b4102c91/raw/$version/channels-balance-state.jq > /tmp/clsnippet.jq; lightning-cli listfunds | jq -f /tmp/clsnippet.jq'
#
# lightning-cli listfunds | jq '
.channels
| sort_by(.channel_sat) | reverse
| map
(
{ peer: .peer_id
, scid: .short_channel_id
, capacity: .channel_total_sat
, our: (.channel_sat / .channel_total_sat | . * 100 | round | "\(.)%")
}
)
# '
# this prints a list of your channels with their total capacity and how much of it is in your side,
# like the following:
# [
# {
# "peer": "01bbd1812d3824f7cc4cdd38da5d66a29fcfec146fe95e26cd2e0d3f930d653abc",
# "scid": "638539x1474x0",
# "capacity": 2207006,
# "our": "90%"
# },
# {
# "peer": "07db7afbcf3d7ab282d974d2a73c6537cc2cb26b96cdc08f88d05bb492f53caabc",
# "scid": "631257x1142x1",
# "capacity": 2050000,
# "our": "87%"
# },
# {
# "peer": "03d5ebd3385840e6296bef346a69593f6ae80c649713d08c832feec81288d5fabc",
# "scid": "564521x691x0",
# "capacity": 1500000,
# "our": "81%"
# },
# {
# "peer": "03d480ac7ad220371f1b9c2560be6eb8da6335d6a0d8cb1bc27db1a3958fd8cabc",
# "scid": "618532x1076x0",
# "capacity": 1146181,
# "our": "100%"
# },
# {
# "peer": "03a8355790b89f4d96963019eb9413b9a2c884691837ac976bacfe25a5212892d7",
# "scid": "585448x2022x1",
# "capacity": 1100000,
# "our": "95%"
# },
# {
# "peer": "0321f80652fb840239df8dc99205792bba2e559805469915804c08420230e23c6a",
# "scid": null,
# "capacity": 349267,
# "our": "100%"
# }
# ]
# use with:
# bash -c 'version=$(curl -s https://api.github.com/gists/e20c109af9b07a871aacac37b4102c91 | jq -rc .history[0].version); curl -s https://gist.githubusercontent.com/fiatjaf/e20c109af9b07a871aacac37b4102c91/raw/$version/inspect-mpp.jq > /tmp/clsnippet.jq; lightning-cli listsendpays | jq -f /tmp/clsnippet.jq'
#
# lightning-cli listsendpays | jq '
.payments[-500:]
| reduce .[] as $p
( {}
; .[$p.payment_hash] =
( (.[$p.payment_hash] // {complete: [], failed: []})
| if $p.status == "complete" then .complete += [$p.msatoshi]
else .failed += [$p.msatoshi]
end
)
)
| to_entries | map(.value)
| map
( .complete as $complete
| .failed as $failed
| { success:
( if ($complete | length > 0)
then
{ msatoshi: ($complete | add )
, nshards: ($complete | length)
, avg: ($complete | add | . / ($complete | length) | round)
, minmax: [($complete | min), ($complete | max)]
}
else null
end
)
, failure:
( if ($failed | length > 0)
then
{ nshards: ($failed | length)
, avg: ($failed | add | . / ($failed | length) | round)
, minmax: [($failed | min), ($failed | max)]
}
else null
end
)
}
)
| map(select( (.success and (.success.nshards > 1)) or (.failure and (.failure.nshards > 1)) ))
# '
# this prints statistics about MPP splitting from your last payments.
# it shows how many shards there were for each payment, their average size, min and max sizes,
# and how many shards were failed before the payment finally succeeded.
# produces output like the following:
# [{
# "success": {
# "satoshi": 171704,
# "nshards": 18,
# "avg": 9539111,
# "minmax": [
# 7576167,
# 12409876
# ]
# },
# "failure": {
# "nshards": 70,
# "avg": 9632309,
# "minmax": [
# 7576167,
# 12409876
# ]
# }
# },
# {
# "success": {
# "satoshi": 10000,
# "nshards": 2,
# "avg": 5000000,
# "minmax": [
# 2175964,
# 7824036
# ]
# },
# "failure": null
# }]
# use with:
# bash -c 'version=$(curl -s https://api.github.com/gists/e20c109af9b07a871aacac37b4102c91 | jq -rc .history[0].version); curl -s https://gist.githubusercontent.com/fiatjaf/e20c109af9b07a871aacac37b4102c91/raw/$version/inspect-pending-htlcs.jq > /tmp/clsnippet.jq; lightning-cli listpeers | jq -f /tmp/clsnippet.jq'
#
# lightning-cli listpeers | jq '
.peers
| map(select(.channels | length > 0))
| map(.channels[-1] as $ch | {id, scid: $ch.short_channel_id, connected, htlcs: $ch.htlcs, status})
| map(select(.htlcs | length > 0))
# '
# this prints an array of all your channels that have pending HTLCs for any reason and the
# state of the connection between you and the corresponding peers.
# if no HTLCs are pending it will print an empty array.
# use with:
# bash -c 'version=$(curl -s https://api.github.com/gists/e20c109af9b07a871aacac37b4102c91 | jq -rc .history[0].version); curl -s https://gist.githubusercontent.com/fiatjaf/e20c109af9b07a871aacac37b4102c91/raw/$version/network-stats.jq > /tmp/clsnippet.jq; lightning-cli listchannels | jq -f /tmp/clsnippet.jq'
#
# lightning-cli listpeers | jq '
.channels | map(select(.public))
| reduce .[] as $c
( {channels: {}, nodes: {}}
; .channels[$c.short_channel_id] = $c
| .nodes[$c.source] = true
| .nodes[$c.destination] = true
)
| (.nodes | length) as $nodecount
| .channels | to_entries | map(.value)
| reduce .[] as $c
( {n: 0, cap: [], base: [], ppm: [], delay: []}
; .n += 1
| .cap += [$c.satoshis]
| .base += [$c.base_fee_millisatoshi]
| .ppm += [$c.fee_per_millionth]
| .delay += [$c.delay]
)
| .n as $n
| def median:
. | sort | .[(. | length | . / 2 | round | . - 1 )]
;
{ node_count: $nodecount
, channel_count: $n
, total_capacity: (.cap | add)
, avg_capacity: (.cap | add | . / $n | round)
, median_capacity: (.cap | median)
, min_max_capacity: [(.cap | min), (.cap | max)]
, avg_base_fee: (.base | add | . / $n | round)
, median_base_fee: (.base | median)
, minmax_base_fee: [(.base | min), (.base | max)]
, avg_ppm_fee: (.ppm | add | . / $n | round)
, median_ppm_fee: (.ppm | median)
, minmax_ppm_fee: [(.ppm | min), (.ppm | max)]
, avg_delay: (.delay | add | . / $n | round)
, median_delay: (.delay | median)
, minmax_delay: [(.delay | min), (.delay | max)]
}
# '
# this prints output like the following:
# {
# "node_count": 5805,
# "channel_count": 32700,
# "total_capacity": 100414729091,
# "avg_capacity": 3070786,
# "median_capacity": 741172,
# "min_max_capacity": [
# 1100,
# 250000000
# ],
# "avg_base_fee": 2392,
# "median_base_fee": 1000,
# "minmax_base_fee": [
# 0,
# 1000000
# ],
# "avg_ppm_fee": 106951,
# "median_ppm_fee": 1,
# "minmax_ppm_fee": [
# 0,
# 1000000000
# ],
# "avg_delay": 63,
# "median_delay": 40,
# "minmax_delay": [
# 0,
# 2016
# ]
# }
# use with:
# bash -c 'version=$(curl -s https://api.github.com/gists/e20c109af9b07a871aacac37b4102c91 | jq -rc .history[0].version); curl -s https://gist.githubusercontent.com/fiatjaf/e20c109af9b07a871aacac37b4102c91/raw/$version/routing-activity-summary.jq > /tmp/clsnippet.jq; lightning-cli listforwards | jq -r -f /tmp/clsnippet.jq'
#
# lightning-cli listforwards | jq -r '
{in_success: [], out_success: [], in_failure: [], out_failure: []} as $base
| def category(scid):
(if scid == .in_channel then "in" else "out" end)
+ "_"
+ (if .status == "settled" then "success" else "failure" end)
; def add: reduce .[] as $item (0; . + $item)
; def div: if .[0] == 0 then 0 else .[0] / .[1] end
; .forwards
| map(select(.status != "local_failed"))
| reduce .[] as $f
( {}
; reduce ["in_channel", "out_channel"][] as $inout
( .
; $f[$inout] as $scid
| .[$scid] = (.[$scid] // $base) # initiates a grouping for this channel
| ($f | category($scid)) as $cat
| .[$scid][$cat] +=
[ { fee: $f.fee
, msatoshi: $f.out_msatoshi
, time:
( if $f.resolved_time then ($f.resolved_time | round) else null end )
, diff:
(
if $f.resolved_time then
($f | .resolved_time - .received_time)
else null
end
)
}
]
)
)
| map_values
( (.out_success | length) as $out_n
| (.in_success | length) as $in_n
| (.out_failure | length) as $out_fails
| (.in_failure | length) as $in_fails
| (.out_success | map(.fee) | add) as $out_earned
| (.in_success | map(.fee) | add) as $in_earned
| (.out_success | map(.msatoshi) | add | . / 1000 | round) as $out_routed
| (.in_success | map(.msatoshi) | add | . / 1000 | round) as $in_routed
| { outgoing:
{ failed: $out_fails
, successful: $out_n
, total_satoshi: $out_routed
, avg_satoshi: ([$out_routed, $out_n] | div)
, minmax_satoshi: (.out_success | map(.msatoshi | . / 1000 | round) | [(. | min), (. | max)])
, total_fee: $out_earned
, avg_fee: ([$out_earned, $out_n] | div)
, minmax_fee: (.out_success | map(.fee) | [(. | min), (. | max)])
}
, incoming:
{ failed: $in_fails
, successful: $in_n
, total_satoshi: $in_routed
, avg_satoshi: ([$in_routed, $in_n] | div)
, minmax_satoshi: (.in_success | map(.msatoshi | . / 1000 | round) | [(. | min), (. | max)])
, total_fee: $in_earned
, avg_fee: ([$in_earned, $in_n] | div)
, minmax_fee: (.in_success | map(.fee) | [(. | min), (. | max)])
}
, total:
{ successes: ($out_n + $in_n)
, failures: ($out_fails + $in_fails)
, satoshi: $in_routed
, fee: $in_earned
}
, resolve_times:
( .in_failure + .out_failure + .in_success + .out_success
| map(.diff | select(.) | . * 1000)
| if length > 0 then
( { avg: ([add, length] | div | round)
, minmax: ([min, max] | map(round))
}
)
else null
end
)
, last_activity:
( .in_failure + .out_failure + .in_success + .out_success
| map(.time | select(.))
| if length > 0 then max else null end
)
}
)
| def bold: "\u001b[1m\(.)\u001b[0m"
; def underline: "\u001b[1;4m\(.)\u001b[0m"
; def red: "\u001b[1;31m\(.)\u001b[0m"
; def green: "\u001b[1;32m\(.)\u001b[0m"
; def yellow: "\u001b[1;33m\(.)\u001b[0m"
; def blue: "\u001b[1;34m\(.)\u001b[0m"
; def print_direction_summary(direction):
( .[direction]
| if .successful > 0 then "\n - Forwarded \(.failed + .successful | blue) \(direction) payments, \((.successful) / (.failed + .successful) | . * 100 | round | green)% of which were successful, a total of \(.total_satoshi | green)sat routed (\(.avg_satoshi | green)sat on average), earning a total of \(.total_fee / 1000 | round | yellow)sat (\(.avg_fee | yellow)msat on average). The transactions ranged from \(.minmax_satoshi[0] | underline) to \(.minmax_satoshi[1] | underline)sat and fees from \(.minmax_fee[0] | underline) to \(.minmax_fee[1] | underline)msat."
else
if .failed == 0 then "\n - No \(direction) forwards."
else "\n - All \(.failed | blue) \(direction) payments \("failed" | red)."
end
end
)
; map_values
( { order: [((.last_activity | select(.) | strftime("%Y%m")) // null), .total.satoshi]
, text:
( "\n - Forwarded a total of \(.total.satoshi | green)sat in \(.total.successes | blue) payments and earned \(.total.fee | yellow)msat."
+ (if .total.failures > 0 then " \(.total.failures | red) routing attempts failed." else "" end)
+ (if .last_activity then "\n - The last routing activity was in \(.last_activity | strftime("%d %B, %Y") | bold)." else "" end)
+ print_direction_summary("incoming")
+ print_direction_summary("outgoing")
+ (if .resolve_times then "\n - On average, forwards were resolved in \(.resolve_times.avg | blue)ms, ranging from \(.resolve_times.minmax[0] | underline) to \(.resolve_times.minmax[1] | underline)ms." else "" end)
)
}
)
| to_entries
| sort_by(.value.order)
| map((.key | bold) + ":" + .value.text)
| join("\n\n")
# '
# this will print something like the following (but with colors!):
# 631502x228x0:
# - Forwarded a total of 6979399sat in 31 payments and earned 11134956msat. 170 routing attempts failed.
# - The last routing activity was in 14 August, 2020.
# - Forwarded 86 incoming payments, 13% of which were successful, a total of 6979399sat routed (634490.8181818182sat on average), earning a total of 11135sat (1012268.7272727273msat on average). The transactions ranged from 141 to 4277237sat and fees from 1 to 11120816msat.
# - Forwarded 115 outgoing payments, 17% of which were successful, a total of 26483214sat routed (1324160.7sat on average), earning a total of 51sat (2540.85msat on average). The transactions ranged from 55565 to 3950611sat and fees from 1 to 3000msat.
# - On average, forwards were resolved in 5577ms, ranging from 278 to 120905ms.
#
# 637256x811x0:
# - Forwarded a total of 9433455sat in 5 payments and earned 11135msat. 38 routing attempts failed.
# - The last routing activity was in 13 August, 2020.
# - Forwarded 43 incoming payments, 12% of which were successful, a total of 9433455sat routed (1886691sat on average), earning a total of 11sat (2227msat on average). The transactions ranged from 805 to 3950611sat and fees from 2227 to 2227msat.
# - No outgoing forwards.
# - On average, forwards were resolved in 872ms, ranging from 327 to 3714ms.
#
# 632470x435x1:
# - Forwarded a total of 22182731sat in 25 payments and earned 19540541msat. 270 routing attempts failed.
# - The last routing activity was in 15 August, 2020.
# - Forwarded 98 incoming payments, 20% of which were successful, a total of 22182731sat routed (1109136.55sat on average), earning a total of 19541sat (977027.05msat on average). The transactions ranged from 255 to 2500000sat and fees from 2227 to 5103449msat.
# - Forwarded 197 outgoing payments, 3% of which were successful, a total of 570747sat routed (114149.4sat on average), earning a total of 9sat (1782msat on average). The transactions ranged from 30394 to 310335sat and fees from 2 to 2227msat.
# - On average, forwards were resolved in 4808ms, ranging from 278 to 128844ms.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment