Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change bolt12_unsigned to bolt12 #207

Open
wants to merge 37 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
948607f
change bolt12_unsigned to bolt12
hMsats Apr 14, 2023
c160396
Euro and Bolt12
hMsats Apr 27, 2023
bc355f0
Tell about this fork
hMsats Apr 28, 2023
da0ff5a
Tell about this fork
hMsats Apr 28, 2023
95ccc74
Euro sign, not dollar sign
hMsats Apr 29, 2023
51e8660
Always euro, not cent
hMsats Apr 29, 2023
e35a84b
fat
hMsats Apr 29, 2023
6c05c1b
Ready for Core Lightning v23.05
hMsats May 9, 2023
736052e
Not msatoshi but amount_msat
hMsats May 10, 2023
03c111d
First modification for listpeerchannels
hMsats May 31, 2023
86ba2af
Spark-wallet working with CL allow-deprecated-apis=false, except chan…
hMsats Jun 5, 2023
482a48a
Everything in spark-wallet working with CL allow-deprecated-apis=false
hMsats Jun 5, 2023
464791f
Compatible with CL v23.05
hMsats Jun 5, 2023
4cf63bc
Remove some old stuff
hMsats Jun 6, 2023
1fcf12a
How I run everything
hMsats Jun 6, 2023
00efe0e
How I run everything
hMsats Jun 6, 2023
7db4102
Link to usd version
hMsats Jun 6, 2023
80ed099
greater/less than
hMsats Jun 6, 2023
01737f6
greater/less than
hMsats Jun 6, 2023
41dce21
Browser not website
hMsats Jun 7, 2023
ca891e9
Always use decode instead of decodepay
hMsats Jul 21, 2023
db8055c
Put back comment as code
hMsats Jul 21, 2023
650ea09
Always assume experimental offers
hMsats Jul 21, 2023
9efff95
Some config statements
hMsats Jul 22, 2023
6eb7c44
mandatory
hMsats Jul 22, 2023
376f19f
Don't wait for listconfigs makes spark start-up much faster
hMsats Jul 22, 2023
f0d4efa
Remove a text line about offers
hMsats Jul 29, 2023
c6a0a39
Update README.md
hMsats Aug 25, 2023
bebb8d4
Spark-wallet will give a correct message if "experimental-offers" is …
hMsats Sep 4, 2023
98d4601
Install babel
hMsats Nov 8, 2023
942e14e
Update
hMsats Oct 13, 2024
b2d58d4
Update
hMsats Oct 13, 2024
960dc35
Return offer for any amount via payer_note when paying a bolt12 offer
hMsats Oct 16, 2024
60ac941
Add a warning
hMsats Oct 16, 2024
0367832
offer.amount_msat -> offer.offer_amount_msat
hMsats Oct 20, 2024
636aeae
Remove payer_note
hMsats Oct 26, 2024
e2371c0
Show payer offer along with Offer ID
hMsats Oct 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ TODO
dist
spark-wallet-*-npm.tgz
docker-builds
maken_spark.sh
putback.sh
48 changes: 47 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,49 @@
# Spark Lightning Wallet Euro

<b>This fork of Spark-wallet shows prices in Euro plus Bolt12 offers working.

WARNING: This fork of Spark-wallet returns your offer for any amount when paying a bolt12 offer.

Compatible with Core Lightning version v23.05 or higher.

The `allow-deprecated-apis=false` is optional in config.

