Skip to content

Commit

Permalink
v1.0.3 (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
cryptosharks131 authored Feb 13, 2022
1 parent 6b1c810 commit d3f20ed
Show file tree
Hide file tree
Showing 17 changed files with 471 additions and 80 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ Alternatively, you may also make your own task for these files with your preferr
You can serve the dashboard at all times using a webserver instead of the development server. Using a webserver will serve your static files and installing whitenoise is not required when running in this manner. Any webserver can be used to host the site if configured properly. A bash script has been included to help aide in the setup of a nginx webserver. `sudo bash nginx.sh`

## Key Features
### Suggests Fee Rates
LNDg will make suggestions on an adjustment to the current set outbound fee rate for each channel. This uses historical payment and forwarding data over the last 7 days to drive suggestions.

You may see another adjustment right after setting the new suggested fee rate on some channels. This is normal and you should wait ~24 hours before changing the fee rate again on any given channel.

### Suggests New Peers
LNDg will make suggestions for new peers to open channels to based on your node's successful routing history.
#### There are two unique values in LNDg:
Expand Down
2 changes: 2 additions & 0 deletions gui/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ class AutoRebalanceForm(forms.Form):
(3, 'ar_in_target'),
(4, 'ar_out_target'),
(5, 'ar_enabled'),
(6, 'ar_max_cost'),
(7, 'channel_state'),
]

class UpdateChannel(forms.Form):
Expand Down
71 changes: 71 additions & 0 deletions gui/migrations/0020_auto_20220126_2113.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Generated by Django 3.2.7 on 2022-01-26 21:13

from django.db import migrations, models
import django.utils.timezone

def update_defaults(apps, schedma_editor):
channels = apps.get_model('gui', 'channels')
settings = apps.get_model('gui', 'localsettings')
try:
if settings.objects.filter(key='AR-MaxCost%').exists():
ar_max_cost = float(settings.objects.filter(key='AR-MaxCost%')[0].value)
else:
ar_max_cost = 0.75
channels.objects.all().update(ar_max_cost=ar_max_cost*100)
except Exception as e:
print('Migration step failed:', str(e))

def revert_defaults(apps, schedma_editor):
pass

class Migration(migrations.Migration):

dependencies = [
('gui', '0019_auto_20220122_1009'),
]

operations = [
migrations.AddField(
model_name='channels',
name='ar_max_cost',
field=models.IntegerField(default=65),
),
migrations.AddField(
model_name='channels',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='channels',
name='local_disabled',
field=models.BooleanField(default=False),
preserve_default=False,
),
migrations.AddField(
model_name='channels',
name='remote_disabled',
field=models.BooleanField(default=False),
preserve_default=False,
),
migrations.AddField(
model_name='payments',
name='cleaned',
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name='invoices',
name='message',
field=models.CharField(max_length=500, null=True),
),
migrations.RunPython(update_defaults, revert_defaults),
migrations.AlterField(
model_name='channels',
name='ar_max_cost',
field=models.IntegerField(),
),
migrations.AlterField(
model_name='channels',
name='last_update',
field=models.DateTimeField(),
),
]
14 changes: 13 additions & 1 deletion gui/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Payments(models.Model):
chan_out_alias = models.CharField(null=True, max_length=32)
keysend_preimage = models.CharField(null=True, max_length=64)
message = models.CharField(null=True, max_length=255)
cleaned = models.BooleanField(default=False)
class Meta:
app_label = 'gui'

Expand Down Expand Up @@ -41,7 +42,7 @@ class Invoices(models.Model):
chan_in = models.IntegerField(null=True)
chan_in_alias = models.CharField(null=True, max_length=32)
keysend_preimage = models.CharField(null=True, max_length=64)
message = models.CharField(null=True, max_length=255)
message = models.CharField(null=True, max_length=500)
index = models.IntegerField()
class Meta:
app_label = 'gui'
Expand Down Expand Up @@ -74,14 +75,18 @@ class Channels(models.Model):
alias = models.CharField(max_length=32)
local_base_fee = models.IntegerField()
local_fee_rate = models.IntegerField()
local_disabled = models.BooleanField()
remote_base_fee = models.IntegerField()
remote_fee_rate = models.IntegerField()
remote_disabled = models.BooleanField()
is_active = models.BooleanField()
is_open = models.BooleanField()
last_update = models.DateTimeField()
auto_rebalance = models.BooleanField(default=False)
ar_amt_target = models.BigIntegerField()
ar_in_target = models.IntegerField(default=100)
ar_out_target = models.IntegerField()
ar_max_cost = models.IntegerField()

