LIGHTNING-LISTPEERCHANNELS(7)
π LIGHTNING-LISTPEERCHANNELS(7) β the manpage, but make it cute β¨
okay bestie, this is section 7 of the lightning manual, and it's literally the page about listpeerchannels, so buckle up π
πΈ NAME πΈ
listpeerchannels β the command that hands you all the data on the channels of your connected lightning nodes π«Ά
β¨ SYNOPSIS β¨
listpeerchannels [id] [short_channel_id] [channel_id]
π DESCRIPTION π
So first of all, this command was added in v23.02 β vintage, iconic, we love her π
The listpeerchannels RPC command returns a list of this node's channels. That's the whole ~concept~ π«
By default you get data for all the known channels β including the ones to peers who are currently connected, and the ones to peers who are disconnected but still have open channels. like yeah they're not answering your texts rn but the channel is literally still there, no cap π
At most one of id, short_channel_id or channel_id may be provided as a filter. If more than one is provided, the command fails with an error. that's your vibe check: pick one filter, bestie, don't be greedy π
id(pubkey, optional) β if supplied, limits the channels to just the peer with the given ID, if it exists. Cannot be used withshort_channel_idorchannel_id.short_channel_id(short_channel_id, optional) β if supplied, limits the channels to just thisshort_channel_id(or local alias), if it exists. Cannot be used withidorchannel_id. (added v25.05 β¨)channel_id(hash, optional) β if supplied, limits the channels to just thischannel_id, if it exists. Cannot be used withidorshort_channel_id. (added v26.04 π)
π RETURN VALUE π
On success, an object containing channels is returned. It is an array of objects, where each object contains β and yeah, it's a long list, but we're reading all of it because I refuse to skip parts π
peer_id(pubkey) β node public key. that's their identity, respect it π«‘peer_connected(boolean) β a boolean flag that is set totrueif the peer is online. like a little green dot but in JSON form π’state(string) (one of"OPENINGD","CHANNELD_AWAITING_LOCKIN","CHANNELD_NORMAL","CHANNELD_SHUTTING_DOWN","CLOSINGD_SIGEXCHANGE","CLOSINGD_COMPLETE","AWAITING_UNILATERAL","FUNDING_SPEND_SEEN","ONCHAIN","DUALOPEND_OPEN_INIT","DUALOPEND_AWAITING_LOCKIN","CHANNELD_AWAITING_SPLICE","DUALOPEND_OPEN_COMMITTED","DUALOPEND_OPEN_COMMIT_READY") β the channel state. and in particular,CHANNELD_NORMALmeans the channel can be used normally β that's the main character state, the one you want β¨opener(string) (one of"local","remote") β who initiated the channel. who texted first, essentially πfeatures(array of strings) β the feature list, and each entry is:- (string, optional) (one of
"option_static_remotekey","option_anchor_outputs","option_anchors","option_scid_alias","option_zeroconf") β BOLT #9 features which apply to this channel.
- (string, optional) (one of
reestablished(boolean, optional) β a boolean flag that is set totrueif we have successfully exchanged reestablish messages with this connection. (added v24.02) the reunion arc π₯Ήscratch_txid(txid, optional) β the txid we would use if we went onchain now.channel_type(object, optional) βChannel_typeas negotiated with peer. (added v23.05) ββ okay this one's got layers, stay with me π§bits(array of u32s) β each bit set in thischannel_type.:- (u32, optional) β bit number.
names(array of strings) β feature name for each bit set in thischannel_type. Note thatanchors_zero_fee_htlc_txis a deprecated synonym foranchors. (yes, deprecated β clock that π°οΈ):- (string, optional) (one of
"static_remotekey/even","anchor_outputs/even","anchors/even","anchors_zero_fee_htlc_tx/even","scid_alias/even","zeroconf/even") β name of feature bit.
- (string, optional) (one of
updates(object, optional) β latest gossip updates sent/received. (added v24.02) gossip!! the tea!! π΅local(object) β our gossip for channel. (added v24.02):htlc_minimum_msat(msat) β minimum msat amount we allow. (added v24.02)htlc_maximum_msat(msat) β maximum msat amount we allow. (added v24.02)cltv_expiry_delta(u32) β blocks delay required between incoming and outgoing HTLCs. (added v24.02)fee_base_msat(msat) β amount we charge to use the channel. (added v24.02) πΈfee_proportional_millionths(u32) β amount we charge to use the channel in parts-per-million. (added v24.02)
remote(object, optional) β peer's gossip for channel. (added v24.02):htlc_minimum_msat(msat) β minimum msat amount they allow. (added v24.02)htlc_maximum_msat(msat) β maximum msat amount they allow. (added v24.02)cltv_expiry_delta(u32) β blocks delay required between incoming and outgoing HTLCs. (added v24.02)fee_base_msat(msat) β amount they charge to use the channel. (added v24.02)fee_proportional_millionths(u32) β amount they charge to use the channel in parts-per-million. (added v24.02)
ignore_fee_limits(boolean, optional) β set if we allow this peer to set fees to anything they want. (added v23.08) chaos mode activated πlost_state(boolean, optional) β set if we are fallen behind i.e. lost some channel state. (added v24.02) not the flop era πfeerate(object, optional) β feerates for the current tx.:perkw(u32) β feerate per 1000 weight (i.e kSipa).perkb(u32) β feerate per 1000 virtual bytes.
owner(string, optional) β the current subdaemon controlling this connection.short_channel_id(short_channel_id, optional) β theshort_channel_id(once locked in).direction(u32, optional) β the direction of the channel (i.e.0if we are the lesser node id,1if we are the greater).channel_id(hash, optional) β the fullchannel_id(funding txid Xored with output number).funding_txid(txid, optional) β ID of the funding transaction.funding_outnum(u32, optional) β the 0-based output number of the funding transaction which opens the channel.initial_feerate(string, optional) β for inflight opens, the first feerate used to initiate the channel open.last_feerate(string, optional) β for inflight opens, the most recent feerate used on the channel open.next_feerate(string, optional) β for inflight opens, the next feerate we'll use for the channel open. Omitted iflast_feerateadmits no valid next feerate.next_fee_step(u32, optional) β inflight opens only, bestie: this is the next feerate step we're gonna use for the channel open. πΈinflight(array of objects, optional) β the current candidate funding transactions, like the shortlist of txs that might actually open this channel. Each one's got:funding_txid(txid) β the ID of the funding transaction.funding_outnum(u32) β the 0-based output number of the funding transaction that opens the channel.feerate(string) β the feerate for this funding transaction, per-1000-weight, withkpwtacked on the end.total_funding_msat(msat) β total amount in the channel.splice_amount(integer) β how many sats we're splicing in or out. (added v23.08)our_funding_msat(msat) β how much of the channel is ours.scratch_txid(txid, optional) β the commitment transaction txid we'd be using if we went onchain, like, right now.
close_to(hex, optional) β the ScriptPubkey we have to close to if we mutual close.private(boolean, optional) β ifTrue, we will not announce this channel. π€«closer(string, optional) (one of"local","remote") β who initiated the channel close. Only present if closing, obvi.funding(object, optional) β the whole "who paid for what" receipts:local_funds_msat(msat) β amount of the channel we funded.remote_funds_msat(msat) β amount of the channel they funded.pushed_msat(msat, optional) β amount pushed from opener to peer.fee_paid_msat(msat, optional) β amount we paid the peer at open.fee_rcvd_msat(msat, optional) β amount we were paid by the peer at open.psbt(string, optional) β the PSBT (may be non-final or unsigned) we should use to open the channel, if any. This is initially fromfundchannel_complete, but will be updated with ifsendpsbtis called with an updated PSBT. (added v25.12)withheld(boolean, optional) βTrueiffundchannel_completetold us it will not broadcast the funding transaction (so we know not to bother with any other onchain transactions in the case of this channel). This is set tofalseifsendpsbtis send on the above PSBT. (added v25.12)
to_us_msat(msat, optional) β how much of the channel is owed to us. π«Άmin_to_us_msat(msat, optional) β the least amount ever owed to us. If the peer were to successfully steal from us, this is the amount we would still retain. Not the vibe, but good to know.max_to_us_msat(msat, optional) β the most amount ever owed to us. If we were to successfully steal from the peer, this is the amount we could potentially get. πtotal_msat(msat, optional) β total amount in the channel.fee_base_msat(msat, optional) β amount we charge to use the channel.fee_proportional_millionths(u32, optional) β amount we charge to use the channel, in parts-per-million.dust_limit_msat(msat, optional) β the minimum amount for an output on the channel transactions. Anything under this is literally dust, hence the name, slay.their_max_htlc_value_in_flight_msat(msat, optional) β the cap on the total value of outstanding HTLCs offered to the remote node. This limits the total amount in flight we can send through this channel. (added v25.02)our_max_htlc_value_in_flight_msat(msat, optional) β the cap on the total value of outstanding HTLCs we accept from the remote node. This limits the total amount in flight we can receive through this channel. (added v25.02)their_reserve_msat(msat, optional) β the minimum we insist they keep in the channel. If they have less than this in the channel, they cannot send to us on that channel. The default is 1% of the total channel capacity. πour_reserve_msat(msat, optional) β the minimum they insist we keep in the channel. If you have less than this in the channel, you cannot send out via this channel.spendable_msat(msat, optional) β an estimate of the total we could send through the channel. Heads up though: it can be wrong, because adding HTLCs requires an increase in fees paid to onchain miners, and onchain fees change dynamically according to onchain activity. So like, vibe estimate, not gospel. πreceivable_msat(msat, optional) β an estimate of the total the peer could send through the channel.minimum_htlc_in_msat(msat, optional) β the minimum amount HTLC we accept.minimum_htlc_out_msat(msat, optional) β the minimum amount HTLC we will send.maximum_htlc_out_msat(msat, optional) β the maximum amount HTLC we will send.their_to_self_delay(u32, optional) β the number of blocks before they can take their funds if they unilateral close.our_to_self_delay(u32, optional) β the number of blocks before we can take our funds if we unilateral close.max_accepted_htlcs(u32, optional) β the maximum number of incoming HTLCs we will accept at once.alias(object, optional) β the cute lil nicknames for this channel:local(short_channel_id, optional) β an alias assigned by this node to this channel, used for outgoing payments.remote(short_channel_id, optional) β an alias assigned by the remote node to this channel, usable in routehints and invoices.
state_changes(array of objects, optional) β the prior state changes, like a whole character arc for the channel. Each entry:timestamp(string) β UTC timestamp of the formYYYY-mm-ddTHH:MM:SS.%03dZ.old_state(string) (one of"OPENINGD","CHANNELD_AWAITING_LOCKIN","CHANNELD_NORMAL","CHANNELD_SHUTTING_DOWN","CLOSINGD_SIGEXCHANGE","CLOSINGD_COMPLETE","AWAITING_UNILATERAL","FUNDING_SPEND_SEEN","ONCHAIN","DUALOPEND_OPEN_INIT","DUALOPEND_AWAITING_LOCKIN","DUALOPEND_OPEN_COMMITTED","DUALOPEND_OPEN_COMMIT_READY","CHANNELD_AWAITING_SPLICE") β previous state.new_state(string) (one of"OPENINGD","CHANNELD_AWAITING_LOCKIN","CHANNELD_NORMAL","CHANNELD_SHUTTING_DOWN","CLOSINGD_SIGEXCHANGE","CLOSINGD_COMPLETE","AWAITING_UNILATERAL","FUNDING_SPEND_SEEN","ONCHAIN","DUALOPEND_OPEN_INIT","DUALOPEND_AWAITING_LOCKIN","DUALOPEND_OPEN_COMMITTED","DUALOPEND_OPEN_COMMIT_READY","CHANNELD_AWAITING_SPLICE") β new state.cause(string) (one of"unknown","local","user","remote","protocol","onchain") β what caused the change.message(string) β human-readable explanation. finally, something in plain English β¨
status(array of strings, optional) β the billboard:- (string, optional) β billboard log of significant changes.
in_payments_offered(u64, optional) β number of incoming payment attempts.in_offered_msat(msat, optional) β total amount of incoming payment attempts.in_payments_fulfilled(u64, optional) β number of successful incoming payment attempts.in_fulfilled_msat(msat, optional) β total amount of successful incoming payment attempts.out_payments_offered(u64, optional) β number of outgoing payment attempts.out_offered_msat(msat, optional) β total amount of outgoing payment attempts.out_payments_fulfilled(u64, optional) β number of successful outgoing payment attempts.out_fulfilled_msat(msat, optional) β total amount of successful outgoing payment attempts.last_stable_connection(u64, optional) β the last time we reestablished the open channel and stayed connected for 1 minute. (added v24.02) honestly a whole achievement πhtlcs(array of objects, optional) β the HTLCs currently in this channel. Each one:direction(string) (one of"in","out") β whether it came from the peer, or is going to the peer. (added v23.02)id(u64) β unique ID for this htlc on this channel in this direction.amount_msat(msat) β amount sent/received for this HTLC.expiry(u32) β the block this HTLC expires at (after which anindirection HTLC will be returned to the peer, anoutreturned to us). If this expiry is too close,lightningd(8)will automatically unilaterally close the channel in order to enforce the timeout onchain. so, y'know, no pressure or anything πpayment_hash(hash) β the hash of thepayment_preimagewhich will prove payment.local_trimmed(boolean, optional) (alwaystrue) β if this is too small to enforce onchain; it doesn't appear in the commitment transaction and will not be enforced in a unilateral close. Generallytrueif the HTLC (after subtracting onchain fees) is below thedust_limit_msatfor the channel.status(string, optional) β set if this HTLC is currently waiting on a hook (and shows what plugin). πͺ
okay so the htlcs objects get a lil conditional moment, depending on which way the HTLC is going:
- If
directionis"out":state(string) (one of"SENT_ADD_HTLC","SENT_ADD_COMMIT","RCVD_ADD_REVOCATION","RCVD_ADD_ACK_COMMIT","SENT_ADD_ACK_REVOCATION","RCVD_REMOVE_HTLC","RCVD_REMOVE_COMMIT","SENT_REMOVE_REVOCATION","SENT_REMOVE_ACK_COMMIT","RCVD_REMOVE_ACK_REVOCATION") β status of the HTLC.
- If
directionis"in":state(string) (one of"RCVD_ADD_HTLC","RCVD_ADD_COMMIT","SENT_ADD_REVOCATION","SENT_ADD_ACK_COMMIT","RCVD_ADD_ACK_REVOCATION","SENT_REMOVE_HTLC","SENT_REMOVE_COMMIT","RCVD_REMOVE_REVOCATION","RCVD_REMOVE_ACK_COMMIT","SENT_REMOVE_ACK_REVOCATION") β status of the HTLC.
And there's more conditional goodness, bestie β these show up only when their trigger field is around:
- If
peer_connectedistrue:reestablished(boolean, optional) βTrueif we have successfully exchanged reestablish messages on this connection.
- If
close_tois present:close_to_addr(string, optional) β the bitcoin address we will close to (present ifclose_to_addris a standardized address).
- If
scratch_txidis present:last_tx_fee_msat(msat) β fee attached to this the current tx.
- If
short_channel_idis present:direction(u32) β0if we're the lessernode_id,1if we're the greater (as used in BOLT #7channel_update). (added v23.02)
- If
inflightis present:initial_feerate(string) β the feerate for the initial funding transaction, per-1000-weight, withkpwappended.last_feerate(string) β the feerate for the latest funding transaction, per-1000-weight, withkpwappended.next_feerate(string, optional) β the minimum feerate for the next funding transaction, per-1000-weight, withkpwappended. Omitted iflast_feerateadmits no valid next feerate.
The state field values (and old_state / new_state) are worth describing further:
OPENINGDβ the channel funding protocol with the peer is literally happening right now and both sides are hashing out the parameters πDUALOPEND_OPEN_INITβ same energy asOPENINGD, but for v2 connections that are doing collaborative opens β¨DUALOPEND_OPEN_COMMIT_READYβ again, likeOPENINGD, but for v2 connections using collaborative opens. Bestie, you are ready to send your commitment signed to your peer πDUALOPEND_OPEN_COMMITTEDβ likeOPENINGD, but for v2 connections using collaborative opens. You've gotten an initial signed commitment from your peer, slay π«ΆCHANNELD_AWAITING_LOCKIN/DUALOPEND_AWAITING_LOCKINβ the peer and you have agreed on channel parameters and are just sitting there waiting for the channel funding transaction to be confirmed deeply (that's the original protocol and the collaborative open protocol respectively, iykyk). Both you and the peer have to acknowledge the channel funding transaction as confirmed deeply before anybody moves to the next state. Bonus: you can bump the onchain fee for channels inDUALOPEND_AWAITING_LOCKINusinglightning-openchannel_bump(7)π₯CHANNELD_NORMALβ the channel can be used for normal payments. main character energy, honestly πCHANNELD_SHUTTING_DOWNβ a mutual close was requested (by you or by the peer) and both of you are waiting for the in-flight HTLCs to either fail or succeed. The channel can no longer be used for normal payments and forwarding. The mutual close only proceeds once every HTLC in the channel has been fulfilled or failed πCLOSINGD_SIGEXCHANGEβ you and the peer are negotiating the mutual close onchain fee. haggling arc πCLOSINGD_COMPLETEβ you and the peer have agreed on the mutual close onchain fee and are now awaiting the mutual close getting confirmed deeply βAWAITING_UNILATERALβ you initiated a unilateral close, and now you're just waiting for the peer-selected unilateral close timeout to complete πFUNDING_SPEND_SEENβ you saw the funding transaction getting spent (usually the peer initiated a unilateral close) and you will now determine what exactly happened, i.e. whether it was a theft attempt πONCHAINβ you saw the funding transaction getting spent and now you know what happened, i.e. whether it was a proper unilateral close by the peer or a theft attempt π¦
π ERRORS π
When something goes wrong, the returned object comes with code and message properties, and code is gonna be one of these bad boys:
-32602β if the given parameters are wrong. classic. not the vibe π
β¨ AUTHOR β¨
Michael Hawkins michael.hawkins@protonmail.com.
π SEE ALSO π
lightning-connect(7), lightning-fundchannel_start(7)
πΈ RESOURCES πΈ
Main web site: https://github.com/ElementsProject/lightning
Lightning RFC site (BOLT #9): https://github.com/lightningnetwork/lightning-rfc/blob/master/09-feaβ tures.md
π¦ EXAMPLES π¦
Example 1:
Request:
$ lightning-cli listpeerchannels -k "id"="nodeid020202020202020202020202020202020202020202020202020202020202"
{
"id": "example:listpeerchannels#1",
"method": "listpeerchannels",
"params": {
"id": "nodeid020202020202020202020202020202020202020202020202020202020202"
}
}
Response:
{
"channels": [
{
"peer_id": "nodeid020202020202020202020202020202020202020202020202020202020202",
"peer_connected": true,
"reestablished": true,
"channel_type": {
"bits": [
12,
22
],
"names": [
"static_remotekey/even",
"anchors/even"
]
},
"updates": {
"local": {
"htlc_minimum_msat": 0,
"htlc_maximum_msat": 990000000,
"cltv_expiry_delta": 6,
"fee_base_msat": 1,
"fee_proportional_millionths": 10
},
"remote": {
"htlc_minimum_msat": 0,
"htlc_maximum_msat": 990000000,
"cltv_expiry_delta": 6,
"fee_base_msat": 1,
"fee_proportional_millionths": 10
}
},
"last_stable_connection": 1738510000,
"state": "CHANNELD_NORMAL",
"scratch_txid": "scratchid1010101010101010101010101010101010101010101010101010101",
"last_tx_fee_msat": 4867000,
"lost_state": false,
"feerate": {
"perkw": 3755,
"perkb": 15020
},
"owner": "channeld",
"short_channel_id": "109x1x1",
"direction": 1,
"channel_id": "channelid0120000120000120000120000120000120000120000120000120000",
"funding_txid": "channeltxid120000120000120000120000120000120000120000120000120000",
"funding_outnum": 1,
"close_to_addr": "bcrt1p8c0ku4mpxq3443rss8e6rjwamztvv8yxvmxtetal5d0n6v39rlwqvfqy6n",
"close_to": "51203e1f6e576130235ac47081f3a1c9ddd896c61c8666ccbcafbfa35f3d32251fdc",
"private": false,
"opener": "local",
"alias": {
"local": "30000001x60000001x60001",
"remote": "10000001x20000001x30001"
},
"features": [
"option_static_remotekey",
"option_anchors"
],
"funding": {
"local_funds_msat": 1000000000,
"remote_funds_msat": 0,
"pushed_msat": 0
},
"to_us_msat": 390492790,
"min_to_us_msat": 390492790,
"max_to_us_msat": 1000000000,
"total_msat": 1000000000,
"fee_base_msat": 1,
"fee_proportional_millionths": 10,
"dust_limit_msat": 546000,
"their_max_htlc_value_in_flight_msat": 18446744073709552000,
"our_max_htlc_value_in_flight_msat": 18446744073709552000,
"their_reserve_msat": 10000000,
"our_reserve_msat": 10000000,
"spendable_msat": 363951708,
"receivable_msat": 599507210,
"minimum_htlc_in_msat": 0,
"minimum_htlc_out_msat": 0,
"maximum_htlc_out_msat": 990000000,
"their_to_self_delay": 5,
"our_to_self_delay": 5,
"max_accepted_htlcs": 483,
"state_changes": [
{
"timestamp": "2024-10-10T00:01:00.000Z",
"old_state": "DUALOPEND_OPEN_COMMITTED",
"new_state": "DUALOPEND_AWAITING_LOCKIN",
"cause": "user",
"message": "Sigs exchanged, waiting for lock-in"
},
{
"timestamp": "2024-10-10T00:02:00.000Z",
"old_state": "DUALOPEND_AWAITING_LOCKIN",
"new_state": "CHANNELD_NORMAL",
"cause": "user",
"message": "Lockin complete"
}
],
"status": [
"CHANNELD_NORMAL:Channel ready for use."
],
"in_payments_offered": 1,
"in_offered_msat": 1000000,
"in_payments_fulfilled": 1,
"in_fulfilled_msat": 1000000,
"out_payments_offered": 22,
"out_offered_msat": 665528797,
"out_payments_fulfilled": 16,
"out_fulfilled_msat": 610507210,
"htlcs": [
{
"direction": "out",
"id": 17,
"amount_msat": 4000082,
"expiry": 181,
"payment_hash": "paymenthashdelpay30303030303030303030303030303030303030303030303",
"state": "SENT_ADD_ACK_REVOCATION"
}
]
}
]
}
Example 2:
Request:
$ lightning-cli listpeerchannels
{
"id": "example:listpeerchannels#2",
"method": "listpeerchannels",
"params": {}
}
Response:
β¦bestie, buckle up, because here's the rest of that output and it is a LOT π
It's an object with a "channels" array, and channel number one is absolutely living its best main character life while channel number two is fully onchain and kind of in its flop era (affectionate). Every single field, exactly as it prints:
{
"channels": [
{
"peer_id": "nodeid020202020202020202020202020202020202020202020202020202020202",
"peer_connected": true,
"reestablished": true,
"channel_type": {
"bits": [
12,
22
],
"names": [
"static_remotekey/even",
"anchors/even"
]
},
"updates": {
"local": {
"htlc_minimum_msat": 0,
"htlc_maximum_msat": 990000000,
"cltv_expiry_delta": 6,
"fee_base_msat": 1,
"fee_proportional_millionths": 10
},
"remote": {
"htlc_minimum_msat": 0,
"htlc_maximum_msat": 990000000,
"cltv_expiry_delta": 6,
"fee_base_msat": 1,
"fee_proportional_millionths": 10
}
},
"last_stable_connection": 1738520000,
"state": "CHANNELD_NORMAL",
"scratch_txid": "scratchid2020202020202020202020202020202020202020202020202020202",
"last_tx_fee_msat": 4867000,
"lost_state": false,
"feerate": {
"perkw": 3755,
"perkb": 15020
},
"owner": "channeld",
"short_channel_id": "109x1x1",
"direction": 1,
"channel_id": "channelid0120000120000120000120000120000120000120000120000120000",
"funding_txid": "channeltxid120000120000120000120000120000120000120000120000120000",
"funding_outnum": 1,
"close_to_addr": "bcrt1pcl00020002000200020002000200020002000200020002000200020002",
"close_to": "db2dec31020202020202020202020202020202020202020202020202020202020202",
"private": false,
"opener": "local",
"alias": {
"local": "30000002x60000002x60002",
"remote": "10000002x20000002x30002"
},
"features": [
"option_static_remotekey",
"option_anchors"
],
"funding": {
"local_funds_msat": 1000000000,
"remote_funds_msat": 0,
"pushed_msat": 0
},
"to_us_msat": 390492790,
"min_to_us_msat": 390492790,
"max_to_us_msat": 1000000000,
"total_msat": 1000000000,
"fee_base_msat": 1,
"fee_proportional_millionths": 10,
"dust_limit_msat": 546000,
"their_max_htlc_value_in_flight_msat": 18446744073709552000,
"our_max_htlc_value_in_flight_msat": 18446744073709552000,
"their_reserve_msat": 10000000,
"our_reserve_msat": 10000000,
"spendable_msat": 363951708,
"receivable_msat": 599507210,
"minimum_htlc_in_msat": 0,
"minimum_htlc_out_msat": 0,
"maximum_htlc_out_msat": 990000000,
"their_to_self_delay": 5,
"our_to_self_delay": 5,
"max_accepted_htlcs": 483,
"state_changes": [
{
"timestamp": "2024-10-10T00:01:00.000Z",
"old_state": "DUALOPEND_OPEN_COMMITTED",
"new_state": "DUALOPEND_AWAITING_LOCKIN",
"cause": "user",
"message": "Sigs exchanged, waiting for lock-in"
},
{
"timestamp": "2024-10-10T00:02:00.000Z",
"old_state": "DUALOPEND_AWAITING_LOCKIN",
"new_state": "CHANNELD_NORMAL",
"cause": "user",
"message": "Lockin complete"
}
],
"status": [
"CHANNELD_NORMAL:Channel ready for use."
],
"in_payments_offered": 1,
"in_offered_msat": 1000000,
"in_payments_fulfilled": 1,
"in_fulfilled_msat": 1000000,
"out_payments_offered": 22,
"out_offered_msat": 665528797,
"out_payments_fulfilled": 16,
"out_fulfilled_msat": 610507210,
"htlcs": [
{
"direction": "out",
"id": 17,
"amount_msat": 4000082,
"expiry": 181,
"payment_hash": "paymenthashdelpay30303030303030303030303030303030303030303030303",
"state": "SENT_ADD_ACK_REVOCATION"
}
]
},
{
"peer_id": "nodeid030303030303030303030303030303030303030303030303030303030303",
"peer_connected": false,
"channel_type": {
"bits": [
12,
22
],
"names": [
"static_remotekey/even",
"anchors/even"
]
},
"updates": {
"local": {
"htlc_minimum_msat": 0,
"htlc_maximum_msat": 19454000,
"cltv_expiry_delta": 6,
"fee_base_msat": 1,
"fee_proportional_millionths": 10
}
},
"state": "ONCHAIN",
"scratch_txid": "scratchid2030303030303030303030303030303030303030303030303030303",
"last_tx_fee_msat": 2250000,
"lost_state": false,
"feerate": {
"perkw": 3750,
"perkb": 15000
},
"owner": "onchaind",
"direction": 0,
"channel_id": "channelid1100011000110001100011000110001100011000110001100011000",
"funding_txid": "channeltxid01050000500005000050000500005000050000500005000050000",
"funding_outnum": 1,
"initial_feerate": "10000perkw",
"last_feerate": "10000perkw",
"next_feerate": "10416perkw",
"inflight": [
{
"funding_txid": "channeltxid01050000500005000050000500005000050000500005000050000",
"funding_outnum": 1,
"feerate": "10000perkw",
"total_funding_msat": 20000000,
"our_funding_msat": 20000000,
"splice_amount": 0,
"scratch_txid": "scratchid2030303030303030303030303030303030303030303030303030303"
}
],
"close_to_addr": "bcrt1pcl00030003000300030003000300030003000300030003000300030003",
"close_to": "db2dec31030303030303030303030303030303030303030303030303030303030303",
"private": false,
"opener": "local",
"closer": "local",
"alias": {
"local": "30000003x60000003x60003",
"remote": "10000003x20000003x30003"
},
"features": [
"option_static_remotekey",
"option_anchors"
],
"funding": {
"local_funds_msat": 20000000,
"remote_funds_msat": 0,
"pushed_msat": 0
},
"to_us_msat": 20000000,
"min_to_us_msat": 20000000,
"max_to_us_msat": 20000000,
"total_msat": 20000000,
"fee_base_msat": 1,
"fee_proportional_millionths": 10,
"dust_limit_msat": 546000,
"their_max_htlc_value_in_flight_msat": 18446744073709552000,
"our_max_htlc_value_in_flight_msat": 18446744073709552000,
"their_reserve_msat": 546000,
"our_reserve_msat": 546000,
"spendable_msat": 8172000,
"receivable_msat": 0,
"minimum_htlc_in_msat": 0,
"minimum_htlc_out_msat": 0,
"maximum_htlc_out_msat": 19454000,
"their_to_self_delay": 5,
"our_to_self_delay": 5,
"max_accepted_htlcs": 483,
"state_changes": [
{
"timestamp": "2024-10-10T00:01:00.000Z",
"old_state": "DUALOPEND_OPEN_COMMITTED",
"new_state": "DUALOPEND_AWAITING_LOCKIN",
"cause": "user",
"message": "Sigs exchanged, waiting for lock-in"
},
{
"timestamp": "2024-10-10T00:02:00.000Z",
"old_state": "DUALOPEND_AWAITING_LOCKIN",
"new_state": "CHANNELD_SHUTTING_DOWN",
"cause": "user",
"message": "User or plugin invoked close command"
},
{
"timestamp": "2024-10-10T00:03:00.000Z",
"old_state": "CHANNELD_SHUTTING_DOWN",
"new_state": "CLOSINGD_SIGEXCHANGE",
"cause": "user",
"message": "Start closingd"
},
{
"timestamp": "2024-10-10T00:04:00.000Z",
"old_state": "CLOSINGD_SIGEXCHANGE",
"new_state": "CLOSINGD_COMPLETE",
"cause": "user",
"message": "Closing complete"
},
{
"timestamp": "2024-10-10T00:05:00.000Z",
"old_state": "CLOSINGD_COMPLETE",
"new_state": "FUNDING_SPEND_SEEN",
"cause": "user",
"message": "Onchain funding spend"
},
{
"timestamp": "2024-10-10T00:06:00.000Z",
"old_state": "FUNDING_SPEND_SEEN",
"new_state": "ONCHAIN",
"cause": "user",
"message": "Onchain init reply"
}
],
"status": [
"CLOSINGD_SIGEXCHANGE:We agreed on a closing fee of 2250 satoshi for tx:scratchid2030303030303030303030303030303030303030303030303030303",
"ONCHAIN:Tracking mutual close transaction",
"ONCHAIN:All outputs resolved: waiting 96 more blocks before forgetting channel"
],
"in_payments_offered": 0,
"in_offered_msat": 0,
"in_payments_fulfilled": 0,
"in_fulfilled_msat": 0,
"out_payments_offered": 0,
"out_offered_msat": 0,
"out_payments_fulfilled": 0,
"out_fulfilled_msat": 0,
"htlcs": [],
"last_stable_connection": 1738530000
}
]
}
okay so a few things to clock, bestie π
- Channel one is
"state": "CHANNELD_NORMAL","peer_connected": true, and it's got the little"reestablished": truebadge on it like a friendship bracelet π«Ά Its"status"is literally"CHANNELD_NORMAL:Channel ready for use."β thriving. - It's also got exactly one HTLC mid-flight in
"htlcs","state": "SENT_ADD_ACK_REVOCATION","direction": "out","id": 17,"amount_msat": 4000082,"expiry": 181. Not me refreshing my little payment tracker π - Channel two is
"peer_connected": false,"state": "ONCHAIN","owner": "onchaind", and it's got both"opener": "local"AND"closer": "local"β she opened it, she closed it, she contained multitudes β¨ It also has"closer"at all, plus"initial_feerate","last_feerate","next_feerate"and an"inflight"entry, which channel one justβ¦ doesn't. Different eras, different fields, no notes. - Peep the
"state_changes"journey on channel two:DUALOPEND_OPEN_COMMITTEDβDUALOPEND_AWAITING_LOCKINβCHANNELD_SHUTTING_DOWNβCLOSINGD_SIGEXCHANGEβCLOSINGD_COMPLETEβFUNDING_SPEND_SEENβONCHAIN. It's giving character development π - And the last
"status"line on it:"ONCHAIN:All outputs resolved: waiting 96 more blocks before forgetting channel"β she's not gone, she's just on a 96-block wellness retreat π - Also
"lost_state": falseon BOTH, which is the vibe we want. And"htlcs": []on channel two, because there's nothing left to send,"receivable_msat": 0bestie.
one tiny thing:"channels"is the key holding the whole array β if a channel has no"updates".remote"like channel two, that just means it only printed"local". That's literally what's in the output, don't read anything extra into it π
and that's the whole page, bestie! π happy channel-stalking. this page came to you straight from the Core Lightning girlies β version v26.06.9 β and it's LIGHTNING-LISTPEERCHANNELS(7) if you ever need to find it again. go check your listpeerchannels output, feel your feelings, slay, periodt ππ¦β¨
π¦ where this page comes from
- nixpkgs unstable: clightning 26.06.9
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms