Skip to content

Commit

Permalink
v1.8.0 (#350)
Browse files Browse the repository at this point in the history
  • Loading branch information
cryptosharks131 authored Dec 27, 2023
2 parents a01fb26 + 6573691 commit 2a9b876
Show file tree
Hide file tree
Showing 40 changed files with 3,148 additions and 1,339 deletions.
175 changes: 107 additions & 68 deletions README.md

Large diffs are not rendered by default.

24 changes: 16 additions & 8 deletions gui/af.py → af.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def main(channels):
if LocalSettings.objects.filter(key='AF-LowLiqLimit').exists():
lowliq_limit = int(LocalSettings.objects.filter(key='AF-LowLiqLimit').get().value)
else:
LocalSettings(key='AF-LowLiqLimit', value='5').save()
LocalSettings(key='AF-LowLiqLimit', value='15').save()
lowliq_limit = 5
if LocalSettings.objects.filter(key='AF-ExcessLimit').exists():
excess_limit = int(LocalSettings.objects.filter(key='AF-ExcessLimit').get().value)
Expand All @@ -57,12 +57,20 @@ def main(channels):
lowliq_limit = 5
excess_limit = 95
forwards = Forwards.objects.filter(forward_date__gte=filter_7day, amt_out_msat__gte=1000000)
if forwards.exists():
forwards_df_in_7d_sum = DataFrame.from_records(forwards.values('chan_id_in').annotate(amt_out_msat=Sum('amt_out_msat'), fee=Sum('fee')), 'chan_id_in')
forwards_df_out_7d_sum = DataFrame.from_records(forwards.values('chan_id_out').annotate(amt_out_msat=Sum('amt_out_msat'), fee=Sum('fee')), 'chan_id_out')
forwards_1d = forwards.filter(forward_date__gte=filter_1day)
if forwards_1d.exists():
forwards_df_in_1d_sum = DataFrame.from_records(forwards_1d.values('chan_id_in').annotate(amt_out_msat=Sum('amt_out_msat'), fee=Sum('fee')), 'chan_id_in')
if forwards.exists():
forwards_df_in_7d_sum = DataFrame.from_records(forwards.values('chan_id_in').annotate(amt_out_msat=Sum('amt_out_msat'), fee=Sum('fee')), 'chan_id_in')
forwards_df_out_7d_sum = DataFrame.from_records(forwards.values('chan_id_out').annotate(amt_out_msat=Sum('amt_out_msat'), fee=Sum('fee')), 'chan_id_out')
else:
forwards_df_in_7d_sum = DataFrame()
forwards_df_out_7d_sum = DataFrame()
else:
forwards_df_in_1d_sum = DataFrame()
forwards_df_in_7d_sum = DataFrame()
forwards_df_out_7d_sum = DataFrame()
channels_df['amt_routed_in_1day'] = channels_df.apply(lambda row: int(forwards_df_in_1d_sum.loc[row.chan_id].amt_out_msat/1000) if (forwards_df_in_1d_sum.index == row.chan_id).any() else 0, axis=1)
channels_df['amt_routed_in_7day'] = channels_df.apply(lambda row: int(forwards_df_in_7d_sum.loc[row.chan_id].amt_out_msat/1000) if (forwards_df_in_7d_sum.index == row.chan_id).any() else 0, axis=1)
channels_df['amt_routed_out_7day'] = channels_df.apply(lambda row: int(forwards_df_out_7d_sum.loc[row.chan_id].amt_out_msat/1000) if (forwards_df_out_7d_sum.index == row.chan_id).any() else 0, axis=1)
channels_df['net_routed_7day'] = channels_df.apply(lambda row: round((row['amt_routed_out_7day']-row['amt_routed_in_7day'])/row['capacity'], 1), axis=1)
Expand All @@ -79,21 +87,21 @@ def main(channels):
failed_htlc_df = failed_htlc_df[(failed_htlc_df['wire_failure']==15) & (failed_htlc_df['failure_detail']==6) & (failed_htlc_df['amount']>failed_htlc_df['chan_out_liq']+failed_htlc_df['chan_out_pending'])]
lowliq_df['failed_out_1day'] = 0 if failed_htlc_df.empty else lowliq_df.apply(lambda row: len(failed_htlc_df[failed_htlc_df['chan_id_out']==row.chan_id]), axis=1)
# INCREASE IF (failed htlc > threshhold) && (flow in == 0)
lowliq_df['new_rate'] = lowliq_df.apply(lambda row: row['local_fee_rate']+(5*multiplier) if row['failed_out_1day']>failed_htlc_limit and row['amt_routed_in_7day'] == 0 else row['local_fee_rate'], axis=1)
lowliq_df['new_rate'] = lowliq_df.apply(lambda row: row['local_fee_rate']+(5*multiplier) if row['failed_out_1day']>failed_htlc_limit and row['amt_routed_in_1day'] == 0 else row['local_fee_rate'], axis=1)

# Balanced Liquidity
balanced_df = channels_df[(channels_df['out_percent'] > lowliq_limit) & (channels_df['out_percent'] < excess_limit)].copy()
# IF NO FLOW THEN DECREASE FEE AND IF HIGH FLOW THEN SLOWLY INCREASE FEE
balanced_df['new_rate'] = balanced_df.apply(lambda row: row['local_fee_rate']+((2*multiplier)*(1+(row['net_routed_7day']/row['capacity']))) if row['net_routed_7day'] > row['capacity'] else row['local_fee_rate'], axis=1)
balanced_df['new_rate'] = balanced_df.apply(lambda row: row['local_fee_rate']-(3*multiplier) if (row['amt_routed_in_7day']+row['amt_routed_out_7day']) == 0 else row['local_fee_rate'], axis=1)
balanced_df['new_rate'] = balanced_df.apply(lambda row: row['local_fee_rate']+((2*multiplier)*(1+(row['net_routed_7day']/row['capacity']))) if row['net_routed_7day'] > 1 else row['local_fee_rate'], axis=1)
balanced_df['new_rate'] = balanced_df.apply(lambda row: row['local_fee_rate']-(3*multiplier) if (row['amt_routed_in_7day']+row['amt_routed_out_7day']) == 0 else row['new_rate'], axis=1)

# Excess Liquidity
excess_df = channels_df[channels_df['out_percent'] >= excess_limit].copy()
excess_df['revenue_7day'] = excess_df.apply(lambda row: int(forwards_df_out_7d_sum.loc[row.chan_id].fee) if forwards_df_out_7d_sum.empty == False and (forwards_df_out_7d_sum.index == row.chan_id).any() else 0, axis=1)
excess_df['revenue_assist_7day'] = excess_df.apply(lambda row: int(forwards_df_in_7d_sum.loc[row.chan_id].fee) if forwards_df_in_7d_sum.empty == False and (forwards_df_in_7d_sum.index == row.chan_id).any() else 0, axis=1)
# DECREASE IF (assisting channel or stagnant liq)
excess_df['new_rate'] = excess_df.apply(lambda row: row['local_fee_rate']-(5*multiplier) if row['net_routed_7day'] < 0 and row['revenue_assist_7day'] > (row['revenue_7day']*10) else row['local_fee_rate'], axis=1)
excess_df['new_rate'] = excess_df.apply(lambda row: row['local_fee_rate']-(5*multiplier) if (row['amt_routed_in_7day']+row['amt_routed_out_7day']) == 0 else row['local_fee_rate'], axis=1)
excess_df['new_rate'] = excess_df.apply(lambda row: row['local_fee_rate']-(5*multiplier) if (row['amt_routed_in_7day']+row['amt_routed_out_7day']) == 0 else row['new_rate'], axis=1)

#Merge back results
result_df = concat([lowliq_df, balanced_df, excess_df])
Expand Down
23 changes: 23 additions & 0 deletions controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import multiprocessing
import jobs, rebalancer, htlc_stream, p2p

def run_task(task):
task()

def main():
tasks = [jobs.main, rebalancer.main, htlc_stream.main, p2p.main]
print('Controller is starting...')

processes = []
for task in tasks:
process = multiprocessing.Process(target=run_task, args=(task,))
processes.append(process)
process.start()

for process in processes:
process.join()

print('Controller is stopping...')

if __name__ == '__main__':
main()
30 changes: 2 additions & 28 deletions gui/forms.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,14 @@
from django import forms
from .models import Channels

class RebalancerModelChoiceIterator(forms.models.ModelChoiceIterator):
def choice(self, obj):
return (self.field.prepare_value(obj),
(str(obj.chan_id) + ' | ' + obj.alias + ' | ' + "{:,}".format(obj.local_balance) + ' | ' + obj.remote_pubkey))

class RebalancerModelChoiceField(forms.models.ModelMultipleChoiceField):
def _get_choices(self):
if hasattr(self, '_choices'):
return self._choices
return RebalancerModelChoiceIterator(self)
choices = property(_get_choices,
forms.MultipleChoiceField._set_choices)

class ChanPolicyModelChoiceIterator(forms.models.ModelChoiceIterator):
def choice(self, obj):
return (self.field.prepare_value(obj),
(str(obj.chan_id) + ' | ' + obj.alias + ' | ' + str(obj.local_base_fee) + ' | ' + str(obj.local_fee_rate) + ' | ' + str(obj.local_cltv)))

class ChanPolicyModelChoiceField(forms.models.ModelMultipleChoiceField):
def _get_choices(self):
if hasattr(self, '_choices'):
return self._choices
return ChanPolicyModelChoiceIterator(self)
choices = property(_get_choices,
forms.MultipleChoiceField._set_choices)

class OpenChannelForm(forms.Form):
peer_pubkey = forms.CharField(label='peer_pubkey', max_length=66)
local_amt = forms.IntegerField(label='local_amt')
sat_per_byte = forms.IntegerField(label='sat_per_btye')

class CloseChannelForm(forms.Form):
chan_id = forms.CharField(label='chan_id')
target_fee = forms.IntegerField(label='target_fee')
target_fee = forms.IntegerField(label='target_fee', required=False)
force = forms.BooleanField(widget=forms.CheckboxSelectMultiple, required=False)

class ConnectPeerForm(forms.Form):
Expand All @@ -59,7 +33,7 @@ class Meta:
fields = []
value = forms.IntegerField(label='value')
fee_limit = forms.IntegerField(label='fee_limit')
outgoing_chan_ids = RebalancerModelChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Channels.objects.filter(is_open=1, is_active=1).order_by('-local_balance'), required=False)
outgoing_chan_ids = forms.ModelMultipleChoiceField(queryset=Channels.objects.filter(is_open=1, is_active=1), required=False)
last_hop_pubkey = forms.CharField(label='funding_txid', max_length=66, required=False)
duration = forms.IntegerField(label='duration')

Expand Down
7 changes: 4 additions & 3 deletions gui/lnd_deps/lnd_connect.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os, codecs, grpc
from lndg import settings

def creds():
def get_creds():
#Open connection with lnd via grpc
with open(os.path.expanduser(settings.LND_MACAROON_PATH), 'rb') as f:
macaroon_bytes = f.read()
Expand All @@ -15,11 +15,12 @@ def metadata_callback(context, callback):
creds = grpc.composite_channel_credentials(cert_creds, auth_creds)
return creds

creds = get_creds()
def lnd_connect():
return grpc.secure_channel(settings.LND_RPC_SERVER, creds(), options=[('grpc.max_send_message_length', int(settings.LND_MAX_MESSAGE)*1000000), ('grpc.max_receive_message_length', int(settings.LND_MAX_MESSAGE)*1000000),])
return grpc.secure_channel(settings.LND_RPC_SERVER, creds, options=[('grpc.max_send_message_length', int(settings.LND_MAX_MESSAGE)*1000000), ('grpc.max_receive_message_length', int(settings.LND_MAX_MESSAGE)*1000000),])

def async_lnd_connect():
return grpc.aio.secure_channel(settings.LND_RPC_SERVER, creds(), options=[('grpc.max_send_message_length', int(settings.LND_MAX_MESSAGE)*1000000), ('grpc.max_receive_message_length', int(settings.LND_MAX_MESSAGE)*1000000),])
return grpc.aio.secure_channel(settings.LND_RPC_SERVER, creds, options=[('grpc.max_send_message_length', int(settings.LND_MAX_MESSAGE)*1000000), ('grpc.max_receive_message_length', int(settings.LND_MAX_MESSAGE)*1000000),])

def main():
pass
Expand Down
28 changes: 28 additions & 0 deletions gui/migrations/0037_tradesales.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 4.2.6 on 2023-11-08 20:52

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


class Migration(migrations.Migration):

dependencies = [
('gui', '0036_peers'),
]

operations = [
migrations.CreateModel(
name='TradeSales',
fields=[
('id', models.CharField(max_length=64, primary_key=True, serialize=False)),
('creation_date', models.DateTimeField(default=django.utils.timezone.now)),
('expiry', models.DateTimeField(null=True)),
('description', models.CharField(max_length=100)),
('price', models.BigIntegerField()),
('sale_type', models.IntegerField()),
('secret', models.CharField(max_length=1000, null=True)),
('sale_limit', models.IntegerField(null=True)),
('sale_count', models.IntegerField(default=0)),
],
),
]
21 changes: 16 additions & 5 deletions gui/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,15 @@ def save(self, *args, **kwargs):
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
LocalSettings(key='AR-Inbound%', value='90').save()
inbound_setting = 90
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)
else:
LocalSettings(key='AR-Target%', value='5').save()
amt_setting = 5
LocalSettings(key='AR-Target%', value='3').save()
amt_setting = 3
self.ar_amt_target = int((amt_setting/100) * self.capacity)
if not self.ar_max_cost:
if LocalSettings.objects.filter(key='AR-MaxCost%').exists():
Expand Down Expand Up @@ -325,4 +325,15 @@ class HistFailedHTLC(models.Model):
other_count = models.IntegerField()
class Meta:
app_label = 'gui'
unique_together = (('date', 'chan_id_in', 'chan_id_out'),)
unique_together = (('date', 'chan_id_in', 'chan_id_out'),)

class TradeSales(models.Model):
id = models.CharField(max_length=64, primary_key=True)
creation_date = models.DateTimeField(default=timezone.now)
expiry = models.DateTimeField(null=True)
description = models.CharField(max_length=100)
price = models.BigIntegerField()
sale_type = models.IntegerField()
secret = models.CharField(null=True, max_length=1000)
sale_limit = models.IntegerField(null=True)
sale_count = models.IntegerField(default=0)
39 changes: 37 additions & 2 deletions gui/serializers.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
from rest_framework import serializers
from rest_framework.relations import PrimaryKeyRelatedField
from .models import LocalSettings, Payments, PaymentHops, Invoices, Forwards, Channels, Rebalancer, Peers, Onchain, PendingHTLCs, FailedHTLCs, Closures, Resolutions, PeerEvents
from .models import LocalSettings, Payments, PaymentHops, Invoices, Forwards, Channels, Rebalancer, Peers, Onchain, PendingHTLCs, FailedHTLCs, Closures, Resolutions, PeerEvents, TradeSales, Autofees

##FUTURE UPDATE 'exclude' TO 'fields'

class PaymentSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.IntegerField(source='index')
payment_hash = serializers.ReadOnlyField()
class Meta:
model = Payments
exclude = []

class InvoiceSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.IntegerField(source='index')
r_hash = serializers.ReadOnlyField()
creation_date = serializers.ReadOnlyField()
settle_date = serializers.ReadOnlyField()
Expand Down Expand Up @@ -100,6 +102,9 @@ class Meta:
class ConnectPeerSerializer(serializers.Serializer):
peer_id = serializers.CharField(label='peer_pubkey', max_length=200)

class DisconnectPeerSerializer(serializers.Serializer):
peer_id = serializers.CharField(label='peer_pubkey', max_length=66)

class OpenChannelSerializer(serializers.Serializer):
peer_pubkey = serializers.CharField(label='peer_pubkey', max_length=66)
local_amt = serializers.IntegerField(label='local_amt')
Expand All @@ -119,6 +124,27 @@ class BumpFeeSerializer(serializers.Serializer):
class BroadcastTXSerializer(serializers.Serializer):
raw_tx = serializers.CharField(label='raw_tx')

class CreateTradeSerializer(serializers.Serializer):
description = serializers.CharField(max_length=100)
price = serializers.IntegerField()
type = serializers.IntegerField()
secret = serializers.CharField(max_length=100, required=False, default=None)
expiry = serializers.DateTimeField(required=False, default=None)
sale_limit = serializers.IntegerField(required=False, default=None)

class TradeSalesSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.ReadOnlyField()
creation_date = serializers.ReadOnlyField()
sale_type = serializers.ReadOnlyField()
secret = serializers.ReadOnlyField()
sale_count = serializers.ReadOnlyField()
class Meta:
model = TradeSales
exclude = []

class SignMessageSerializer(serializers.Serializer):
message = serializers.CharField(label='message')

class AddInvoiceSerializer(serializers.Serializer):
value = serializers.IntegerField(label='value')

Expand Down Expand Up @@ -190,8 +216,17 @@ def get_out_liq_percent(self, obj):
capacity = Channels.objects.filter(chan_id=obj.chan_id).get().capacity
return int(round((obj.out_liq/capacity)*100, 1))

class FeeLogSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.ReadOnlyField()
class Meta:
model = Autofees
exclude = []

class FailedHTLCSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.ReadOnlyField()
class Meta:
model = FailedHTLCs
exclude = []
exclude = []

class ResetSerializer(serializers.Serializer):
table = serializers.CharField(max_length=20)
2 changes: 1 addition & 1 deletion gui/static/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ async function DELETE(url, {method = 'DELETE'} = {}){
async function call({url, method, data, body, headers = {'Content-Type':'application/json'}}){
if(url.charAt(url.length-1) != '/') url += '/'
if(method != 'GET') headers['X-CSRFToken'] = document.getElementById('api').dataset.token
const result = await fetch(`api/${url}${data ? '?': ''}${new URLSearchParams(data).toString()}`, {method, body: JSON.stringify(body), headers})
const result = await fetch(`/api/${url}${data ? '?': ''}${new URLSearchParams(data).toString()}`, {method, body: JSON.stringify(body), headers})
return result.json()
}

Expand Down
Loading

0 comments on commit 2a9b876

Please sign in to comment.