Work on order cancel

This commit is contained in:
Reckless_Satoshi 2022-01-06 14:39:59 -08:00
parent c0d6236dbb
commit 31b19ce18c
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
3 changed files with 92 additions and 65 deletions

View File

@ -80,57 +80,81 @@ class Logics():
def update_invoice(cls, order, user, invoice):
is_valid_invoice, num_satoshis, description, payment_hash, expires_at = LNNode.validate_ln_invoice(invoice)
# only user is the buyer and a valid LN invoice
if cls.is_buyer(order, user) and is_valid_invoice:
order.buyer_invoice, _ = LNPayment.objects.update_or_create(
concept = LNPayment.Concepts.PAYBUYER,
type = LNPayment.Types.NORM,
sender = User.objects.get(username=ESCROW_USERNAME),
receiver= user,
# if there is a LNPayment matching these above, it updates that with defaults below.
defaults={
'invoice' : invoice,
'status' : LNPayment.Status.VALIDI,
'num_satoshis' : num_satoshis,
'description' : description,
'payment_hash' : payment_hash,
'expires_at' : expires_at}
)
if not (cls.is_buyer(order, user) or is_valid_invoice):
return False, {'bad_request':'Invalid Lightning Network Invoice. It starts by LNTB...'}
#If the order status was Payment Failed. Move foward to invoice Updated.
if order.status == Order.Status.FAI:
order.status = Order.Status.UPI
order.save()
return True, None
order.buyer_invoice, _ = LNPayment.objects.update_or_create(
concept = LNPayment.Concepts.PAYBUYER,
type = LNPayment.Types.NORM,
sender = User.objects.get(username=ESCROW_USERNAME),
receiver= user,
# if there is a LNPayment matching these above, it updates that one with defaults below.
defaults={
'invoice' : invoice,
'status' : LNPayment.Status.VALIDI,
'num_satoshis' : num_satoshis,
'description' : description,
'payment_hash' : payment_hash,
'expires_at' : expires_at}
)
return False, {'bad_request':'Invalid Lightning Network Invoice. It starts by LNTB...'}
# If the order status is 'Waiting for invoice'. Move forward to 'waiting for invoice'
if order.status == Order.Status.WFE: order.status = Order.Status.CHA
# If the order status is 'Waiting for both'. Move forward to 'waiting for escrow' or to 'chat'
if order.status == Order.Status.WF2:
print(order.trade_escrow)
if order.trade_escrow:
if order.trade_escrow.status == LNPayment.Status.LOCKED:
order.status = Order.Status.CHA
else:
order.status = Order.Status.WFE
# If the order status was Payment Failed. Move forward to invoice Updated.
if order.status == Order.Status.FAI:
order.status = Order.Status.UPI
order.save()
return True, None
@classmethod
def cancel_order(cls, order, user, state):
# 1) When maker cancels before bond
'''The order never shows up on the book and status
changes to cancelled. That's it.'''
'''The order never shows up on the book and order
status becomes "cancelled". That's it.'''
if order.status == Order.Status.WFB and order.maker == user:
order.maker = None
order.status = Order.Status.UCA
order.save()
return True, None
# 2) When maker cancels after bond
'''The order dissapears from book and goes to cancelled.
Maker is charged a small amount of sats, to prevent DDOS
on the LN node and order book'''
# 3) When taker cancels before bond
''' The order goes back to the book as public.
LNPayment "order.taker_bond" is deleted() '''
# 2) When maker cancels after bond
'''The order dissapears from book and goes to cancelled.
Maker is charged a small amount of sats, to prevent DDOS
on the LN node and order book'''
# 4) When taker or maker cancel after bond
'''The order goes into cancelled status if maker cancels.
The order goes into the public book if taker cancels.
In both cases there is a small fee.'''
# 3) When taker cancels before bond
''' The order goes back to the book as public.
LNPayment "order.taker_bond" is deleted() '''
# 4) When taker or maker cancel after bond
'''The order goes into cancelled status if maker cancels.
The order goes into the public book if taker cancels.
In both cases there is a small fee.'''
# 5) When trade collateral has been posted
'''Always goes to cancelled status. Collaboration is needed.
When a user asks for cancel, 'order.is_pending_cancel' goes True.
When the second user asks for cancel. Order is totally cancelled.
Has a small cost for both parties to prevent node DDOS.'''
else:
return False, {'bad_request':'You cannot cancel this order'}
# 5) When trade collateral has been posted
'''Always goes to cancelled status. Collaboration is needed.
When a user asks for cancel, 'order.is_pending_cancel' goes True.
When the second user asks for cancel. Order is totally cancelled.
Has a small cost for both parties to prevent node DDOS.'''
pass
@classmethod
@ -168,7 +192,7 @@ class Logics():
return True, {'invoice':invoice,'bond_satoshis':bond_satoshis}
@classmethod
def gen_takerbuyer_hodl_invoice(cls, order, user):
def gen_taker_hodl_invoice(cls, order, user):
# Do not gen and cancel if a taker invoice is there and older than 2 minutes
if order.taker_bond:

View File

