Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
cryptosharks131 authored Aug 27, 2022
1 parent 53e5858 commit c63c065
Show file tree
Hide file tree
Showing 29 changed files with 1,382 additions and 330 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/on-push-github.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Build on push

permissions:
packages: write

on:
push:
branches:
- master

jobs:
build:
name: Build image
runs-on: ubuntu-22.04

steps:
- name: Checkout project
uses: actions/checkout@v3

- name: Set env variables
run: |
echo "BRANCH=$(echo ${GITHUB_REF#refs/heads/} | sed 's/\//-/g')" >> $GITHUB_ENV
IMAGE_NAME="${GITHUB_REPOSITORY#*/}"
echo "IMAGE_NAME=${IMAGE_NAME//docker-/}" >> $GITHUB_ENV
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v2
id: qemu

- name: Setup Docker buildx action
uses: docker/setup-buildx-action@v2
id: buildx

- name: Run Docker buildx
run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME:latest \
--output "type=registry" ./
47 changes: 47 additions & 0 deletions .github/workflows/on-tag-github.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Build on tag

permissions:
packages: write

on:
push:
tags:
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-*

jobs:
build:
name: Build image
runs-on: ubuntu-22.04

steps:
- name: Checkout project
uses: actions/checkout@v3

- name: Set env variables
run: |
echo "TAG=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
IMAGE_NAME="${GITHUB_REPOSITORY#*/}"
echo "IMAGE_NAME=${IMAGE_NAME//docker-/}" >> $GITHUB_ENV
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v2
id: qemu

- name: Setup Docker buildx action
uses: docker/setup-buildx-action@v2
id: buildx

- name: Run Docker buildx
run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME:$TAG \
--output "type=registry" ./
45 changes: 3 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# LNDg
Lite GUI web interface to analyze lnd data and manage your node with automation.

Start by choosing one of the following installation methods:
[Docker Installation](https://github.com/cryptosharks131/lndg#docker-installation-requires-docker-and-docker-compose-be-installed) | [Umbrel Installation](https://github.com/cryptosharks131/lndg#umbrel-installation) | [Manual Installation](https://github.com/cryptosharks131/lndg#manual-installation)
Start by choosing one of the following installation methods: [Docker Installation](https://github.com/cryptosharks131/lndg#docker-installation-requires-docker-and-docker-compose-be-installed) | [Manual Installation](https://github.com/cryptosharks131/lndg#manual-installation)

LNDg can also be found directly on popular apps like Umbrel and Citadel with a 1-click install from the GUI.

## Docker Installation (requires docker and docker-compose be installed)
### Build and deploy
Expand Down Expand Up @@ -37,46 +38,6 @@ docker-compose up -d
docker system prune -f
```

## Manual Umbrel Installation (now available directly from the Umbrel app store)

### Build and deploy
1. Log into your umbrel via ssh
2. Clone respository `git clone https://github.com/cryptosharks131/lndg.git`
3. Change directory `cd lndg`
4. Copy and replace the contents of the `docker-compose.yaml` with the below: `nano docker-compose.yaml`
```
services:
lndg:
build: .
volumes:
- /home/umbrel/umbrel/lnd:/root/.lnd:ro
- /home/umbrel/lndg/data:/lndg/data:rw
command:
- sh
- -c
- python initialize.py -net 'mainnet' -server '10.21.21.9:10009' -d && supervisord && python manage.py runserver 0.0.0.0:8000
ports:
- 8889:8000
networks:
default:
external: true
name: umbrel_main_network
```
5. Deploy your docker image: `docker-compose up -d`
6. You can now access LNDg via your browser on port 8889: `http://umbrel.local:8889`
7. Open and copy the password from output file: `nano data/lndg-admin.txt`
8. Use the password from the output file and the username `lndg-admin` to login

### Updating
```
docker-compose down
docker-compose build --no-cache
docker-compose up -d
# OPTIONAL: remove unused builds and objects
docker system prune -f
```

## Manual Installation
### Step 1 - Install lndg
1. Clone respository `git clone https://github.com/cryptosharks131/lndg.git`
Expand Down
12 changes: 11 additions & 1 deletion gui/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,13 @@ class AutoRebalanceForm(forms.Form):
target_time = forms.IntegerField(label='target_time', required=False)
fee_rate = forms.IntegerField(label='fee_rate', required=False)
outbound_percent = forms.FloatField(label='outbound_percent', required=False)
inbound_percent = forms.FloatField(label='inbound_percent', required=False)
max_cost = forms.FloatField(label='max_cost', required=False)
variance = forms.IntegerField(label='variance', required=False)
wait_period = forms.IntegerField(label='wait_period', required=False)
autopilot = forms.IntegerField(label='autopilot', required=False)
autopilotdays = forms.IntegerField(label='autopilotdays', required=False)
targetallchannels = forms.BooleanField(widget=forms.CheckboxSelectMultiple, required=False)

updates_channel_codes = [
(0, 'base_fee'),
Expand All @@ -96,13 +99,20 @@ class AutoRebalanceForm(forms.Form):
(7, 'channel_state'),
(8, 'auto_fees'),
(9, 'cltv'),
(10, 'closing_costs'),
]

class UpdateChannel(forms.Form):
chan_id = forms.IntegerField(label='chan_id')
target = forms.IntegerField(label='target')
update_target = forms.ChoiceField(label='update_target', choices=updates_channel_codes)

class UpdatePending(forms.Form):
funding_txid = forms.CharField(label='funding_txid', max_length=64)
output_index = forms.IntegerField(label='output_index')
target = forms.IntegerField(label='target')
update_target = forms.ChoiceField(label='update_target', choices=updates_channel_codes)

class UpdateSetting(forms.Form):
key = forms.CharField(label='setting', max_length=20)
value = forms.CharField(label='value', max_length=50)
Expand All @@ -128,4 +138,4 @@ class BatchOpenForm(forms.Form):
amt9 = forms.IntegerField(label='amt9', required=False)
pubkey10 = forms.CharField(label='pubkey10', max_length=66, required=False)
amt10 = forms.IntegerField(label='amt10', required=False)
fee_rate = forms.IntegerField(label='fee_rate')
fee_rate = forms.IntegerField(label='fee_rate')
70 changes: 70 additions & 0 deletions gui/migrations/0030_auto_20220722_0912.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Generated by Django 3.2.7 on 2022-07-21 05:57

from django.db import migrations, models
from requests import get
from lndg.settings import LND_NETWORK

def update_close_fees(apps, schedma_editor):
channels = apps.get_model('gui', 'channels')
closures = apps.get_model('gui', 'closures')
resolutions = apps.get_model('gui', 'resolutions')
settings = apps.get_model('gui', 'localsettings')
def network_links():
if settings.objects.filter(key='GUI-NetLinks').exists():
network_links = str(settings.objects.filter(key='GUI-NetLinks')[0].value)
else:
network_links = 'https://mempool.space'
return network_links
def get_tx_fees(txid):
base_url = network_links() + ('/testnet' if LND_NETWORK == 'testnet' else '') + '/api/tx/'
try:
request_data = get(base_url + txid).json()
fee = request_data['fee']
except Exception as e:
print('Error getting closure fees for', txid, '-', str(e))
fee = 0
return fee
try:
for closure in closures.objects.exclude(open_initiator=2, close_type=0):
if channels.objects.filter(chan_id=closure.chan_id).exists():
channel = channels.objects.filter(chan_id=closure.chan_id)[0]
closing_costs = get_tx_fees(closure.closing_tx) if closure.open_initiator == 1 else 0
for resolution in resolutions.objects.filter(chan_id=closure.chan_id).exclude(resolution_type=2):
closing_costs += get_tx_fees(resolution.sweep_txid)
channel.closing_costs = closing_costs
channel.save()
except Exception as e:
print('Migration step failed:', str(e))

def revert_close_fees(apps, schedma_editor):
pass

class Migration(migrations.Migration):

dependencies = [
('gui', '0029_update_percent_vars'),
]

operations = [
migrations.AddField(
model_name='channels',
name='closing_costs',
field=models.IntegerField(default=0),
),
migrations.AddField(
model_name='rebalancer',
name='fees_paid',
field=models.FloatField(default=None, null=True),
),
migrations.AlterField(
model_name='channels',
name='ar_in_target',
field=models.IntegerField(),
),
migrations.AlterField(
model_name='channels',
name='auto_fees',
field=models.BooleanField(),
),
migrations.RunPython(update_close_fees, revert_close_fees),
]
33 changes: 33 additions & 0 deletions gui/migrations/0031_pendingchannels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 3.2.7 on 2022-08-05 11:21

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('gui', '0030_auto_20220722_0912'),
]

operations = [
migrations.CreateModel(
name='PendingChannels',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('funding_txid', models.CharField(max_length=64)),
('output_index', models.IntegerField()),
('local_base_fee', models.IntegerField(default=None, null=True)),
('local_fee_rate', models.IntegerField(default=None, null=True)),
('local_cltv', models.IntegerField(default=None, null=True)),
('auto_rebalance', models.BooleanField(default=None, null=True)),
('ar_amt_target', models.BigIntegerField(default=None, null=True)),
('ar_in_target', models.IntegerField(default=None, null=True)),
('ar_out_target', models.IntegerField(default=None, null=True)),
('ar_max_cost', models.IntegerField(default=None, null=True)),
('auto_fees', models.BooleanField(default=None, null=True)),
],
options={
'unique_together': {('funding_txid', 'output_index')},
},
),
]
38 changes: 35 additions & 3 deletions gui/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,20 +95,35 @@ class Channels(models.Model):
last_update = models.DateTimeField()
auto_rebalance = models.BooleanField(default=False)
ar_amt_target = models.BigIntegerField()
ar_in_target = models.IntegerField(default=100)
ar_in_target = models.IntegerField()
ar_out_target = models.IntegerField()
ar_max_cost = models.IntegerField()
fees_updated = models.DateTimeField(default=timezone.now)
auto_fees = models.BooleanField(default=False)
auto_fees = models.BooleanField()
closing_costs = models.IntegerField(default=0)

def save(self, *args, **kwargs):
if self.auto_fees is None:
if LocalSettings.objects.filter(key='AF-Enabled').exists():
enabled = int(LocalSettings.objects.filter(key='AF-Enabled')[0].value)
else:
LocalSettings(key='AF-Enabled', value='0').save()
enabled = 0
self.auto_fees = False if enabled == 0 else True
if not self.ar_out_target:
if LocalSettings.objects.filter(key='AR-Outbound%').exists():
outbound_setting = int(LocalSettings.objects.filter(key='AR-Outbound%')[0].value)
else:
LocalSettings(key='AR-Outbound%', value='75').save()
outbound_setting = 75
self.ar_out_target = outbound_setting
if not self.ar_in_target:
if LocalSettings.objects.filter(key='AR-Inbound%').exists():
inbound_setting = int(LocalSettings.objects.filter(key='AR-Inbound%')[0].value)
else:
LocalSettings(key='AR-Inbound%', value='100').save()
inbound_setting = 100
self.ar_in_target = inbound_setting
if not self.ar_amt_target:
if LocalSettings.objects.filter(key='AR-Target%').exists():
amt_setting = float(LocalSettings.objects.filter(key='AR-Target%')[0].value)
Expand Down Expand Up @@ -153,6 +168,7 @@ class Rebalancer(models.Model):
status = models.IntegerField(default=0)
payment_hash = models.CharField(max_length=64, null=True, default=None)
manual = models.BooleanField(default=False)
fees_paid = models.FloatField(null=True, default=None)
class Meta:
app_label = 'gui'

Expand Down Expand Up @@ -247,4 +263,20 @@ class Autofees(models.Model):
old_value = models.IntegerField()
new_value = models.IntegerField()
class Meta:
app_label = 'gui'
app_label = 'gui'

class PendingChannels(models.Model):
funding_txid = models.CharField(max_length=64)
output_index = models.IntegerField()
local_base_fee = models.IntegerField(null=True, default=None)
local_fee_rate = models.IntegerField(null=True, default=None)
local_cltv = models.IntegerField(null=True, default=None)
auto_rebalance = models.BooleanField(null=True, default=None)
ar_amt_target = models.BigIntegerField(null=True, default=None)
ar_in_target = models.IntegerField(null=True, default=None)
ar_out_target = models.IntegerField(null=True, default=None)
ar_max_cost = models.IntegerField(null=True, default=None)
auto_fees = models.BooleanField(null=True, default=None)
class Meta:
app_label = 'gui'
unique_together = (('funding_txid', 'output_index'),)
6 changes: 3 additions & 3 deletions gui/templates/advanced.html
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,11 @@ <h2>Update Local Settings</h2>
{% csrf_token %}
{% if settings.key == 'AR-Target%' %}
<input style="text-align:center" id="value" type="number" step="0.1" min="0.1" max="100" name="value" value="{{ settings.value }}">
{% elif settings.key|slice:"-1:" == '%' or settings.key == 'AR-Variance' or settings.key == 'AF-Increment' or settings.key == 'AF-Multiplier' or settings.key == 'AF-FailedHTLCs' or settings.key == 'AR-WaitPeriod'%}
{% elif settings.key|slice:"-1:" == '%' or settings.key == 'AR-Variance' or settings.key == 'AF-Increment' or settings.key == 'AF-Multiplier' or settings.key == 'AF-FailedHTLCs' or settings.key == 'AR-WaitPeriod' or settings.key == 'AR-APDays' %}
<input style="text-align:center" id="value" type="number" min="1" max="100" name="value" value="{{ settings.value }}">
{% elif settings.key == 'AR-Time' %}
<input style="text-align:center" id="value" type="number" min="1" max="60" name="value" value="{{ settings.value }}">
{% elif settings.key == 'AR-MaxFeeRate' or settings.key == 'AF-MaxRate' %}
{% elif settings.key == 'AR-MaxFeeRate' %}
<input style="text-align:center" id="value" type="number" min="1" max="2500" name="value" value="{{ settings.value }}">
{% elif settings.key == 'AF-MaxRate' or settings.key == 'AF-MinRate' %}
<input style="text-align:center" id="value" type="number" min="0" max="5000" name="value" value="{{ settings.value }}">
Expand All @@ -227,4 +227,4 @@ <h2>Update Local Settings</h2>
</table>
</div>
{% endif %}
{% endblock %}
{% endblock %}
Loading

0 comments on commit c63c065

Please sign in to comment.