mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-05 22:10:10 +00:00
Convert order cleaning task into admin command
This commit is contained in:
parent
eddd4674f6
commit
0db73c7c82
@ -113,6 +113,7 @@ class Logics():
|
|||||||
|
|
||||||
elif order.status == Order.Status.WFB:
|
elif order.status == Order.Status.WFB:
|
||||||
order.status = Order.Status.EXP
|
order.status = Order.Status.EXP
|
||||||
|
cls.cancel_bond(order.maker_bond)
|
||||||
order.maker = None
|
order.maker = None
|
||||||
order.taker = None
|
order.taker = None
|
||||||
order.save()
|
order.save()
|
||||||
@ -127,6 +128,7 @@ class Logics():
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
elif order.status == Order.Status.TAK:
|
elif order.status == Order.Status.TAK:
|
||||||
|
cls.cancel_bond(order.taker_bond)
|
||||||
cls.kick_taker(order)
|
cls.kick_taker(order)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -149,6 +151,7 @@ class Logics():
|
|||||||
# If maker is seller, settle the bond and order goes to expired
|
# If maker is seller, settle the bond and order goes to expired
|
||||||
if maker_is_seller:
|
if maker_is_seller:
|
||||||
cls.settle_bond(order.maker_bond)
|
cls.settle_bond(order.maker_bond)
|
||||||
|
cls.return_bond(order.taker_bond)
|
||||||
order.status = Order.Status.EXP
|
order.status = Order.Status.EXP
|
||||||
order.maker = None
|
order.maker = None
|
||||||
order.taker = None
|
order.taker = None
|
||||||
@ -167,19 +170,20 @@ class Logics():
|
|||||||
|
|
||||||
elif order.status == Order.Status.WFI:
|
elif order.status == Order.Status.WFI:
|
||||||
# The trade could happen without a buyer invoice. However, this user
|
# The trade could happen without a buyer invoice. However, this user
|
||||||
# is most likely AFK since he did not submit an invoice; will most
|
# is likely AFK since he did not submit an invoice; will probably
|
||||||
# likely desert the contract as well.
|
# desert the contract as well.
|
||||||
maker_is_buyer = cls.is_buyer(order, order.maker)
|
maker_is_buyer = cls.is_buyer(order, order.maker)
|
||||||
# If maker is buyer, settle the bond and order goes to expired
|
# If maker is buyer, settle the bond and order goes to expired
|
||||||
if maker_is_buyer:
|
if maker_is_buyer:
|
||||||
cls.settle_bond(order.maker_bond)
|
cls.settle_bond(order.maker_bond)
|
||||||
|
cls.return_bond(order.taker_bond)
|
||||||
order.status = Order.Status.EXP
|
order.status = Order.Status.EXP
|
||||||
order.maker = None
|
order.maker = None
|
||||||
order.taker = None
|
order.taker = None
|
||||||
order.save()
|
order.save()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# If maker is seller, settle the taker's bond order goes back to public
|
# If maker is seller settle the taker's bond, order goes back to public
|
||||||
else:
|
else:
|
||||||
cls.settle_bond(order.taker_bond)
|
cls.settle_bond(order.taker_bond)
|
||||||
order.status = Order.Status.PUB
|
order.status = Order.Status.PUB
|
||||||
@ -203,14 +207,13 @@ class Logics():
|
|||||||
profile.penalty_expiration = timezone.now() + timedelta(seconds=PENALTY_TIMEOUT)
|
profile.penalty_expiration = timezone.now() + timedelta(seconds=PENALTY_TIMEOUT)
|
||||||
profile.save()
|
profile.save()
|
||||||
|
|
||||||
# Delete the taker_bond payment request, and make order public again
|
# Make order public again
|
||||||
if LNNode.cancel_return_hold_invoice(order.taker_bond.payment_hash):
|
order.status = Order.Status.PUB
|
||||||
order.status = Order.Status.PUB
|
order.taker = None
|
||||||
order.taker = None
|
order.taker_bond = None
|
||||||
order.taker_bond = None
|
order.expires_at = order.created_at + timedelta(seconds=Order.t_to_expire[Order.Status.PUB])
|
||||||
order.expires_at = order.created_at + timedelta(seconds=Order.t_to_expire[Order.Status.PUB])
|
order.save()
|
||||||
order.save()
|
return True
|
||||||
return True
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def open_dispute(cls, order, user=None):
|
def open_dispute(cls, order, user=None):
|
||||||
@ -369,6 +372,7 @@ class Logics():
|
|||||||
LNPayment "order.taker_bond" is deleted() '''
|
LNPayment "order.taker_bond" is deleted() '''
|
||||||
elif order.status == Order.Status.TAK and order.taker == user:
|
elif order.status == Order.Status.TAK and order.taker == user:
|
||||||
# adds a timeout penalty
|
# adds a timeout penalty
|
||||||
|
cls.cancel_bond(order.taker_bond)
|
||||||
cls.kick_taker(order)
|
cls.kick_taker(order)
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
@ -495,6 +499,7 @@ class Logics():
|
|||||||
|
|
||||||
# Do not gen and kick out the taker if order is older than expiry time
|
# Do not gen and kick out the taker if order is older than expiry time
|
||||||
if order.expires_at < timezone.now():
|
if order.expires_at < timezone.now():
|
||||||
|
cls.cancel_bond(order.taker_bond)
|
||||||
cls.kick_taker(order)
|
cls.kick_taker(order)
|
||||||
return False, {'bad_request':'Invoice expired. You did not confirm taking the order in time.'}
|
return False, {'bad_request':'Invoice expired. You did not confirm taking the order in time.'}
|
||||||
|
|
||||||
@ -615,9 +620,31 @@ class Logics():
|
|||||||
|
|
||||||
def return_bond(bond):
|
def return_bond(bond):
|
||||||
'''returns a bond'''
|
'''returns a bond'''
|
||||||
if LNNode.cancel_return_hold_invoice(bond.payment_hash):
|
if bond == None:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
LNNode.cancel_return_hold_invoice(bond.payment_hash)
|
||||||
bond.status = LNPayment.Status.RETNED
|
bond.status = LNPayment.Status.RETNED
|
||||||
return True
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
if 'invoice already settled' in str(e):
|
||||||
|
bond.status = LNPayment.Status.SETLED
|
||||||
|
return True
|
||||||
|
|
||||||
|
def cancel_bond(bond):
|
||||||
|
'''cancel a bond'''
|
||||||
|
# Same as return bond, but used when the invoice was never accepted
|
||||||
|
if bond == None:
|
||||||
|
return True
|
||||||
|
try:
|
||||||
|
LNNode.cancel_return_hold_invoice(bond.payment_hash)
|
||||||
|
bond.status = LNPayment.Status.CANCEL
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
if 'invoice already settled' in str(e):
|
||||||
|
bond.status = LNPayment.Status.SETLED
|
||||||
|
return True
|
||||||
|
|
||||||
def pay_buyer_invoice(order):
|
def pay_buyer_invoice(order):
|
||||||
''' Pay buyer invoice'''
|
''' Pay buyer invoice'''
|
||||||
|
41
api/management/commands/clean_orders.py
Normal file
41
api/management/commands/clean_orders.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
|
||||||
|
import time
|
||||||
|
from api.models import Order
|
||||||
|
from api.logics import Logics
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'Follows all active hold invoices'
|
||||||
|
|
||||||
|
# def add_arguments(self, parser):
|
||||||
|
# parser.add_argument('debug', nargs='+', type=boolean)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
''' Continuously checks order expiration times for 1 hour. If order
|
||||||
|
has expires, it calls the logics module for expiration handling.'''
|
||||||
|
|
||||||
|
do_nothing = [Order.Status.DEL, Order.Status.UCA,
|
||||||
|
Order.Status.EXP, Order.Status.FSE,
|
||||||
|
Order.Status.DIS, Order.Status.CCA,
|
||||||
|
Order.Status.PAY, Order.Status.SUC,
|
||||||
|
Order.Status.FAI, Order.Status.MLD,
|
||||||
|
Order.Status.TLD]
|
||||||
|
|
||||||
|
while True:
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
queryset = Order.objects.exclude(status__in=do_nothing)
|
||||||
|
queryset = queryset.filter(expires_at__lt=timezone.now()) # expires at lower than now
|
||||||
|
|
||||||
|
debug = {}
|
||||||
|
debug['num_expired_orders'] = len(queryset)
|
||||||
|
debug['expired_orders'] = []
|
||||||
|
|
||||||
|
for idx, order in enumerate(queryset):
|
||||||
|
context = str(order)+ " was "+ Order.Status(order.status).label
|
||||||
|
if Logics.order_expires(order): # Order send to expire here
|
||||||
|
debug['expired_orders'].append({idx:context})
|
||||||
|
|
||||||
|
self.stdout.write(str(timezone.now()))
|
||||||
|
self.stdout.write(str(debug))
|
@ -1,7 +1,6 @@
|
|||||||
from distutils.log import debug
|
|
||||||
from re import L
|
|
||||||
from xmlrpc.client import boolean
|
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
|
||||||
|
from django.utils import timezone
|
||||||
from api.lightning.node import LNNode
|
from api.lightning.node import LNNode
|
||||||
from decouple import config
|
from decouple import config
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
@ -53,9 +52,9 @@ class Command(BaseCommand):
|
|||||||
try:
|
try:
|
||||||
request = LNNode.invoicesrpc.LookupInvoiceMsg(payment_hash=bytes.fromhex(hold_lnpayment.payment_hash))
|
request = LNNode.invoicesrpc.LookupInvoiceMsg(payment_hash=bytes.fromhex(hold_lnpayment.payment_hash))
|
||||||
response = stub.LookupInvoiceV2(request, metadata=[('macaroon', MACAROON.hex())])
|
response = stub.LookupInvoiceV2(request, metadata=[('macaroon', MACAROON.hex())])
|
||||||
|
|
||||||
hold_lnpayment.status = lnd_state_to_lnpayment_status[response.state]
|
hold_lnpayment.status = lnd_state_to_lnpayment_status[response.state]
|
||||||
# If it fails at finding the invoice it has definetely been canceled.
|
|
||||||
|
# If it fails at finding the invoice it has been canceled.
|
||||||
# On RoboSats DB we make a distinction between cancelled and returned (LND does not)
|
# On RoboSats DB we make a distinction between cancelled and returned (LND does not)
|
||||||
except:
|
except:
|
||||||
hold_lnpayment.status = LNPayment.Status.CANCEL
|
hold_lnpayment.status = LNPayment.Status.CANCEL
|
||||||
@ -76,9 +75,10 @@ class Command(BaseCommand):
|
|||||||
'old_status': old_status,
|
'old_status': old_status,
|
||||||
'new_status': new_status,
|
'new_status': new_status,
|
||||||
}})
|
}})
|
||||||
|
|
||||||
debug['time']=time.time()-t0
|
debug['time']=time.time()-t0
|
||||||
|
|
||||||
self.stdout.write(str(debug))
|
self.stdout.write(str(timezone.now())+str(debug))
|
||||||
|
|
||||||
|
|
||||||
|
|
44
api/tasks.py
44
api/tasks.py
@ -30,50 +30,6 @@ def users_cleansing():
|
|||||||
'num_deleted': len(deleted_users),
|
'num_deleted': len(deleted_users),
|
||||||
'deleted_users': deleted_users,
|
'deleted_users': deleted_users,
|
||||||
}
|
}
|
||||||
|
|
||||||
return results
|
|
||||||
|
|
||||||
|
|
||||||
@shared_task(name="orders_expire")
|
|
||||||
def orders_expire(rest_secs):
|
|
||||||
'''
|
|
||||||
Continuously checks order expiration times for 1 hour. If order
|
|
||||||
has expires, it calls the logics module for expiration handling.
|
|
||||||
'''
|
|
||||||
import time
|
|
||||||
from .models import Order
|
|
||||||
from .logics import Logics
|
|
||||||
from datetime import timedelta
|
|
||||||
from django.utils import timezone
|
|
||||||
|
|
||||||
now = timezone.now()
|
|
||||||
end_time = now + timedelta(minutes=60)
|
|
||||||
context = []
|
|
||||||
|
|
||||||
while now < end_time:
|
|
||||||
queryset = Order.objects.exclude(status=Order.Status.EXP).exclude(status=Order.Status.UCA).exclude(status= Order.Status.CCA)
|
|
||||||
queryset = queryset.filter(expires_at__lt=now) # expires at lower than now
|
|
||||||
|
|
||||||
for order in queryset:
|
|
||||||
try: # TODO Fix, it might fail if returning an already returned bond.
|
|
||||||
info = str(order)+ " was "+ Order.Status(order.status).label
|
|
||||||
if Logics.order_expires(order): # Order send to expire here
|
|
||||||
context.append(info)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Allow for some thread rest.
|
|
||||||
time.sleep(rest_secs)
|
|
||||||
|
|
||||||
# Update 'now' for a new loop
|
|
||||||
now = timezone.now()
|
|
||||||
|
|
||||||
results = {
|
|
||||||
'num_expired': len(context),
|
|
||||||
'expired_orders_context': context,
|
|
||||||
'rest_param': rest_secs,
|
|
||||||
}
|
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@shared_task(name='follow_send_payment')
|
@shared_task(name='follow_send_payment')
|
||||||
|
@ -5,7 +5,7 @@ import numpy as np
|
|||||||
|
|
||||||
market_cache = {}
|
market_cache = {}
|
||||||
|
|
||||||
# @ring.dict(market_cache, expire=5) #keeps in cache for 5 seconds
|
@ring.dict(market_cache, expire=5) #keeps in cache for 5 seconds
|
||||||
def get_exchange_rates(currencies):
|
def get_exchange_rates(currencies):
|
||||||
'''
|
'''
|
||||||
Params: list of currency codes.
|
Params: list of currency codes.
|
||||||
|
@ -39,11 +39,6 @@ app.conf.beat_schedule = {
|
|||||||
'task': 'cache_external_market_prices',
|
'task': 'cache_external_market_prices',
|
||||||
'schedule': timedelta(seconds=60),
|
'schedule': timedelta(seconds=60),
|
||||||
},
|
},
|
||||||
'orders_expire': { # Continuous order expire removal (1 hour long process, every hour reports results)
|
|
||||||
'task': 'orders_expire',
|
|
||||||
'schedule': timedelta(hours=1),
|
|
||||||
'args': [5], # Rest between checks (secs)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.conf.timezone = 'UTC'
|
app.conf.timezone = 'UTC'
|
Loading…
Reference in New Issue
Block a user