Maker and taker bonds OK

This commit is contained in:
Reckless_Satoshi 2022-01-06 13:36:22 -08:00
parent 34e05465c2
commit c0d6236dbb
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
3 changed files with 53 additions and 28 deletions

View File

@ -11,6 +11,9 @@ BOND_SIZE = float(config('BOND_SIZE'))
MARKET_PRICE_API = config('MARKET_PRICE_API')
ESCROW_USERNAME = config('ESCROW_USERNAME')
MIN_TRADE = int(config('MIN_TRADE'))
MAX_TRADE = int(config('MAX_TRADE'))
EXP_MAKER_BOND_INVOICE = int(config('EXP_MAKER_BOND_INVOICE'))
EXP_TAKER_BOND_INVOICE = int(config('EXP_TAKER_BOND_INVOICE'))
EXP_TRADE_ESCR_INVOICE = int(config('EXP_TRADE_ESCR_INVOICE'))
@ -32,6 +35,14 @@ class Logics():
return False, {'Bad Request':'You are already taker of an order'}
return True, None
def validate_order_size(order):
'''Checks if order is withing limits at t0'''
if order.t0_satoshis > MAX_TRADE:
return False, {'Bad_request': 'Your order is too big. It is worth {order.t0_satoshis} now, max is {MAX_TRADE}'}
if order.t0_satoshis < MIN_TRADE:
return False, {'Bad_request': 'Your order is too small. It is worth {order.t0_satoshis} now, min is {MIN_TRADE}'}
return True, None
def take(order, user):
order.taker = user
order.status = Order.Status.TAK
@ -135,7 +146,7 @@ class Logics():
return True, {'invoice':order.maker_bond.invoice,'bond_satoshis':order.maker_bond.num_satoshis}
order.satoshis_now = cls.satoshis_now(order)
bond_satoshis = order.satoshis_now * BOND_SIZE
bond_satoshis = int(order.satoshis_now * BOND_SIZE)
description = f'RoboSats - Maker bond for order ID {order.id}. These sats will return to you if you do not cheat!'
# Gen HODL Invoice
@ -160,16 +171,16 @@ class Logics():
def gen_takerbuyer_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.created_at < (timezone.now()+timedelta(minutes=EXP_TAKER_BOND_INVOICE)):
cls.cancel_order(order, user, 3) # State 3, cancel order before taker bond
return False, {'Invoice expired':'You did not confirm taking the order in time.'}
# Return the previous invoice if there was one
if order.taker_bond:
return True, {'invoice':order.taker_bond.invoice,'bond_satoshis':order.taker_bond.num_satoshis}
if order.taker_bond.created_at > (timezone.now()+timedelta(minutes=EXP_TAKER_BOND_INVOICE)):
cls.cancel_order(order, user, 3) # State 3, cancel order before taker bond
return False, {'Invoice expired':'You did not confirm taking the order in time.'}
else:
# Return the previous invoice if there was one
return True, {'invoice':order.taker_bond.invoice,'bond_satoshis':order.taker_bond.num_satoshis}
order.satoshis_now = cls.satoshis_now(order)
bond_satoshis = order.satoshis_now * BOND_SIZE
bond_satoshis = int(order.satoshis_now * BOND_SIZE)
description = f'RoboSats - Taker bond for order ID {order.id}. These sats will return to you if you do not cheat!'
# Gen HODL Invoice
@ -188,4 +199,4 @@ class Logics():
expires_at = expires_at)
order.save()
return True, {'invoice':invoice,'bond_satoshis':bond_satoshis}
return True, {'invoice':invoice,'bond_satoshis': bond_satoshis}

View File

@ -1,5 +1,5 @@
from rest_framework import serializers
from .models import Order, LNPayment
from .models import Order
class ListOrderSerializer(serializers.ModelSerializer):
class Meta:
@ -13,5 +13,5 @@ class MakeOrderSerializer(serializers.ModelSerializer):
class UpdateOrderSerializer(serializers.Serializer):
invoice = serializers.CharField(max_length=300, allow_null=True, allow_blank=True, default=None)
action = serializers.ChoiceField(choices=('take','dispute','cancel','confirm','rate'), allow_null=False)
action = serializers.ChoiceField(choices=('take','update_invoice','dispute','cancel','confirm','rate'), allow_null=False)
rating = serializers.ChoiceField(choices=('1','2','3','4','5'), allow_null=True, allow_blank=True, default=None)

View File

@ -1,7 +1,6 @@
from rest_framework import status, serializers
from rest_framework import status, viewsets
from rest_framework.generics import CreateAPIView, ListAPIView
from rest_framework.views import APIView
from rest_framework import viewsets
from rest_framework.response import Response
from django.contrib.auth import authenticate, login, logout
@ -9,7 +8,7 @@ from django.contrib.auth.models import User
from .serializers import ListOrderSerializer, MakeOrderSerializer, UpdateOrderSerializer
from .models import Order
from .logics import EXP_MAKER_BOND_INVOICE, Logics
from .logics import Logics
from .nick_generator.nick_generator import NickGenerator
from robohash import Robohash
@ -20,7 +19,6 @@ import hashlib
from pathlib import Path
from datetime import timedelta
from django.utils import timezone
from decouple import config
EXP_MAKER_BOND_INVOICE = int(config('EXP_MAKER_BOND_INVOICE'))
@ -47,7 +45,7 @@ class OrderMakerView(CreateAPIView):
is_explicit = serializer.data.get('is_explicit')
valid, context = Logics.validate_already_maker_or_taker(request.user)
if not valid: return Response(context, status=status.HTTP_409_CONFLICT)
if not valid: return Response(context, status.HTTP_409_CONFLICT)
# Creates a new order
order = Order(
@ -58,10 +56,14 @@ class OrderMakerView(CreateAPIView):
premium=premium,
satoshis=satoshis,
is_explicit=is_explicit,
expires_at=timezone.now()+timedelta(minutes=EXP_MAKER_BOND_INVOICE),
expires_at=timezone.now()+timedelta(minutes=EXP_MAKER_BOND_INVOICE), # TODO Move to class method
maker=request.user)
# TODO move to Order class method when new instance is created!
order.last_satoshis = order.t0_satoshis = Logics.satoshis_now(order)
order.last_satoshis = order.t0_satoshis = Logics.satoshis_now(order) # TODO move to Order class method when new instance is created!
valid, context = Logics.validate_order_size(order)
if not valid: return Response(context, status.HTTP_400_BAD_REQUEST)
order.save()
return Response(ListOrderSerializer(order).data, status=status.HTTP_201_CREATED)
@ -112,25 +114,37 @@ class OrderView(viewsets.ViewSet):
# 4) If status is 'waiting for maker bond', 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)
data = {**data, **context} if valid else Response(context, status.HTTP_400_BAD_REQUEST)
if valid:
data = {**data, **context}
else:
return Response(context, status.HTTP_400_BAD_REQUEST)
# 5) If status is 'Public' and user is taker/buyer, reply with a TAKER HODL invoice.
elif order.status == Order.Status.PUB and data['is_taker'] and data['is_buyer']:
# 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)
data = {**data, **context} if valid else Response(context, status.HTTP_400_BAD_REQUEST)
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)
data = {**data, **context} if valid else Response(context, status.HTTP_400_BAD_REQUEST)
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']:
valid, context = Logics.gen_seller_hodl_invoice(order, request.user)
data = {**data, **context} if valid else Response(context, status=status.HTTP_400_BAD_REQUEST)
if valid:
data = {**data, **context}
else:
return Response(context, status.HTTP_400_BAD_REQUEST)
return Response(data, status=status.HTTP_200_OK)
return Response({'Order Not Found':'Invalid Order Id'},status=status.HTTP_404_NOT_FOUND)
return Response(data, status.HTTP_200_OK)
return Response({'Order Not Found':'Invalid Order Id'}, status.HTTP_404_NOT_FOUND)
def take_update_confirm_dispute_cancel(self, request, format=None):
order_id = request.GET.get(self.lookup_url_kwarg)
@ -140,7 +154,7 @@ class OrderView(viewsets.ViewSet):
order = Order.objects.get(id=order_id)
# action is either 1)'take', 2)'confirm', 3)'cancel', 4)'dispute' , 5)'update' (invoice) 6)'rate' (counterparty)
# action is either 1)'take', 2)'confirm', 3)'cancel', 4)'dispute' , 5)'update_invoice' 6)'rate' (counterparty)
action = serializer.data.get('action')
invoice = serializer.data.get('invoice')
rating = serializer.data.get('rating')
@ -232,7 +246,7 @@ class UserView(APIView):
with open(image_path, "wb") as f:
rh.img.save(f, format="png")
# Create new credentials and logsin if nickname is new
# Create new credentials and log in if nickname is new
if len(User.objects.filter(username=nickname)) == 0:
User.objects.create_user(username=nickname, password=token, is_staff=False)
user = authenticate(request, username=nickname, password=token)