mirror of
https://github.com/RoboSats/robosats.git
synced 2024-12-13 19:06:26 +00:00
Fix invoice payouts. Add onchain summary to accounting days.
This commit is contained in:
parent
5c87c5ad85
commit
43b85d79d4
@ -93,7 +93,7 @@ class LNNode:
|
||||
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}
|
||||
@ -108,7 +108,7 @@ class LNNode:
|
||||
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,
|
||||
@ -208,22 +208,17 @@ class LNNode:
|
||||
metadata=[("macaroon",
|
||||
MACAROON.hex())
|
||||
])
|
||||
print("status here")
|
||||
print(response.state)
|
||||
|
||||
# TODO ERROR HANDLING
|
||||
# Will fail if 'unable to locate invoice'. Happens if invoice expiry
|
||||
# time has passed (but these are 15% padded at the moment). Should catch it
|
||||
# and report back that the invoice has expired (better robustness)
|
||||
if response.state == 0: # OPEN
|
||||
print("STATUS: OPEN")
|
||||
pass
|
||||
if response.state == 1: # SETTLED
|
||||
pass
|
||||
if response.state == 2: # CANCELLED
|
||||
pass
|
||||
if response.state == 3: # ACCEPTED (LOCKED)
|
||||
print("STATUS: ACCEPTED")
|
||||
lnpayment.expiry_height = response.htlcs[0].expiry_height
|
||||
lnpayment.status = LNPayment.Status.LOCKED
|
||||
lnpayment.save()
|
||||
@ -254,7 +249,6 @@ class LNNode:
|
||||
|
||||
try:
|
||||
payreq_decoded = cls.decode_payreq(invoice)
|
||||
print(payreq_decoded)
|
||||
except:
|
||||
payout["context"] = {
|
||||
"bad_invoice": "Does not look like a valid lightning invoice"
|
||||
|
@ -725,7 +725,7 @@ class Logics:
|
||||
concept=LNPayment.Concepts.PAYBUYER,
|
||||
type=LNPayment.Types.NORM,
|
||||
sender=User.objects.get(username=ESCROW_USERNAME),
|
||||
order_paid=
|
||||
order_paid_LN=
|
||||
order, # In case this user has other payouts, update the one related to this order.
|
||||
receiver=user,
|
||||
# if there is a LNPayment matching these above, it updates that one with defaults below.
|
||||
|
@ -87,7 +87,7 @@ def follow_send_payment(hash):
|
||||
timeout_seconds=timeout_seconds,
|
||||
)
|
||||
|
||||
order = lnpayment.order_paid
|
||||
order = lnpayment.order_paid_LN
|
||||
try:
|
||||
for response in LNNode.routerstub.SendPaymentV2(request,
|
||||
metadata=[
|
||||
|
@ -1,5 +1,5 @@
|
||||
from django.contrib import admin
|
||||
from control.models import AccountingDay, AccountingMonth, BalanceLog
|
||||
from control.models import AccountingDay, BalanceLog
|
||||
from import_export.admin import ImportExportModelAdmin
|
||||
|
||||
# Register your models here.
|
||||
@ -17,6 +17,7 @@ class AccountingDayAdmin(ImportExportModelAdmin):
|
||||
"inflow",
|
||||
"outflow",
|
||||
"routing_fees",
|
||||
"mining_fees",
|
||||
"cashflow",
|
||||
"outstanding_earned_rewards",
|
||||
"outstanding_pending_disputes",
|
||||
@ -28,31 +29,6 @@ class AccountingDayAdmin(ImportExportModelAdmin):
|
||||
change_links = ["day"]
|
||||
search_fields = ["day"]
|
||||
|
||||
@admin.register(AccountingMonth)
|
||||
class AccountingMonthAdmin(ImportExportModelAdmin):
|
||||
|
||||
list_display = (
|
||||
"month",
|
||||
"contracted",
|
||||
"num_contracts",
|
||||
"net_settled",
|
||||
"net_paid",
|
||||
"net_balance",
|
||||
"inflow",
|
||||
"outflow",
|
||||
"routing_fees",
|
||||
"cashflow",
|
||||
"outstanding_earned_rewards",
|
||||
"outstanding_pending_disputes",
|
||||
"lifetime_rewards_claimed",
|
||||
"outstanding_earned_rewards",
|
||||
"pending_disputes",
|
||||
"rewards_claimed",
|
||||
)
|
||||
change_links = ["month"]
|
||||
search_fields = ["month"]
|
||||
|
||||
|
||||
@admin.register(BalanceLog)
|
||||
class BalanceLogAdmin(ImportExportModelAdmin):
|
||||
|
||||
|
@ -23,6 +23,8 @@ class AccountingDay(models.Model):
|
||||
outflow = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Total cost in routing fees
|
||||
routing_fees = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Total cost in minig fees
|
||||
mining_fees = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Total inflows minus outflows and routing fees
|
||||
cashflow = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Balance on earned rewards (referral rewards, slashed bonds and solved disputes)
|
||||
@ -38,41 +40,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)
|
||||
|
||||
# Every field is denominated in Sats with (3 decimals for millisats)
|
||||
# Total volume contracted
|
||||
contracted = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Number of contracts
|
||||
num_contracts = models.BigIntegerField(default=0, null=False, blank=False)
|
||||
# Net volume of trading invoices settled (excludes disputes)
|
||||
net_settled = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Net volume of trading invoices paid (excludes rewards and disputes)
|
||||
net_paid = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Sum of net settled and net paid
|
||||
net_balance = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Total volume of invoices settled
|
||||
inflow = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Total volume of invoices paid
|
||||
outflow = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Total cost in routing fees
|
||||
routing_fees = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Total inflows minus outflows and routing fees
|
||||
cashflow = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Balance on earned rewards (referral rewards, slashed bonds and solved disputes)
|
||||
outstanding_earned_rewards = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Balance on pending disputes (not resolved yet)
|
||||
outstanding_pending_disputes = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Rewards claimed lifetime
|
||||
lifetime_rewards_claimed = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Balance change from last day on earned rewards (referral rewards, slashed bonds and solved disputes)
|
||||
earned_rewards = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Balance change on pending disputes (not resolved yet)
|
||||
pending_disputes = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
# Rewards claimed on day
|
||||
rewards_claimed = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||
|
||||
class BalanceLog(models.Model):
|
||||
|
||||
def get_total():
|
||||
|
@ -6,7 +6,7 @@ def do_accounting():
|
||||
Does all accounting from the beginning of time
|
||||
'''
|
||||
|
||||
from api.models import Order, LNPayment, Profile, MarketTick
|
||||
from api.models import Order, LNPayment, OnchainPayment, Profile, MarketTick
|
||||
from control.models import AccountingDay
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
@ -36,14 +36,16 @@ def do_accounting():
|
||||
result = {}
|
||||
while day <= today:
|
||||
day_payments = all_payments.filter(created_at__gte=day,created_at__lte=day+timedelta(days=1))
|
||||
day_onchain_payments = OnchainPayment.objects.filter(created_at__gte=day,created_at__lte=day+timedelta(days=1))
|
||||
day_ticks = all_ticks.filter(timestamp__gte=day,timestamp__lte=day+timedelta(days=1))
|
||||
|
||||
# Coarse accounting based on LNpayment objects
|
||||
# Coarse accounting based on LNpayment and OnchainPayment objects
|
||||
contracted = day_ticks.aggregate(Sum('volume'))['volume__sum']
|
||||
num_contracts = day_ticks.count()
|
||||
inflow = day_payments.filter(type=LNPayment.Types.HOLD,status=LNPayment.Status.SETLED).aggregate(Sum('num_satoshis'))['num_satoshis__sum']
|
||||
outflow = day_payments.filter(type=LNPayment.Types.NORM,status=LNPayment.Status.SUCCED).aggregate(Sum('num_satoshis'))['num_satoshis__sum']
|
||||
outflow = day_payments.filter(type=LNPayment.Types.NORM,status=LNPayment.Status.SUCCED).aggregate(Sum('num_satoshis'))['num_satoshis__sum'] + day_onchain_payments.filter(status__in=[OnchainPayment.Status.MEMPO,OnchainPayment.Status.CONFI]).aggregate(Sum('sent_satoshis'))['sent_satoshis__sum']
|
||||
routing_fees = day_payments.filter(type=LNPayment.Types.NORM,status=LNPayment.Status.SUCCED).aggregate(Sum('fee'))['fee__sum']
|
||||
mining_fees = day_onchain_payments.filter(status__in=[OnchainPayment.Status.MEMPO,OnchainPayment.Status.CONFI]).aggregate(Sum('mining_fee_sats'))['mining_fee_sats__sum']
|
||||
rewards_claimed = day_payments.filter(type=LNPayment.Types.NORM,concept=LNPayment.Concepts.WITHREWA,status=LNPayment.Status.SUCCED).aggregate(Sum('num_satoshis'))['num_satoshis__sum']
|
||||
|
||||
contracted = 0 if contracted == None else contracted
|
||||
@ -59,6 +61,7 @@ def do_accounting():
|
||||
inflow = inflow,
|
||||
outflow = outflow,
|
||||
routing_fees = routing_fees,
|
||||
mining_fees = mining_fees,
|
||||
cashflow = inflow - outflow - routing_fees,
|
||||
rewards_claimed = rewards_claimed,
|
||||
)
|
||||
@ -70,9 +73,20 @@ def do_accounting():
|
||||
payouts_paid = 0
|
||||
routing_cost = 0
|
||||
for payout in payouts:
|
||||
escrows_settled += payout.order_paid.trade_escrow.num_satoshis
|
||||
escrows_settled += payout.order_paid_LN.trade_escrow.num_satoshis
|
||||
payouts_paid += payout.num_satoshis
|
||||
routing_cost += payout.fee
|
||||
|
||||
# Same for orders that use onchain payments.
|
||||
payouts_tx = day_onchain_payments.filter(status__in=[OnchainPayment.Status.MEMPO,OnchainPayment.Status.CONFI])
|
||||
escrows_settled = 0
|
||||
payouts_tx_paid = 0
|
||||
mining_cost = 0
|
||||
for payout_tx in payouts_tx:
|
||||
escrows_settled += payout_tx.order_paid_TX.trade_escrow.num_satoshis
|
||||
payouts_tx_paid += payout_tx.sent_satoshis
|
||||
mining_cost += payout_tx.fee
|
||||
|
||||
|
||||
# account for those orders where bonds were lost
|
||||
# + Settled bonds / bond_split
|
||||
@ -117,8 +131,8 @@ def compute_node_balance():
|
||||
'''
|
||||
Queries LND for channel and wallet balance
|
||||
'''
|
||||
|
||||
from control.models import BalanceLog
|
||||
|
||||
BalanceLog.objects.create()
|
||||
|
||||
|
||||
return
|
@ -936,7 +936,7 @@ class TradeBox extends Component {
|
||||
<Grid container spacing={1}>
|
||||
<Grid item xs={12} align="center">
|
||||
<Typography variant="subtitle1">
|
||||
<b>{t("Your invoice looks good!")}</b> {" " + this.stepXofY()}
|
||||
<b>{t("Your info looks good!")}</b> {" " + this.stepXofY()}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} align="center">
|
||||
|
@ -181,6 +181,7 @@
|
||||
"You do not have previous orders":"You do not have previous orders",
|
||||
"Join RoboSats' Subreddit":"Join RoboSats' Subreddit",
|
||||
"RoboSats in Reddit":"RoboSats in Reddit",
|
||||
"Current onchain payout fee":"Current onchain payout fee",
|
||||
|
||||
"ORDER PAGE - OrderPage.js": "Order details page",
|
||||
"Order Box":"Order Box",
|
||||
@ -316,7 +317,7 @@
|
||||
"Submit an invoice for {{amountSats}} Sats":"Submit an invoice for {{amountSats}} Sats",
|
||||
"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.":"The taker is committed! Before letting you send {{amountFiat}} {{currencyCode}}, we want to make sure you are able to receive the BTC. Please provide a valid invoice for {{amountSats}} Satoshis.",
|
||||
"Payout Lightning Invoice":"Payout Lightning Invoice",
|
||||
"Your invoice looks good!":"Your invoice looks good!",
|
||||
"Your info looks good!":"Your info looks good!",
|
||||
"We are waiting for the seller to lock the trade amount.":"We are waiting for the seller to lock the trade amount.",
|
||||
"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).":"Just hang on for a moment. If the seller does not deposit, you will get your bond back automatically. In addition, you will receive a compensation (check the rewards in your profile).",
|
||||
"The trade collateral is locked!":"The trade collateral is locked!",
|
||||
|
@ -181,6 +181,7 @@
|
||||
"You do not have previous orders":"No tienes órdenes previas",
|
||||
"Join RoboSats' Subreddit":"Únete al subreddit de RoboSats",
|
||||
"RoboSats in Reddit":"RoboSats en Reddit",
|
||||
"Current onchain payout fee":"Coste por envio onchain actual",
|
||||
|
||||
"ORDER PAGE - OrderPage.js": "Order details page",
|
||||
"Order Box": "Orden",
|
||||
|
Loading…
Reference in New Issue
Block a user