def save(self, *args, **kwargs):
if not self.ar_out_target:
Expand All @@ -98,6 +103,13 @@ def save(self, *args, **kwargs):
LocalSettings(key='AR-Target%', value='0.05').save()
amt_setting = 0.05
self.ar_amt_target = int(amt_setting * self.capacity)
if not self.ar_max_cost:
if LocalSettings.objects.filter(key='AR-MaxCost%').exists():
cost_setting = float(LocalSettings.objects.filter(key='AR-MaxCost%')[0].value)
else:
LocalSettings(key='AR-MaxCost%', value='0.65').save()
cost_setting = 0.65
self.ar_max_cost = int(cost_setting * 100)
super(Channels, self).save(*args, **kwargs)

class Meta:
Expand Down
3 changes: 3 additions & 0 deletions gui/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class ChannelSerializer(serializers.HyperlinkedModelSerializer):
is_active = serializers.ReadOnlyField()
is_open = serializers.ReadOnlyField()
num_updates = serializers.ReadOnlyField()
local_disabled = serializers.ReadOnlyField()
remote_disabled = serializers.ReadOnlyField()
last_update = serializers.ReadOnlyField()
class Meta:
model = Channels
exclude = []
Expand Down
37 changes: 32 additions & 5 deletions gui/templates/advanced.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ <h2>Advanced Channel Settings</h2>
<th>Outbound Liquidity</th>
<th width=10%></th>
<th>Inbound Liquidity</th>
<th>Channel State</th>
<th>oRate</th>
<th>oBase</th>
<th>iRate</th>
<th>iBase</th>
<th title="When AR is ENABLED for the channel, the size of the rebalance attempts that should be tried during attempts to refill the channel.">Target Amt</th>
<th title="When AR is ENABLED, the maximum percentage amount of the local fee rate that can be used for the max rebalancing cost.">Max Cost %</th>
<th title="When AR is NOT ENABLED for the channel, keep pushing OUT the channel until its outbound liquidity falls below the oTarget%.">oTarget%</th>
<th title="When AR is ENABLED for the channel, keep pulling IN to the channel until its inbound liquidity falls below the iTarget%.">iTarget%</th>
<th title="When AR is ENABLED it will refill the channel with outbound liquidity.">AR</th>
Expand All @@ -32,24 +34,37 @@ <h2>Advanced Channel Settings</h2>
<td>{{ channel.local_balance|intcomma }} ({{ channel.out_percent }}%)</td>
<td><div class="w3-orange w3-round">{% if channel.in_percent == 0 %}<div class="w3-container w3-round w3-blue" style="height:16px;width:100%"></div>{% elif channel.out_percent == 0 %}<div class="w3-container w3-round w3-orange" style="height:16px;width:100%"></div>{% else %}<div class="w3-container w3-round w3-blue" style="height:16px;width:{{ channel.out_percent }}%"></div>{% endif %}</div></td>
<td>{{ channel.remote_balance|intcomma }} ({{ channel.in_percent }}%)</td>
<td>
<td {% if channel.local_disabled == True %}style="background-color: #fadbd5"{% endif %}>
{% if channel.is_active == True %}
<form action="/update_channel/" method="post">
{% csrf_token %}
<input type="submit" value="{% if channel.local_disabled == False %}Disable{% else %}Enable{% endif %}">
<input type="hidden" name="chan_id" value="{{ channel.chan_id }}">
<input type="hidden" name="update_target" value="7">
<input type="hidden" name="target" value="{% if channel.local_disabled == False %}0{% else %}1{% endif %}">
</form>
{% else %}
---
{% endif %}
</td>
<td {% if channel.local_disabled == True %}style="background-color: #fadbd5"{% endif %}>
<form action="/update_channel/" method="post">
{% csrf_token %}
<input style="text-align:center" id="target" type="number" min="0" max="100000" name="target" value="{{ channel.local_fee_rate }}">
<input type="hidden" name="chan_id" value="{{ channel.chan_id }}">
<input type="hidden" name="update_target" value="1">
</form>
</td>
<td>
<td {% if channel.local_disabled == True %}style="background-color: #fadbd5"{% endif %}>
<form action="/update_channel/" method="post">
{% csrf_token %}
<input style="text-align:center" id="target" type="number" min="0" max="100000" name="target" value="{{ channel.local_base_fee }}">
<input type="hidden" name="chan_id" value="{{ channel.chan_id }}">
<input type="hidden" name="update_target" value="0">
</form>
</td>
<td>{{ channel.remote_fee_rate|intcomma }}</td>
<td>{{ channel.remote_base_fee|intcomma }}</td>
<td title="Fee Ratio: {{ channel.fee_ratio }}%" {% if channel.remote_disabled == True %}style="background-color: #fadbd5"{% endif %}>{{ channel.remote_fee_rate|intcomma }}</td>
<td {% if channel.remote_disabled == True %}style="background-color: #fadbd5"{% endif %}>{{ channel.remote_base_fee|intcomma }}</td>
<td>
<form action="/update_channel/" method="post">
{% csrf_token %}
Expand All @@ -58,6 +73,14 @@ <h2>Advanced Channel Settings</h2>
<input type="hidden" name="update_target" value="2">
</form>
</td>
<td>
<form action="/update_channel/" method="post">
{% csrf_token %}
<input style="text-align:center" id="target" type="number" min="0" max="100" name="target" value="{{ channel.ar_max_cost }}">
<input type="hidden" name="chan_id" value="{{ channel.chan_id }}">
<input type="hidden" name="update_target" value="6">
</form>
</td>
<td {% if channel.auto_rebalance == False %}style="background-color: #80ced6"{% else %}style="background-color: #f18973"{% endif %}>
<form action="/update_channel/" method="post">
{% csrf_token %}
Expand All @@ -83,7 +106,7 @@ <h2>Advanced Channel Settings</h2>
<input type="hidden" name="target" value="0">
</form>
</td>
<td>{{ channel.is_active }}</td>
<td title="{% if channel.is_active == True %}Uptime: {{ channel.last_update|naturaltime|slice:":-4" }}{% else %}Downtime: {{ channel.last_update|naturaltime|slice:":-4" }}{% endif %}">{{ channel.is_active }}</td>
</tr>
{% endfor %}
</table>
Expand Down Expand Up @@ -115,6 +138,10 @@ <h2>Update Local Settings</h2>
<input style="text-align:center" id="value" type="number" min="0" max="60" name="value" value="{{ settings.value }}">
{% elif settings.key == 'AR-MaxFeeRate' %}
<input style="text-align:center" id="value" type="number" min="0" max="2500" name="value" value="{{ settings.value }}">
{% elif settings.key == 'LND-CleanPayments' %}
<input style="text-align:center" id="value" type="number" min="0" max="1" name="value" value="{{ settings.value }}">
{% elif settings.key == 'LND-RetentionDays' %}
<input style="text-align:center" id="value" type="number" min="0" max="1000" name="value" value="{{ settings.value }}">
{% elif settings.key|slice:":3" == 'AR-' %}
<input style="text-align:center" id="value" type="number" min="0" max="1" name="value" value="{{ settings.value }}">
{% else %}
Expand Down
10 changes: 5 additions & 5 deletions gui/templates/balances.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ <h2>Balances</h2>
<th width=40%>Outpoint</th>
<th>Confirmations</th>
</tr>
{% for uxto in utxos %}
{% for utxo in utxos %}
<tr>
<td><a href="{{ network_links }}/{{ network }}address/{{ uxto.address }}" target="_blank">{{ uxto.address }}</a></td>
<td>{{ uxto.amount_sat|intcomma }}</td>
<td><a href="{{ network_links }}/{{ network }}tx/{{ uxto.outpoint.txid_str }}" target="_blank">{{ uxto.outpoint.txid_str }}</a></td>
<td>{{ uxto.confirmations|intcomma }}</td>
<td><a href="{{ network_links }}/{{ network }}address/{{ utxo.address }}" target="_blank">{{ utxo.address }}</a></td>
<td>{{ utxo.amount_sat|intcomma }}</td>
<td><a href="{{ network_links }}/{{ network }}tx/{{ utxo.outpoint.txid_str }}" target="_blank">{{ utxo.outpoint.txid_str }}</a></td>
<td>{{ utxo.confirmations|intcomma }}</td>
</tr>
{% endfor %}
</table>
Expand Down
2 changes: 1 addition & 1 deletion gui/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ <h1><a href="/">My Lnd Overview</a></h1>
<footer>
<div id="footer">
<div class="w3-container w3-padding-small">
<center>LNDg v1.0.2</center>
<center>LNDg v1.0.3</center>
</div>
</div>
</footer>
Expand Down
6 changes: 3 additions & 3 deletions gui/templates/channels.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ <h2>Channel Performance</h2>
<th></th>
<th></th>
<th></th>
<th colspan="3">7-Day Activity And Revenue </th>
<th colspan="3">30-Day Activity And Revenue </th>
<th colspan="3">7-Day Activity And Revenue | {{ apy_7day }}% APY</th>
<th colspan="3">30-Day Activity And Revenue | {{ apy_30day }}% APY </th>
<th colspan="2">Local Fees</th>
<th colspan="2">Peer Fees</th>
<th colspan="2"> Channel Health</th>
Expand Down Expand Up @@ -49,7 +49,7 @@ <h2>Channel Performance</h2>
<td>{{ channel.local_base_fee|intcomma }}</td>
<td>{{ channel.remote_fee_rate|intcomma }}</td>
<td>{{ channel.remote_base_fee|intcomma }}</td>
<td>{{ channel.num_updates|intcomma }}</td>
<td title="Update Count: {{ channel.num_updates|intcomma }}">{{ channel.updates }}%</td>
<td title="Block Opened: {{ channel.open_block }}">{{ channel.initiator }}</td>
</tr>
{% endfor %}
Expand Down
41 changes: 41 additions & 0 deletions gui/templates/closures.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{% extends "base.html" %}
{% block title %} {{ block.super }} - Closures{% endblock %}
{% block content %}
{% load humanize %}
{% if closures %}
<div class="w3-container w3-padding-small">
<h2>Closures</h2>
<table class="w3-table-all w3-centered w3-hoverable">
<tr>
<th>Channel ID</th>
<th>Capacity</th>
<th width=20%>Closing TXID</th>
<th>Settled Balance</th>
<th>Locked Balance</th>
<th>Close Height</th>
<th>Close Type</th>
<th>Opener</th>
<th>Closer</th>
</tr>
{% for closure in closures %}
<tr>
<td><a href="{{ network_links }}/{{ network }}tx/{{ closure.channel_point|slice:":-2" }}" target="_blank">{{ closure.chan_id }}</a></td>
<td>{{ closure.capacity|intcomma }}</td>
<td><a href="{{ network_links }}/{{ network }}tx/{{ closure.closing_tx_hash }}" target="_blank">{{ closure.closing_tx_hash }}</a></td>
<td>{{ closure.settled_balance|intcomma }}</td>
<td>{{ closure.time_locked_balance|intcomma }}</td>
<td>{{ closure.close_height|intcomma }}</td>
<td>{% if closure.close_type == 0 %}Cooperative{% elif closure.close_type == 1 %}Local Force{% elif closure.close_type == 2 %}Remote Force{% elif closure.close_type == 3 %}Breach{% elif closure.close_type == 4 %}Funding Cancelled{% elif closure.close_type == 5 %}Abandoned{% else %}{{ closure.close_type }}{% endif %}</td>
<td>{% if closure.open_initiator == 0 %}Unknown{% elif closure.open_initiator == 1 %}Local{% elif closure.open_initiator == 2 %}Remote{% elif closure.open_initiator == 3 %}Both{% else %}{{ closure.open_initiator }}{% endif %}</td>
<td>{% if closure.close_initiator == 0 %}Unknown{% elif closure.close_initiator == 1 %}Local{% elif closure.close_initiator == 2 %}Remote{% elif closure.close_initiator == 3 %}Both{% else %}{{ closure.close_initiator }}{% endif %}</td>
</tr>
{% endfor %}
</table>
</div>
{% endif %}
{% if not closures %}
<div class="w3-container w3-padding-small">
<center><h1>No channel closures found!</h1></center>
</div>
{% endif %}
{% endblock %}
Loading

0 comments on commit d3f20ed

Please sign in to comment.