@ -77,12 +77,12 @@ class Order(models.Model):
WFB = 0, 'Waiting for maker bond'
PUB = 1, 'Public'
DEL = 2, 'Deleted'
TAK = 3, 'Waiting for taker bond' # only needed when taker is a buyer
TAK = 3, 'Waiting for taker bond'
UCA = 4, 'Cancelled'
WF2 = 5, 'Waiting for trade collateral and buyer invoice'
WTC = 6, 'Waiting only for seller trade collateral'
WBI = 7, 'Waiting only for buyer invoice'
EXF = 8, 'Sending fiat - In chatroom'
WFE = 6, 'Waiting only for seller trade collateral'
WFI = 7, 'Waiting only for buyer invoice'
CHA = 8, 'Sending fiat - In chatroom'
CCA = 9, 'Collaboratively cancelled'
FSE = 10, 'Fiat sent - In chatroom'
FCO = 11, 'Fiat confirmed'

View File

@ -89,6 +89,12 @@ class OrderView(viewsets.ViewSet):
if order.status == Order.Status.EXP:
return Response({'bad_request':'This order has expired'},status.HTTP_400_BAD_REQUEST)
# 2) If order cancelled
if order.status == Order.Status.UCA:
return Response({'bad_request':'This order has been cancelled by the maker'},status.HTTP_400_BAD_REQUEST)
if order.status == Order.Status.CCA:
return Response({'bad_request':'This order has been cancelled collaborativelly'},status.HTTP_400_BAD_REQUEST)
data = ListOrderSerializer(order).data
# Add booleans if user is maker, taker, partipant, buyer or seller
@ -96,11 +102,11 @@ class OrderView(viewsets.ViewSet):
data['is_taker'] = order.taker == request.user
data['is_participant'] = data['is_maker'] or data['is_taker']
# 2) If not a participant and order is not public, forbid.
# 3) If not a participant and order is not public, forbid.
if not data['is_participant'] and order.status != Order.Status.PUB:
return Response({'bad_request':'Not allowed to see this order'},status.HTTP_403_FORBIDDEN)
# 3) Non participants can view details (but only if PUB)
# 4) Non participants can view details (but only if PUB)
elif not data['is_participant'] and order.status != Order.Status.PUB:
return Response(data, status=status.HTTP_200_OK)
@ -111,7 +117,7 @@ class OrderView(viewsets.ViewSet):
data['taker_nick'] = str(order.taker)
data['status_message'] = Order.Status(order.status).label
# 4) If status is 'waiting for maker bond', reply with a MAKER HODL invoice.
# 5) If status is 'waiting for maker bond' and user is MAKER, reply with a MAKER HODL invoice.
if order.status == Order.Status.WFB and data['is_maker']:
valid, context = Logics.gen_maker_hodl_invoice(order, request.user)
if valid:
@ -119,24 +125,16 @@ class OrderView(viewsets.ViewSet):
else:
return Response(context, status.HTTP_400_BAD_REQUEST)
# 5) If status is 'Taken' and user is taker/buyer, reply with a TAKER HODL invoice.
elif order.status == Order.Status.TAK and data['is_taker'] and data['is_buyer']:
valid, context = Logics.gen_takerbuyer_hodl_invoice(order, request.user)
if valid:
data = {**data, **context}
else:
return Response(context, status.HTTP_400_BAD_REQUEST)
# 6) If status is 'Public' and user is taker/seller, reply with a ESCROW HODL invoice.
elif order.status == Order.Status.PUB and data['is_taker'] and data['is_seller']:
valid, context = Logics.gen_seller_hodl_invoice(order, request.user)
# 6) If status is 'waiting for taker bond' and user is TAKER, reply with a TAKER HODL invoice.
elif order.status == Order.Status.TAK and data['is_taker']:
valid, context = Logics.gen_taker_hodl_invoice(order, request.user)
if valid:
data = {**data, **context}
else:
return Response(context, status.HTTP_400_BAD_REQUEST)
# 7) If status is 'WF2/WTC' and user is maker/seller, reply with an ESCROW HODL invoice.
elif (order.status == Order.Status.WF2 or order.status == Order.Status.WF2) and data['is_maker'] and data['is_seller']:
# 7) If status is 'WF2'or'WTC' and user is Seller, reply with an ESCROW HODL invoice.
elif (order.status == Order.Status.WF2 or order.status == Order.Status.WFE) and data['is_seller']:
valid, context = Logics.gen_seller_hodl_invoice(order, request.user)
if valid:
data = {**data, **context}
@ -147,6 +145,10 @@ class OrderView(viewsets.ViewSet):
return Response({'Order Not Found':'Invalid Order Id'}, status.HTTP_404_NOT_FOUND)
def take_update_confirm_dispute_cancel(self, request, format=None):
'''
Here take place all of the user updates to the order object.
That is: take, confim, cancel, dispute, update_invoice or rate.
'''
order_id = request.GET.get(self.lookup_url_kwarg)
serializer = UpdateOrderSerializer(data=request.data)
@ -169,13 +171,14 @@ class OrderView(viewsets.ViewSet):
else: Response({'bad_request':'This order is not public anymore.'}, status.HTTP_400_BAD_REQUEST)
# 2) If action is update (invoice)
elif action == 'update' and invoice:
updated, context = Logics.update_invoice(order,request.user,invoice)
if not updated: return Response(context,status.HTTP_400_BAD_REQUEST)
elif action == 'update_invoice' and invoice:
valid, context = Logics.update_invoice(order,request.user,invoice)
if not valid: return Response(context,status.HTTP_400_BAD_REQUEST)
# 3) If action is cancel
elif action == 'cancel':
pass
valid, context = Logics.cancel_order(order,request.user,invoice)
if not valid: return Response(context,status.HTTP_400_BAD_REQUEST)
# 4) If action is confirm
elif action == 'confirm':