Skip to content

Instantly share code, notes, and snippets.

@tyzbit
Last active July 24, 2021 23:57
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tyzbit/6cc7351c4f9f556bc0f446657c97fd26 to your computer and use it in GitHub Desktop.
Save tyzbit/6cc7351c4f9f556bc0f446657c97fd26 to your computer and use it in GitHub Desktop.
Useful commands/aliases for interacting with LND using lncli (https://github.com/lightningnetwork/lnd)

I am not responsible, directly or indirectly for the loss of funds using these commands. Use at your own risk.

Informational Commands

lrecv

Channels with received satoshis

alias lrecv="lncli listchannels | jq '[ .channels | .[] | select(.total_satoshis_received|tonumber>0) ]'"

loffchain

Channels with offchain transactions

alias loffchain="lncli listchannels | jq '[ .channels | .[] | select(.num_updates|tonumber>0) ]'"

lchaninfo

Lots of info plus distribution_pct, a representation of the balance of your channels

alias lchaninfo="lncli listchannels | jq '[ .channels | .[] | { \"remote_pubkey\": .remote_pubkey, \"capacity\": .capacity|tonumber, \"local_balance\": .local_balance|tonumber, \"remote_balance\": .remote_balance|tonumber, \"distribution_pct\": ( ( .local_balance|tonumber ) / ( (.remote_balance|tonumber ) + ( .local_balance|tonumber ) ) ), \"total_satoshis_sent\": .total_satoshis_sent|tonumber, \"total_satoshis_received\": .total_satoshis_received|tonumber } ]'"

ldist

Show just channel distributions

alias ldist="lncli listchannels | jq '[ .channels | .[] |  { \"remote_pubkey\": .remote_pubkey, \"capacity\": .capacity, \"distribution_pct\": ( ( .local_balance|tonumber ) / ( (.remote_balance|tonumber ) + ( .local_balance|tonumber ) ) ) } ]'"

lunsettled

Show channels with unsettled balances

alias lunsettled="lncli listchannels | jq '[ .channels | .[] | select(.unsettled_balance|tonumber>0) ]'"

ltotalcap

Total capacity of all channels

alias ltotalcap="lncli listchannels | jq '.channels | map(.capacity|tonumber) | add'"

lremotebal

Total remote balance of all channels

alias lremotebal="lncli listchannels | jq '.channels | map(.remote_balance|tonumber) | add'"

lunsettledbal

Total unsettled balance

alias lunsettledbal="lncli listchannels | jq '.channels | map(.unsettled_balance|tonumber) | add'"

lsentbal

Total satoshis sent

alias lsentbal="lncli listchannels | jq '.channels | map(.total_satoshis_sent|tonumber) | add'"

lreceivedbal

Total satoshis receieved

alias lreceivedbal="lncli listchannels | jq '.channels | map(.total_satoshis_received|tonumber) | add'"

loffchainupdates

Total number of offchain channel updates

alias loffchainupdates="lncli listchannels | jq '.channels | map(.num_updates|tonumber) | add'"

lactive

Number of active channels

alias lactive="lncli listchannels | jq '[ .channels | .[] | select(.active==true) ] | length'"

linactive

Number of inactive channels

alias linactive="lncli listchannels | jq '[ .channels | .[] | select(.active==false) ] | length'"

llimbo

Total balance in limbo

alias llimbo="lncli pendingchannels | jq '.total_limbo_balance|tonumber'"

lpendingo

Pending channels

alias lpendingo="lncli pendingchannels | jq '.pending_open_channels|length'"

lpendingc

Pending channels

alias lpendingc="lncli pendingchannels | jq '.pending_close_channels|length'"

lpendingf

Pending channels

alias lpendingf="lncli pendingchannels | jq '.pending_force_closing_channels|length'"

ltopchannels

Top funded channels

alias ltopchannels="lncli describegraph | jq '[ .edges | sort_by(.capacity|tonumber) | reverse | .[] | { \"node1_pub\": .node1_pub, \"node2_pub\": .node2_pub, \"Capacity\": .capacity|tonumber,  } ]'"

ltopchannels

Top funded channels

alias ltopchannels="lncli describegraph | jq '[ .edges | sort_by(.capacity|tonumber) | reverse | .[] | { \"node1_pub\": .node1_pub, \"node2_pub\": .node2_pub, \"Capacity\": .capacity|tonumber,  } ]'"

lunusedchannels

channels that haven't been used for sending or receiving payments

alias lunusedchannels='lncli listchannels | jq '\''[ .channels[] | select(.total_satoshis_sent=="0" and .total_satoshis_received=="0") ]| {"unused channels": map({"channel_point": .channel_point, "local_balance": .local_balance|tonumber, "num_updates": .num_updates|tonumber, "active": .active, "private": .private}) | sort_by(.local_balance) | reverse }'\'''

lnodeinfo

get the node info for all nodes that have channels with us

alias lnodeinfo='lncli listchannels | jq -r '''.channels[].remote_pubkey' | while read p; do lncli getnodeinfo "$p"; done'''

lremotecap

get the total connected capacity of a specific node pubkey

lremotecap() { if [ -z $1 ]; then "specify remote node pubkey"; else lncli describegraph | jq --arg node $1 '[ .edges[] | select(.node1_pub==$node or .node2_pub==$node) ] | map(.capacity|tonumber)  | add | { "capacity" : . }'; fi }

lchannelcaps

See channel caps of all known nodes

NOT WORKING AT THE MOMENT

alias lchannelcaps="lncli describegraph | jq '.nodes[].total_channel_capacities=0 | foreach .nodes[] as $node ( . ; foreach .edges[] as $edge ( . ; if $edge.node1_pub==$node.pub_key then ($node|.total_channel_capacities=.total_channel_capacity+($edge.capacity|tonumber)) else empty end ; .)  ; . )'"

lbestroute

see the best route for a particular pubkey and amount

lbestroute() { if [ -z $1 ]; then echo "need pubkey+amt"; else lncli queryroutes $1 $2 | jq 'routes[0]'; fi; }

ldistance

see the shortest distance to a particular node for a particular amount

ldistance() { if [ -z $1 ]; then echo "need pubkey+amt"; else lncli queryroutes $1 $2 | jq '[ .routes[].hops | length ] | min'; fi; }

lfurthest

see the furthest node from you (takes a long time to run)

lfurthest() { if [ -z $1 ]; then echo "need an amount"; else lncli describegraph | jq '.nodes[].pub_key' | while read p; do echo -en "$p: "; ldistance ${p//\"} $1; done; fi; }

lforcegraph

generate force-graph for visualization (https://bl.ocks.org/tyzbit/e41587d241b0ab0f38273dc4b8dd571e)

alias lforcegraph='lncli describegraph | jq -c '\''{ "nodes": .nodes | map({ "id": .pub_key, "alias": .alias|match("[^\u0000]+")| .string, "group": 1, "color": .color, "addresses": .addresses }), "links": .edges | map({"source": .node1_pub, "target": .node2_pub, "capacity": .capacity|tonumber }) }'\'

lfwdinghistory

forwarding history with human readable timestamps

alias lfwdinghistory='lncli fwdinghistory --start_time=1 --end_time=$(date +%s) | jq '\''.forwarding_events[].timestamp |= (. | tonumber | strftime("%F %T")) | .event_count = (.forwarding_events | length) | .forwarding_events[].amt_in |= (. | tonumber) | .forwarding_events[].amt_out |= (. | tonumber)'\'

DANGEROUS COMMANDS

These are commands which PERFORM OPERATIONS ON YOUR NODE. Use with caution. I am not responsible for any loss of funds resulting from the use of these or any commands.

lcloseall

attempt to cooperatively close all channels with a specific node

lcloseall() { if [ -z $1 ]; then echo "specify remote node pubkey"; else lncli listchannels | jq -r --arg pubkey $1 '.channels[] | select(.remote_pubkey==$pubkey) | "\(.channel_point | .[0:64])"' | while read c; do lncli closechannel $c; done fi }

lforcecloseall

attempt to force close all channels with a specific node

lforcecloseall() { if [ -z $1 ]; then echo "specify remote node pubkey"; else lncli listchannels | jq -r --arg pubkey $1 '.channels[] | select(.remote_pubkey==$pubkey) | .channel_point' | while read c; do lncli closechannel --force ${c%:*} ${c/*:/}; done fi }
@bretton
Copy link

bretton commented Feb 7, 2018

fails:

alias ltotalcap="lncli listchannels | jq '.channels | map(.capacity|tonumber) | add"

works:

alias ltotalcap="lncli listchannels | jq '.channels | map(.capacity|tonumber) | add'"

seem to be a few like this :)

@bretton
Copy link

bretton commented Feb 7, 2018

lchannelcaps isn't working at all

jq: error: syntax error, unexpected '(', expecting '$' or '[' or '{' (Unix shell quoting issues?) at <top-level>, line 1:

@tyzbit
Copy link
Author

tyzbit commented Mar 30, 2018

fixed what I could, lchannelcaps is a really complex filter so it'll take some time to debug, also added lnodeinfo

@BubbleCoinLOL
Copy link

the pending channels stuff isoff? I think that was the old syntax?
alias lpendingf="lncli listchannels | jq '.pending_force_closing_channels|length'"
this works instead
alias lpendingf="lncli pendingchannels | jq '.pending_force_closing_channels|length'"
working versions of the others

alias lpendingc="lncli pendingchannels | jq '.pending_closing_channels|length'"
alias lpendingo="lncli pendingchannels | jq '.pending_open_channels|length'"
alias llimbo="lncli pendingchannels | jq '.total_limbo_balance|tonumber'"

@tyzbit
Copy link
Author

tyzbit commented Apr 5, 2018

Thanks @BubbleCoinLOL, updated.

@tyzbit
Copy link
Author

tyzbit commented Apr 6, 2018

added lremotecap

@tyzbit
Copy link
Author

tyzbit commented Apr 8, 2018

added commands that will close channels for you, don't blame me if you lose money

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment