Merge pull request #4035 from mempool/mononaut/lightning-balance-bars

Lightning channel balance progress bars
This commit is contained in:
softsimon 2023-07-24 16:22:20 +09:00 committed by GitHub
commit dc43a81899
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 195 additions and 31 deletions

View File

@ -1,19 +1,43 @@
<div class="box">
<table class="table table-borderless table-striped">
<tbody>
<tr></tr>
<tr>
<td i18n="lightning.starting-balance|Channel starting balance">Starting balance</td>
<td *ngIf="showStartingBalance && minStartingBalance === maxStartingBalance"><app-sats [satoshis]="minStartingBalance"></app-sats></td>
<td *ngIf="showStartingBalance && minStartingBalance !== maxStartingBalance">{{ minStartingBalance | number : '1.0-0' }} - {{ maxStartingBalance | number : '1.0-0' }}<app-sats [valueOverride]=" "></app-sats></td>
<td *ngIf="!showStartingBalance">?</td>
</tr>
<tr *ngIf="channel.status === 2">
<td i18n="lightning.closing-balance|Channel closing balance">Closing balance</td>
<td *ngIf="showClosingBalance && minClosingBalance === maxClosingBalance"><app-sats [satoshis]="minClosingBalance"></app-sats></td>
<td *ngIf="showClosingBalance && minClosingBalance !== maxClosingBalance">{{ minClosingBalance | number : '1.0-0' }} - {{ maxClosingBalance | number : '1.0-0' }}<app-sats [valueOverride]=" "></app-sats></td>
<td *ngIf="!showClosingBalance">?</td>
</tr>
</tbody>
</table>
<div class="starting-balance" *ngIf="showStartingBalance">
<h5 i18n="lightning.starting-balance|Channel starting balance">Starting balance</h5>
<div class="nodes">
<h5 class="alias">{{ left.alias }}</h5>
<h5 class="alias">{{ right.alias }}</h5>
</div>
<div class="balances">
<div class="balance left">
<span class="value" *ngIf="minStartingBalance !== maxStartingBalance">{{ minStartingBalance | number : '1.0-0' }} - {{ maxStartingBalance | number : '1.0-0' }}<app-sats [valueOverride]=" "></app-sats></span>
<span class="value" *ngIf="minStartingBalance === maxStartingBalance">{{ minStartingBalance | number : '1.0-0' }}<app-sats [valueOverride]=" "></app-sats></span>
</div>
<div class="balance right">
<span class="value" *ngIf="minStartingBalance !== maxStartingBalance">{{ channel.capacity - maxStartingBalance | number : '1.0-0' }} - {{ channel.capacity - minStartingBalance | number : '1.0-0' }}<app-sats [valueOverride]=" "></app-sats></span>
<span class="value" *ngIf="minStartingBalance === maxStartingBalance">{{ channel.capacity - maxStartingBalance | number : '1.0-0' }}<app-sats [valueOverride]=" "></app-sats></span>
</div>
</div>
<div class="balance-bar">
<div class="bar left" [class.hide-value]="hideStartingLeft" [style]="startingBalanceStyle.left"></div>
<div class="bar center" [style]="startingBalanceStyle.center"></div>
<div class="bar right" [class.hide-value]="hideStartingRight" [style]="startingBalanceStyle.right"></div>
</div>
</div>
<br>
<div class="closing-balance" *ngIf="showClosingBalance">
<h5 i18n="lightning.closing-balance|Channel closing balance">Closing balance</h5>
<div class="balances">
<div class="balance left">
<span class="value" *ngIf="minClosingBalance !== maxClosingBalance">{{ minClosingBalance | number : '1.0-0' }} - {{ maxClosingBalance | number : '1.0-0' }}<app-sats [valueOverride]=" "></app-sats></span>
<span class="value" *ngIf="minClosingBalance === maxClosingBalance">{{ minClosingBalance | number : '1.0-0' }}<app-sats [valueOverride]=" "></app-sats></span>
</div>
<div class="balance right">
<span class="value" *ngIf="minClosingBalance !== maxClosingBalance">{{ channel.capacity - maxClosingBalance | number : '1.0-0' }} - {{ channel.capacity - minClosingBalance | number : '1.0-0' }}<app-sats [valueOverride]=" "></app-sats></span>
<span class="value" *ngIf="minClosingBalance === maxClosingBalance">{{ channel.capacity - maxClosingBalance | number : '1.0-0' }}<app-sats [valueOverride]=" "></app-sats></span>
</div>
</div>
<div class="balance-bar">
<div class="bar left" [class.hide-value]="hideClosingLeft" [style]="closingBalanceStyle.left"></div>
<div class="bar center" [style]="closingBalanceStyle.center"></div>
<div class="bar right" [class.hide-value]="hideClosingRight" [style]="closingBalanceStyle.right"></div>
</div>
</div>
</div>

View File

@ -6,4 +6,98 @@
.box {
margin-bottom: 20px;
}
}
.starting-balance, .closing-balance {
width: 100%;
h5 {
text-align: center;
}
}
.nodes {
display: none;
flex-direction: row;
align-items: baseline;
justify-content: space-between;
@media (max-width: 768px) {
display: flex;
}
}
.balances {
display: flex;
flex-direction: row;
align-items: baseline;
justify-content: space-between;
margin-bottom: 8px;
.balance {
&.left {
text-align: start;
}
&.right {
text-align: end;
}
}
}
.balance-bar {
width: 100%;
height: 2em;
position: relative;
.bar {
position: absolute;
top: 0;
bottom: 0;
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
&.left {
background: #105fb0;
}
&.center {
background: repeating-linear-gradient(
60deg,
#105fb0 0,
#105fb0 12px,
#1a9436 12px,
#1a9436 24px
);
}
&.right {
background: #1a9436;
}
.value {
flex: 0;
white-space: nowrap;
}
&.hide-value {
.value {
display: none;
}
}
}
@media (max-width: 768px) {
height: 1em;
.bar.center {
background: repeating-linear-gradient(
60deg,
#105fb0 0,
#105fb0 8px,
#1a9436 8px,
#1a9436 16px
)
}
}
}

