mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-18 12:11:35 +00:00
Create Balance model and log task
This commit is contained in:
parent
4ac3618fd7
commit
f538d26355
18
.env-sample
18
.env-sample
@ -93,7 +93,7 @@ FIAT_EXCHANGE_DURATION = 24
|
||||
|
||||
# ROUTING
|
||||
# Proportional routing fee limit (fraction of total payout: % / 100)
|
||||
PROPORTIONAL_ROUTING_FEE_LIMIT = 0.0002
|
||||
PROPORTIONAL_ROUTING_FEE_LIMIT = 0.001
|
||||
# Base flat limit fee for routing in Sats (used only when proportional is lower than this)
|
||||
MIN_FLAT_ROUTING_FEE_LIMIT = 10
|
||||
MIN_FLAT_ROUTING_FEE_LIMIT_REWARD = 2
|
||||
@ -101,6 +101,22 @@ MIN_FLAT_ROUTING_FEE_LIMIT_REWARD = 2
|
||||
REWARDS_TIMEOUT_SECONDS = 60
|
||||
PAYOUT_TIMEOUT_SECONDS = 60
|
||||
|
||||
# REVERSE SUBMARINE SWAP PAYOUTS
|
||||
# 4 parameters needed, min/max change and min/max balance points. E.g. If 25% or more of liquidity
|
||||
# is onchain the fee for swap is 2% (minimum), if it is 12% fee is 6%, and for 0% fee is 10%.
|
||||
# Minimum swap fee as fraction (2%)
|
||||
MIN_SWAP_FEE = 0.02
|
||||
# Liquidity split point (LN/onchain) at which we use MIN_SWAP_FEE
|
||||
MIN_SWAP_POINT = 0.25
|
||||
# Maximum swap fee as fraction (~10%)
|
||||
MAX_SWAP_FEE = 0.1
|
||||
# Liquidity split point (LN/onchain) at which we use MAX_SWAP_FEE
|
||||
MAX_SWAP_POINT = 0
|
||||
# Shape of fee to available liquidity curve. Only 'linear' implemented.
|
||||
SWAP_FEE_ = 'linear'
|
||||
# Min amount allowed for Swap
|
||||
MIN_SWAP_AMOUNT = 800000
|
||||
|
||||
# Reward tip. Reward for every finished trade in the referral program (Satoshis)
|
||||
REWARD_TIP = 100
|
||||
# Fraction rewarded to user from the slashed bond of a counterpart.
|
||||
|
@ -1,4 +1,4 @@
|
||||
import grpc, os, hashlib, secrets
|
||||
import grpc, os, hashlib, secrets, ring
|
||||
from . import lightning_pb2 as lnrpc, lightning_pb2_grpc as lightningstub
|
||||
from . import invoices_pb2 as invoicesrpc, invoices_pb2_grpc as invoicesstub
|
||||
from . import router_pb2 as routerrpc, router_pb2_grpc as routerstub
|
||||
@ -8,7 +8,6 @@ from base64 import b64decode
|
||||
|
||||
from datetime import timedelta, datetime
|
||||
from django.utils import timezone
|
||||
|
||||
from api.models import LNPayment
|
||||
|
||||
#######
|
||||
@ -67,6 +66,52 @@ class LNNode:
|
||||
MACAROON.hex())])
|
||||
return response
|
||||
|
||||
@classmethod
|
||||
def estimate_fee(cls, amount_sats, target_conf=2, min_confs=1):
|
||||
"""Returns estimated fee for onchain payouts"""
|
||||
|
||||
# We assume segwit. Use robosats donation address (shortcut so there is no need to have user input)
|
||||
request = lnrpc.EstimateFeeRequest(AddrToAmount={'bc1q3cpp7ww92n6zp04hv40kd3eyy5avgughx6xqnx':amount_sats},
|
||||
target_conf=target_conf,
|
||||
min_confs=min_confs,
|
||||
spend_unconfirmed=False)
|
||||
|
||||
response = cls.lightningstub.EstimateFee(request,
|
||||
metadata=[("macaroon",
|
||||
MACAROON.hex())])
|
||||
|
||||
return {'mining_fee_sats': response.fee_sat, 'mining_fee_rate': response.sat_per_vbyte}
|
||||
|
||||
wallet_balance_cache = {}
|
||||
@ring.dict(wallet_balance_cache, expire=10) # keeps in cache for 10 seconds
|
||||
@classmethod
|
||||
def wallet_balance(cls):
|
||||
"""Returns onchain balance"""
|
||||
request = lnrpc.WalletBalanceRequest()
|
||||
response = cls.lightningstub.WalletBalance(request,
|
||||
metadata=[("macaroon",
|
||||
MACAROON.hex())])
|
||||
print(response)
|
||||
return {'total_balance': response.total_balance,
|
||||
'confirmed_balance': response.confirmed_balance,
|
||||
'unconfirmed_balance': response.unconfirmed_balance}
|
||||
|
||||
channel_balance_cache = {}
|
||||
@ring.dict(channel_balance_cache, expire=10) # keeps in cache for 10 seconds
|
||||
@classmethod
|
||||
def channel_balance(cls):
|
||||
"""Returns channels balance"""
|
||||
request = lnrpc.ChannelBalanceRequest()
|
||||
response = cls.lightningstub.ChannelBalance(request,
|
||||
metadata=[("macaroon",
|
||||
MACAROON.hex())])
|
||||
|
||||
print(response)
|
||||
return {'local_balance': response.local_balance.sat,
|
||||
'remote_balance': response.remote_balance.sat,
|
||||
'unsettled_local_balance': response.unsettled_local_balance.sat,
|
||||
'unsettled_remote_balance': response.unsettled_remote_balance.sat}
|
||||
|
||||
@classmethod
|
||||
def cancel_return_hold_invoice(cls, payment_hash):
|
||||
"""Cancels or returns a hold invoice"""
|
||||
|
@ -1,5 +1,5 @@
|
||||
from django.contrib import admin
|
||||
from control.models import AccountingDay, AccountingMonth, Dispute
|
||||
from control.models import AccountingDay, AccountingMonth, BalanceLog
|
||||
from import_export.admin import ImportExportModelAdmin
|
||||
|
||||
# Register your models here.
|
||||
@ -50,4 +50,35 @@ class AccountingMonthAdmin(ImportExportModelAdmin):
|
||||
"rewards_claimed",
|
||||
)
|
||||
change_links = ["month"]
|
||||
search_fields = ["month"]
|
||||
search_fields = ["month"]
|
||||
|
||||
|
||||
@admin.register(BalanceLog)
|
||||
class BalanceLogAdmin(ImportExportModelAdmin):
|
||||
|
||||
list_display = (
|
||||
"time",
|
||||
"total",
|
||||
"onchain_fraction",
|
||||
"onchain_total",
|
||||
"onchain_confirmed",
|
||||
"onchain_unconfirmed",
|
||||
"ln_local",
|
||||
"ln_remote",
|
||||
"ln_local_unsettled",
|
||||
"ln_remote_unsettled",
|
||||
)
|
||||
readonly_fields = [
|
||||
"time",
|
||||
"total",
|
||||
"onchain_fraction",
|
||||
"onchain_total",
|
||||
"onchain_confirmed",
|
||||
"onchain_unconfirmed",
|
||||
"ln_local",
|
||||
"ln_remote",
|
||||
"ln_local_unsettled",
|
||||
"ln_remote_unsettled",
|
||||
]
|
||||
change_links = ["time"]
|
||||
search_fields = ["time"]
|
@ -1,6 +1,8 @@
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
|
||||
from api.lightning.node import LNNode
|
||||
|
||||
class AccountingDay(models.Model):
|
||||
day = models.DateTimeField(primary_key=True, auto_now=False, auto_now_add=False)
|
||||
|
||||
@ -36,8 +38,6 @@ class AccountingDay(models.Model):
|
||||
# Rewards claimed on day
|
||||
rewards_claimed = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
|
||||
|
||||
|
||||
class AccountingMonth(models.Model):
|
||||
month = models.DateTimeField(primary_key=True, auto_now=False, auto_now_add=False)
|
||||
|
||||
@ -73,5 +73,19 @@ class AccountingMonth(models.Model):
|
||||
# Rewards claimed on day
|
||||
rewards_claimed = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
|
||||
class BalanceLog(models.Model):
|
||||
time = models.DateTimeField(primary_key=True, default=timezone.now)
|
||||
|
||||
# Every field is denominated in Sats
|
||||
total = models.PositiveBigIntegerField(default=lambda : LNNode.wallet_balance()['total_balance'] + LNNode.channel_balance()['local_balance'])
|
||||
onchain_fraction = models.DecimalField(max_digits=5, decimal_places=5, default=lambda : (LNNode.wallet_balance()['total_balance'] + LNNode.channel_balance()['local_balance']) / LNNode.wallet_balance()['total_balance'])
|
||||
onchain_total = models.PositiveBigIntegerField(default=lambda : LNNode.wallet_balance()['total_balance'])
|
||||
onchain_confirmed = models.PositiveBigIntegerField(default=lambda : LNNode.wallet_balance()['confirmed_balance'])
|
||||
onchain_unconfirmed = models.PositiveBigIntegerField(default=lambda : LNNode.wallet_balance()['unconfirmed_balance'])
|
||||
ln_local = models.PositiveBigIntegerField(default=lambda : LNNode.channel_balance()['local_balance'])
|
||||
ln_remote = models.PositiveBigIntegerField(default=lambda : LNNode.channel_balance()['remote_balance'])
|
||||
ln_local_unsettled = models.PositiveBigIntegerField(default=lambda : LNNode.channel_balance()['unsettled_local_balance'])
|
||||
ln_remote_unsettled = models.PositiveBigIntegerField(default=lambda : LNNode.channel_balance()['unsettled_remote_balance'])
|
||||
|
||||
class Dispute(models.Model):
|
||||
pass
|
@ -1,10 +1,4 @@
|
||||
from celery import shared_task
|
||||
from api.models import Order, LNPayment, Profile, MarketTick
|
||||
from control.models import AccountingDay, AccountingMonth
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
from django.db.models import Sum
|
||||
from decouple import config
|
||||
|
||||
@shared_task(name="do_accounting")
|
||||
def do_accounting():
|
||||
@ -12,6 +6,13 @@ def do_accounting():
|
||||
Does all accounting from the beginning of time
|
||||
'''
|
||||
|
||||
from api.models import Order, LNPayment, Profile, MarketTick
|
||||
from control.models import AccountingDay
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
from django.db.models import Sum
|
||||
from decouple import config
|
||||
|
||||
all_payments = LNPayment.objects.all()
|
||||
all_ticks = MarketTick.objects.all()
|
||||
today = timezone.now().date()
|
||||
@ -109,4 +110,15 @@ def do_accounting():
|
||||
result[str(day)]={'contracted':contracted,'inflow':inflow,'outflow':outflow}
|
||||
day = day + timedelta(days=1)
|
||||
|
||||
return result
|
||||
return result
|
||||
|
||||
@shared_task(name="compute_node_balance", ignore_result=True)
|
||||
def compute_node_balance():
|
||||
'''
|
||||
Queries LND for channel and wallet balance
|
||||
'''
|
||||
from control.models import BalanceLog
|
||||
|
||||
BalanceLog.objects.create()
|
||||
|
||||
return
|
@ -55,6 +55,10 @@ app.conf.beat_schedule = {
|
||||
"task": "cache_external_market_prices",
|
||||
"schedule": timedelta(seconds=60),
|
||||
},
|
||||
"compute-node-balance": { # Logs LND channel and wallet balance
|
||||
"task":"compute_node_balance",
|
||||
"schedule": timedelta(minutes=15),
|
||||
}
|
||||
}
|
||||
|
||||
app.conf.timezone = "UTC"
|
||||
|
Loading…
Reference in New Issue
Block a user