Note: the usd version can be found [here](https://github.com/hMsats/spark-wallet-usd.git)

HOW I RUN SPARK WALLET ON UBUNTU LINUX:

git clone https://github.com/hMsats/spark-wallet-euro.git

cd spark-wallet-euro

npm install

npm install babel

npm run dist:npm

Opened port 9737 on my modem/router

The tls certificates:
cert.pem key.pem

are in directory:
/home/user/.spark-wallet/tls

and are the same "LetsEncrypt" signed files as used by my website "bitcoinserver.nl"

Run Spark:

/home/user/spark-wallet-euro/dist/cli.js --host 0.0.0.0 --tls-name bitcoinserver.nl --port 9737 --ln-path /media/ssd/.lightning/bitcoin --login &lt;username&gt;:&lt;some large number&gt; &gt;& out_spark.txt &

I open spark-wallet in the address bar of a browser on my smart phone like this:
bitcoinserver.nl:9737

and then create a link/app on the home screen of my phone
</b>

THE REST OF THE TEXT IS FROM THE ORIGINAL SPARK-WALLET:

# Spark Lightning Wallet

[![npm release](https://img.shields.io/npm/v/spark-wallet.svg)](https://www.npmjs.com/package/spark-wallet)
Expand Down Expand Up @@ -178,7 +224,7 @@ The QR scanner works if you access Spark without using the PWA "Add to homescree
- **Pay** and **Request** are pretty intuitive and don't require much explaining. Try them!

- **Display unit:** Click the balance on the top-right or the unit in the "request payment" page to toggle the currency display unit.
The available options are sat, bits, milli, btc and usd.
The available options are sat, bits, milli, btc and euro.

- **Theme switcher:** Click the theme name on the bottom-right to change themes (you can choose between 16 [bootswatch](https://bootswatch.com) themes).

Expand Down
2 changes: 1 addition & 1 deletion client/src/intent.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ module.exports = ({ DOM, route, conf$, scan$, urihandler$, offerInv$ }) => {
// New invoice/offer action
, newInv$ = submit('[do=new-invoice]').map(r => ({
label: nanoid()
, msatoshi: r.msatoshi || 'any'
, amount_msat: r.amount_msat || 'any'
, description: r.description || '⚡'
, reusable_offer: !!r['reusable-offer'] }))
, invUseOffer$ = on('[do=new-invoice] [name=reusable-offer]', 'input')
Expand Down
53 changes: 26 additions & 27 deletions client/src/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ const msatbtc = big(100000000000) // msat in 1 btc
const
sumChans = chans =>
chans.filter(c => c.chan.state === 'CHANNELD_NORMAL')
.reduce((T, c) => T + c.chan.msatoshi_to_us, 0)
.reduce((T, c) => T + c.chan.to_us_msat, 0)

, sumOuts = outs =>
outs.filter(o => o.status === 'confirmed')
.reduce((T, o) => T + o.value*1000, 0)
.reduce((T, o) => T + o.amount_msat, 0)

, fmtAlert = (s, unitf) => s.replace(/@\{\{(\d+)\}\}/g, (_, msat) => unitf(msat))

Expand All @@ -20,10 +20,10 @@ const

const
themes = 'cerulean cosmo cyborg dark flatly lumen lux materia sandstone simplex slate solar spacelab superhero united yeti'.split(' ')
, units = 'sat bits milli BTC USD'.split(' ')
, unitprec = { sat: 3, bits: 5, milli: 8, BTC: 11, USD: 6 }
, units = 'sat bits milli BTC euro'.split(' ')
, unitprec = { sat: 3, bits: 5, milli: 8, BTC: 11, euro: 2 }
, unitrate = { sat: 0.001, bits: 0.00001, milli: 0.00000001, BTC: 0.00000000001 }
, unitstep = { ...unitrate, USD: 0.000001 }
, unitstep = { ...unitrate, euro: 0.01 }

module.exports = ({ dismiss$, togExp$, togTheme$, togUnit$, page$, goHome$, goRecv$, goChan$, confPay$
, amtVal$, execRes$, clrHist$, feedStart$: feedStart_$, togFeed$, togChan$, togAddrType$
Expand All @@ -32,7 +32,7 @@ module.exports = ({ dismiss$, togExp$, togTheme$, togUnit$, page$, goHome$, goRe
, req$$, error$, payreq$, incoming$, payResult$, payments$, invoices$, funds$, payUpdates$
, funded$, closed$
, offer$, offerPayQuantity$: offerPayQuantityInput$, invUseOffer$
, btcusd$, info$, lnconfig$, peers$ }) => {
, btceuro$, info$, lnconfig$, peers$ }) => {
const

// Config options
Expand All @@ -43,9 +43,9 @@ module.exports = ({ dismiss$, togExp$, togTheme$, togUnit$, page$, goHome$, goRe
, conf$ = combine({ expert$, theme$, unit$ })

// Currency & unit conversion handling
, msatusd$ = btcusd$.map(rate => big(rate).div(msatbtc)).startWith(null)
, rate$ = O.combineLatest(unit$, msatusd$, (unit, msatusd) => unitrate[unit] || msatusd)
, unitf$ = O.combineLatest(unit$, msatusd$, unitFormatter)
, msateuro$ = btceuro$.map(rate => big(rate).div(msatbtc)).startWith(null)
, rate$ = O.combineLatest(unit$, msateuro$, (unit, msateuro) => unitrate[unit] || msateuro)
, unitf$ = O.combineLatest(unit$, msateuro$, unitFormatter)

// Keep track of connection status
, connected$ = req$$.flatMap(r$ => r$.mapTo(true).catch(_ => O.empty()))
Expand All @@ -68,8 +68,8 @@ module.exports = ({ dismiss$, togExp$, togTheme$, togUnit$, page$, goHome$, goRe
, alert$ = O.merge(
error$.map(err => [ 'danger', ''+err ])
, incoming$.map(i => [ 'success', `Received payment of @{{${recvAmt(i)}}}` ])
, paySent$.map(p => [ 'success', `Sent payment of @{{${p.msatoshi}}}` ])
, funded$.map(c => [ 'success', `Opening channel for @{{${c.chan.msatoshi_total}}}, awaiting on-chain confirmation` ])
, paySent$.map(p => [ 'success', `Sent payment of @{{${p.amount_msat}}}` ])
, funded$.map(c => [ 'success', `Opening channel for @{{${c.chan.total_msat}}}, awaiting on-chain confirmation` ])
, closed$.map(c => [ 'success', `Channel ${c.chan.short_channel_id || c.chan.channel_id} is closing` ])
, dismiss$.mapTo(null)
)
Expand All @@ -88,7 +88,7 @@ module.exports = ({ dismiss$, togExp$, togTheme$, togUnit$, page$, goHome$, goRe
// Periodically re-sync channel balance from "listpeers",
// continuously patch with known channel opening/closing
, channels$ = O.merge(
peers$.map(peers => _ => getChannels(peers))
peers$.map(channels => _ => getChannels(channels))
, funded$.map(chan => S => [ ...S, chan ])
, closed$.map(chan => S => [ ...S.filter(c => c.chan.channel_id != chan.chan.channel_id), chan ])
).startWith(null).scan((S, mod) => mod(S))
Expand All @@ -99,8 +99,8 @@ module.exports = ({ dismiss$, togExp$, togTheme$, togUnit$, page$, goHome$, goRe
// continuously patch with known incoming & outgoing payments
, cbalance$ = O.merge(
channels$.map(chans => _ => sumChans(chans))
, incoming$.map(inv => N => N + inv.msatoshi_received)
, paySent$.map(pay => N => N - pay.msatoshi_sent)
, incoming$.map(inv => N => N + inv.amount_received_msat)
, paySent$.map(pay => N => N - pay.amount_sent_msat)
).startWith(null).scan((N, mod) => mod(N)).distinctUntilChanged()

// Periodically re-sync from listpays, continuously patch with known outgoing
Expand Down Expand Up @@ -128,7 +128,7 @@ module.exports = ({ dismiss$, togExp$, togTheme$, togUnit$, page$, goHome$, goRe
// Chronologically sorted feed of incoming and outgoing payments
, feed$ = O.combineLatest(freshInvs$, freshPays$, (invoices, payments) => [
...invoices.map(i => [ 'in', i.paid_at, recvAmt(i), i ])
, ...payments.map(p => [ 'out', p.created_at, p.msatoshi, p ])
, ...payments.map(p => [ 'out', p.created_at, p.amount_msat, p ])
].sort((a, b) => b[1] - a[1]))

// Collapsed payment/invoice on home feed list
Expand All @@ -145,7 +145,7 @@ module.exports = ({ dismiss$, togExp$, togTheme$, togUnit$, page$, goHome$, goRe
, amtMsat$ = amtVal$.withLatestFrom(rate$, (amt, rate) => amt && rate && big(amt).div(rate).toFixed(0) || '')
.merge(page$.mapTo(null)).startWith(null)
, amtData$ = combine({
msatoshi: amtMsat$
amount_msat: amtMsat$
, amount: unit$.withLatestFrom(amtMsat$, rate$, (unit, msat, rate) => formatAmt(msat, rate, unitprec[unit], false))
.merge(goRecv$.merge(offer$).merge(payreq$).mapTo(''))
, unit: unit$
Expand Down Expand Up @@ -187,7 +187,7 @@ module.exports = ({ dismiss$, togExp$, togTheme$, togUnit$, page$, goHome$, goRe
, amtData$, chanActive$, rpcHist$
, fundMaxChan$, depositAddrType$
, offersEnabled$, offerPayQuantity$, invUseOffer$
, msatusd$, btcusd$: btcusd$.startWith(null)
, msateuro$, btceuro$: btceuro$.startWith(null)
}).shareReplay(1)
}

Expand All @@ -205,18 +205,18 @@ const markFailed = (payments, payment_hash) => payments.map(pay =>
const pendingPayStub = inv => ({
status: 'pending'
, created_at: Date.now()/1000|0
, msatoshi: inv.custom_msat || inv.msatoshi
, msatoshi_sent: 0
, amount_msat: inv.custom_msat || inv.amount_msat
, amount_sent_msat: 0
, destination: inv.payee || inv.node_id || inv.destination
, ...only(inv, 'payment_hash', 'description', 'offer_id', 'vendor', 'quantity', 'payer_note' )
})

const unitFormatter = (unit, msatusd) => (msat, as_alt_unit=false, non_breaking=true) => {
const unit_d = !as_alt_unit ? unit : (unit == 'USD' ? 'sat' : 'USD')
const unit_rate = unit_d == 'USD' ? msatusd : unitrate[unit_d]
const unitFormatter = (unit, msateuro) => (msat, as_alt_unit=false, non_breaking=true) => {
const unit_d = !as_alt_unit ? unit : (unit == 'euro' ? 'sat' : 'euro')
const unit_rate = unit_d == 'euro' ? msateuro : unitrate[unit_d]

// Use less precision for USD when displayed as the alt unit
const unit_prec = unit_d == 'USD' && as_alt_unit ? 2 : unitprec[unit_d]
// Use less precision for euro when displayed as the alt unit
const unit_prec = unit_d == 'euro' && as_alt_unit ? 2 : unitprec[unit_d]

// If the alt unit's rate is missing, hide it entirely. The primary one
// is returned as 'n/a' (below).
Expand All @@ -226,7 +226,6 @@ const unitFormatter = (unit, msatusd) => (msat, as_alt_unit=false, non_breaking=
return `${unit_rate ? formatAmt(msat, unit_rate, unit_prec) : 'n/a'}${separator}${unit_d}`
}

// Check if experimental offers support is enabled
// Always considered off in c-lightning <=v0.10.0 because it used an incompatible spec.
// Assume experimental offers support is enabled
const checkOffersEnabled = conf =>
!!(conf['experimental-offers'] && !/^0\.(9\.|10\.0)/.test(conf['# version']))
!!(true)
12 changes: 6 additions & 6 deletions client/src/rpc.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ exports.parseRes = ({ HTTP, SSE }) => {

// Periodic updates
, info$: reply('getinfo').map(r => r.body)
, peers$: reply('listpeers').map(r => r.body.peers)
, peers$: reply('listpeerchannels').map(r => r.body.channels)
, payments$: reply('_listpays').map(r => r.body.pays)
, invoices$: reply('_listinvoices').map(r => r.body.invoices)
, funds$: reply('listfunds').map(r => r.body)
Expand All @@ -58,7 +58,7 @@ exports.parseRes = ({ HTTP, SSE }) => {
// Push updates via server-sent events
, incoming$: SSE('inv-paid')
, payUpdates$: SSE('pay-updates')
, btcusd$: SSE('btcusd')
, btceuro$: SSE('btceuro')
}
}

Expand All @@ -69,14 +69,14 @@ exports.makeReq = ({ viewPay$, confPay$, offerPay$, offerRecv$, newInv$, goLogs$
viewPay$.map(paystr => [ '_decodecheck', [ paystr ], { paystr } ])
, confPay$.map(pay => [ '_pay', [ pay.paystr, pay.custom_msat ], { pay, bg: true } ])
, newInv$.map(inv => !inv.reusable_offer
? [ 'invoice', [ inv.msatoshi, inv.label, inv.description, INVOICE_TTL ], inv ]
: [ 'offer', [ inv.msatoshi, inv.description, null, inv.label ], inv ])
? [ 'invoice', [ inv.amount_msat, inv.label, inv.description, INVOICE_TTL ], inv ]
: [ 'offer', [ inv.amount_msat, inv.description, null, inv.label ], inv ])
, offerPay$.map(pay => [ '_fetchinvoice', [ pay.paystr, pay.custom_msat, pay.quantity, pay.payer_note ] ])
, offerRecv$.map(recv => [ 'sendinvoice', [ recv.paystr, recv.label ] ])

, goLogs$.mapTo( [ 'getlog' ] )

, updChan$.mapTo( [ 'listpeers' ] )
, updChan$.mapTo( [ 'listpeerchannels' ] )
, openChan$.map(d => [ '_connectfund', [ d.nodeuri, d.channel_capacity_sat, d.feerate ] ])
, closeChan$.map(d => [ '_close', [ d.peerid, d.chanid ] ])

Expand All @@ -90,7 +90,7 @@ exports.makeReq = ({ viewPay$, confPay$, offerPay$, offerRecv$, newInv$, goLogs$
, timer(60000).mapTo( [ '_listpays', [], { bg: true } ])
, timer(60000).mapTo( [ 'getinfo', [], { bg: true } ])
, timer(60000).merge(goChan$).throttleTime(2000)
.mapTo( [ 'listpeers', [], { bg: true } ])
.mapTo( [ 'listpeerchannels', [], { bg: true } ])
, timer(60000).merge(goNewChan$).merge(goDeposit$).throttleTime(2000)
.mapTo( [ 'listfunds', [], { bg: true } ])

Expand Down
12 changes: 6 additions & 6 deletions client/src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ export const parseUri = uri => {
// returns the expected invoice amount when its <0.5% different from the actual amount paid,
// or the actual amount paid otherwise. this is done to make the UX less confusing when the
// sender uses overpayment randomization (https://github.com/ElementsProject/lightning/issues/1089)
export const recvAmt = ({ msatoshi: expected, msatoshi_received: actual }) =>
export const recvAmt = ({ amount_msat: expected, amount_received_msat: actual }) =>
(expected && (actual-expected)/expected<0.005) ? expected : actual

// Parse "listpeers" to get all channels as a list of (peer,channel) tuples
export const getChannels = peers => [].concat(...peers.map(peer => peer.channels.map(chan => ({ peer, chan }))))
// Parse "listpeerchannels" to get all channels as a list
export const getChannels = channels => [].concat(...channels.map(chan => ({ chan })))

// Parse the `sat`-suffixed amount string fields into numbers
export const parsePayment = p => ({
...p
, msatoshi: p.msatoshi != null ? p.msatoshi : p.amount_msat ? +p.amount_msat.slice(0, -4) : null
, msatoshi_sent: p.amount_sent_msat ? +p.amount_sent_msat.slice(0, -4) : null
, amount_msat: p.amount_msat != null ? p.amount_msat : p.amount_msat ? +p.amount_msat : null
, amount_sent_msat: p.amount_sent_msat ? +p.amount_sent_msat : null
})

export const combine = obj => {
Expand Down Expand Up @@ -70,4 +70,4 @@ export const parseRpcCmd = str => {
export const only = (obj, ...keys) => keys.reduce((R, k) => {
if (obj[k] != null) R[k] = obj[k]
return R
}, {})
}, {})
32 changes: 16 additions & 16 deletions client/src/views/channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ const stateGroups = {
const getGroup = state => Object.keys(stateGroups).find(group => stateGroups[group].includes(state))

// Sort by status first, then by amount
const chanSorter = (a, b) => (chanSorting(b) - chanSorting(a)) || (b.chan.msatoshi_total - a.chan.msatoshi_total)
const chanSorter = (a, b) => (chanSorting(b) - chanSorting(a)) || (b.chan.total_msat - a.chan.total_msat)

const chanSorting = ({ peer, chan }) =>
peer.connected && chan.state == 'CHANNELD_NORMAL' ? 6
: peer.connected && stateGroups.opening.includes(chan.state) ? 5
: !peer.connected && chan.state == 'CHANNELD_NORMAL' ? 4
const chanSorting = ({ chan }) =>
chan.peer_connected && chan.state == 'CHANNELD_NORMAL' ? 6
: chan.peer_connected && stateGroups.opening.includes(chan.state) ? 5
: !chan.peer_connected && chan.state == 'CHANNELD_NORMAL' ? 4
: stateGroups.closing.includes(chan.state) ? 3
: stateGroups.opening.includes(chan.state) ? 2
: stateGroups.closed.includes(chan.state) ? 1
Expand Down Expand Up @@ -77,19 +77,19 @@ export const newChannel = ({ amtData, fundMaxChan, obalance, unitf, conf: { unit
])
}

const channelRenderer = ({ chanActive, unitf, expert, blockheight }) => ({ chan, peer }) => {
const channelRenderer = ({ chanActive, unitf, expert, blockheight }) => ({ chan }) => {

const bar = (label, color, msatoshi, amtText=unitf(msatoshi)) =>
const bar = (label, color, amount_msat, amtText=unitf(amount_msat)) =>
div(`.progress-bar.bg-${color}`, {
attrs: { role: 'progressbar', title: `${label}: ${amtText}` }
, style: { width: `${msatoshi / chan.msatoshi_total * 100}%` }
}, msatoshi/chan.msatoshi_total > 0.05 ? amtText : '')
, style: { width: `${amount_msat / chan.total_msat * 100}%` }
}, amount_msat/chan.total_msat > 0.05 ? amtText : '')

const stateGroup = getGroup(chan.state)
, stateLabel = !peer.connected && stateGroup == 'active' ? 'offline' : stateGroup
, stateLabel = !chan.peer_connected && stateGroup == 'active' ? 'offline' : stateGroup
, isClosed = [ 'closing', 'closed' ].includes(stateGroup)
, ours = chan.msatoshi_to_us
, theirs = chan.msatoshi_total - ours
, ours = chan.to_us_msat
, theirs = chan.total_msat - ours
// the channel reserve fields appear to be sometimes (incorrectly?) missing,
// defaulting them to 0 isn't quite right but should work for now
, ourReserve = chan.our_channel_reserve_satoshis*1000 || 0
Expand All @@ -103,11 +103,11 @@ const channelRenderer = ({ chanActive, unitf, expert, blockheight }) => ({ chan,

const visible = chanActive == chan.channel_id
, classes = { active: visible, 'list-group-item-action': !visible
, [`c-${stateGroup}`]: true, 'p-online': peer.connected, 'p-offline': !peer.connected }
, [`c-${stateGroup}`]: true, 'p-online': chan.peer_connected, 'p-offline': !chan.peer_connected }

return li('.list-group-item', { class: classes, dataset: { chanToggle: chan.channel_id } }, [
header('.d-flex.justify-content-between.mb-2', [
span('.capacity', unitf(chan.msatoshi_total))
span('.capacity', unitf(chan.total_msat))
, span('.state', stateLabel)
])

Expand All @@ -133,12 +133,12 @@ const channelRenderer = ({ chanActive, unitf, expert, blockheight }) => ({ chan,
, isClosed || expert ? li([ strong('Theirs:'), ' ', unitf(theirs) ]) : ''

, channelAge ? li([ strong('Age:'), ' ', `${channelAge} blocks (${channelAgeFuz})` ]) : ''
, li([ strong('Peer:'), ' ', small('.break-all', peer.id), ' ', em(`(${peer.connected ? 'connected' : 'disconnected'})`) ])
, li([ strong('Peer:'), ' ', small('.break-all', chan.peer_id), ' ', em(`(${chan.peer_connected ? 'connected' : 'disconnected'})`) ])
, expert ? li([ strong('Funding TXID:'), ' ', small('.break-all', chan.funding_txid) ]) : ''
, expert ? li('.status-text', chan.status.join('\n')) : ''

, !isClosed ? li('.text-center'
, button('.btn.btn-link.btn-sm', { dataset: { closeChannel: chan.channel_id, closeChannelPeer: peer.id } }, 'Close channel')) : ''
, button('.btn.btn-link.btn-sm', { dataset: { closeChannel: chan.channel_id, closeChannelPeer: chan.peer_id } }, 'Close channel')) : ''

, expert ? li(yaml({ peer: omitKey('channels', peer), ...omitKey('status', chan) })) : ''
])
Expand Down
Loading