View File

@ -8,8 +8,8 @@ import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } f
})
export class ChannelCloseBoxComponent implements OnChanges {
@Input() channel: any;
@Input() local: any;
@Input() remote: any;
@Input() left: any;
@Input() right: any;
showStartingBalance: boolean = false;
showClosingBalance: boolean = false;
@ -18,29 +18,55 @@ export class ChannelCloseBoxComponent implements OnChanges {
minClosingBalance: number;
maxClosingBalance: number;
startingBalanceStyle: {
left: string,
center: string,
right: string,
} = {
left: '',
center: '',
right: '',
};
closingBalanceStyle: {
left: string,
center: string,
right: string,
} = {
left: '',
center: '',
right: '',
};
hideStartingLeft: boolean = false;
hideStartingRight: boolean = false;
hideClosingLeft: boolean = false;
hideClosingRight: boolean = false;
constructor() { }
ngOnChanges(changes: SimpleChanges): void {
if (this.channel && this.local && this.remote) {
this.showStartingBalance = (this.local.funding_balance || this.remote.funding_balance) && this.channel.funding_ratio;
this.showClosingBalance = this.local.closing_balance || this.remote.closing_balance;
let closingCapacity;
if (this.channel && this.left && this.right) {
this.showStartingBalance = (this.left.funding_balance || this.right.funding_balance) && this.channel.funding_ratio;
this.showClosingBalance = this.left.closing_balance || this.right.closing_balance;
if (this.channel.single_funded) {
if (this.local.funding_balance) {
if (this.left.funding_balance) {
this.minStartingBalance = this.channel.capacity;
this.maxStartingBalance = this.channel.capacity;
} else if (this.remote.funding_balance) {
} else if (this.right.funding_balance) {
this.minStartingBalance = 0;
this.maxStartingBalance = 0;
}
} else {
this.minStartingBalance = clampRound(0, this.channel.capacity, this.local.funding_balance * this.channel.funding_ratio);
this.maxStartingBalance = clampRound(0, this.channel.capacity, this.channel.capacity - (this.remote.funding_balance * this.channel.funding_ratio));
this.minStartingBalance = clampRound(0, this.channel.capacity, this.left.funding_balance * this.channel.funding_ratio);
this.maxStartingBalance = clampRound(0, this.channel.capacity, this.channel.capacity - (this.right.funding_balance * this.channel.funding_ratio));
}
const closingCapacity = this.channel.capacity - this.channel.closing_fee;
this.minClosingBalance = clampRound(0, closingCapacity, this.local.closing_balance);
this.maxClosingBalance = clampRound(0, closingCapacity, closingCapacity - this.remote.closing_balance);
closingCapacity = this.channel.capacity - this.channel.closing_fee;
this.minClosingBalance = clampRound(0, closingCapacity, this.left.closing_balance);
this.maxClosingBalance = clampRound(0, closingCapacity, closingCapacity - this.right.closing_balance);
// margin of error to account for 2 x 330 sat anchor outputs
if (Math.abs(this.minClosingBalance - this.maxClosingBalance) <= 660) {
@ -50,6 +76,26 @@ export class ChannelCloseBoxComponent implements OnChanges {
this.showStartingBalance = false;
this.showClosingBalance = false;
}
const startingMinPc = (this.minStartingBalance / this.channel.capacity) * 100;
const startingMaxPc = (this.maxStartingBalance / this.channel.capacity) * 100;
this.startingBalanceStyle = {
left: `left: 0%; right: ${100 - startingMinPc}%;`,
center: `left: ${startingMinPc}%; right: ${100 -startingMaxPc}%;`,
right: `left: ${startingMaxPc}%; right: 0%;`,
};
this.hideStartingLeft = startingMinPc < 15;
this.hideStartingRight = startingMaxPc > 85;
const closingMinPc = (this.minClosingBalance / closingCapacity) * 100;
const closingMaxPc = (this.maxClosingBalance / closingCapacity) * 100;
this.closingBalanceStyle = {
left: `left: 0%; right: ${100 - closingMinPc}%;`,
center: `left: ${closingMinPc}%; right: ${100 - closingMaxPc}%;`,
right: `left: ${closingMaxPc}%; right: 0%;`,
};
this.hideClosingLeft = closingMinPc < 15;
this.hideClosingRight = closingMaxPc > 85;
}
}

View File

@ -75,14 +75,14 @@
<div class="row row-cols-1 row-cols-md-2" *ngIf="!error">
<div class="col">
<app-channel-box [channel]="channel.node_left"></app-channel-box>
<app-channel-close-box *ngIf="showCloseBoxes(channel)" [channel]="channel" [local]="channel.node_left" [remote]="channel.node_right"></app-channel-close-box>
</div>
<div class="col">
<app-channel-box [channel]="channel.node_right"></app-channel-box>
<app-channel-close-box *ngIf="showCloseBoxes(channel)" [channel]="channel" [local]="channel.node_right" [remote]="channel.node_left"></app-channel-close-box>
</div>
</div>
<app-channel-close-box *ngIf="showCloseBoxes(channel)" [channel]="channel" [left]="channel.node_left" [right]="channel.node_right"></app-channel-close-box>
<br>
<ng-container *ngIf="transactions$ | async as transactions">