Add more logics bareframes

This commit is contained in:
Reckless_Satoshi 2022-01-06 12:33:40 -08:00
parent a1771ae5ea
commit 34e05465c2
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
8 changed files with 173 additions and 117 deletions

View File

@ -30,7 +30,7 @@ class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin):
@admin.register(LNPayment) @admin.register(LNPayment)
class LNPaymentAdmin(AdminChangeLinksMixin, admin.ModelAdmin): class LNPaymentAdmin(AdminChangeLinksMixin, admin.ModelAdmin):
list_display = ('id','concept','status','num_satoshis','type','invoice','preimage','expires_at','sender_link','receiver_link') list_display = ('id','concept','status','num_satoshis','type','invoice','expires_at','sender_link','receiver_link')
list_display_links = ('id','concept') list_display_links = ('id','concept')
change_links = ('sender','receiver') change_links = ('sender','receiver')

View File

@ -13,7 +13,7 @@ class LNNode():
Place holder functions to interact with Lightning Node Place holder functions to interact with Lightning Node
''' '''
def gen_hodl_invoice(num_satoshis, description): def gen_hodl_invoice(num_satoshis, description, expiry):
'''Generates hodl invoice to publish an order''' '''Generates hodl invoice to publish an order'''
# TODO # TODO
invoice = ''.join(random.choices(string.ascii_uppercase + string.digits, k=80)) #FIX invoice = ''.join(random.choices(string.ascii_uppercase + string.digits, k=80)) #FIX

View File

@ -11,6 +11,12 @@ BOND_SIZE = float(config('BOND_SIZE'))
MARKET_PRICE_API = config('MARKET_PRICE_API') MARKET_PRICE_API = config('MARKET_PRICE_API')
ESCROW_USERNAME = config('ESCROW_USERNAME') ESCROW_USERNAME = config('ESCROW_USERNAME')
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'))
BOND_EXPIRY = int(config('BOND_EXPIRY'))
ESCROW_EXPIRY = int(config('ESCROW_EXPIRY'))
class Logics(): class Logics():
@ -46,12 +52,10 @@ class Logics():
if order.is_explicit: if order.is_explicit:
satoshis_now = order.satoshis satoshis_now = order.satoshis
else: else:
# TODO Add fallback Public APIs and error handling
market_prices = requests.get(MARKET_PRICE_API).json() market_prices = requests.get(MARKET_PRICE_API).json()
print(market_prices)
exchange_rate = float(market_prices[Order.Currencies(order.currency).label]['last']) exchange_rate = float(market_prices[Order.Currencies(order.currency).label]['last'])
print(exchange_rate)
satoshis_now = ((float(order.amount) * 1+float(order.premium)) / exchange_rate) * 100*1000*1000 satoshis_now = ((float(order.amount) * 1+float(order.premium)) / exchange_rate) * 100*1000*1000
print(satoshis_now)
return satoshis_now return satoshis_now
@ -85,25 +89,57 @@ class Logics():
if order.status == Order.Status.FAI: if order.status == Order.Status.FAI:
order.status = Order.Status.UPI order.status = Order.Status.UPI
order.save() order.save()
return True return True, None
return False, {'bad_request':'Invalid Lightning Network Invoice. It starts by LNTB...'}
@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.'''
# 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() '''
# 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.'''
pass
return False
@classmethod @classmethod
def gen_maker_hodl_invoice(cls, order, user): def gen_maker_hodl_invoice(cls, order, user):
# Do not and delete if order is more than 5 minutes old # Do not gen and delete if order is more than 5 minutes old
if order.expires_at < timezone.now(): if order.expires_at < timezone.now():
cls.order_expires(order) cls.order_expires(order)
return False, {'Order expired':'cannot generate a bond invoice for an expired order. Make a new one.'} return False, {'Order expired':'cannot generate a bond invoice for an expired order. Make a new one.'}
# Return the previous invoice if there was one
if order.maker_bond: if order.maker_bond:
return True, {'invoice':order.maker_bond.invoice,'bond_satoshis':order.maker_bond.num_satoshis} return True, {'invoice':order.maker_bond.invoice,'bond_satoshis':order.maker_bond.num_satoshis}
order.satoshis_now = cls.satoshis_now(order) order.satoshis_now = cls.satoshis_now(order)
bond_satoshis = order.satoshis_now * BOND_SIZE bond_satoshis = order.satoshis_now * BOND_SIZE
description = f'Robosats maker bond for order ID {order.id}. Will return to you if you do not cheat!' description = f'RoboSats - Maker bond for order ID {order.id}. These sats will return to you if you do not cheat!'
invoice, payment_hash, expires_at = LNNode.gen_hodl_invoice(num_satoshis = bond_satoshis, description=description)
# Gen HODL Invoice
invoice, payment_hash, expires_at = LNNode.gen_hodl_invoice(bond_satoshis, description, BOND_EXPIRY*3600)
order.maker_bond = LNPayment.objects.create( order.maker_bond = LNPayment.objects.create(
concept = LNPayment.Concepts.MAKEBOND, concept = LNPayment.Concepts.MAKEBOND,
@ -115,30 +151,32 @@ class Logics():
num_satoshis = bond_satoshis, num_satoshis = bond_satoshis,
description = description, description = description,
payment_hash = payment_hash, payment_hash = payment_hash,
expires_at = expires_at, expires_at = expires_at)
)
order.save() order.save()
return True, {'invoice':invoice,'bond_satoshis':bond_satoshis} return True, {'invoice':invoice,'bond_satoshis':bond_satoshis}
@classmethod @classmethod
def gen_taker_buyer_hodl_invoice(cls, order, user): def gen_takerbuyer_hodl_invoice(cls, order, user):
# Do not and delete if order is more than 5 minutes old # Do not gen and cancel if a taker invoice is there and older than 2 minutes
if order.expires_at < timezone.now(): if order.taker_bond.created_at < (timezone.now()+timedelta(minutes=EXP_TAKER_BOND_INVOICE)):
cls.order_expires(order) cls.cancel_order(order, user, 3) # State 3, cancel order before taker bond
return False, {'Order expired':'cannot generate a bond invoice for an expired order. Make a new one.'} return False, {'Invoice expired':'You did not confirm taking the order in time.'}
if order.maker_bond: # Return the previous invoice if there was one
return True, {'invoice':order.maker_bond.invoice,'bond_satoshis':order.maker_bond.num_satoshis} if order.taker_bond:
return True, {'invoice':order.taker_bond.invoice,'bond_satoshis':order.taker_bond.num_satoshis}
order.satoshis_now = cls.satoshis_now(order) order.satoshis_now = cls.satoshis_now(order)
bond_satoshis = order.satoshis_now * BOND_SIZE bond_satoshis = order.satoshis_now * BOND_SIZE
description = f'Robosats maker bond for order ID {order.id}. Will return to you if you do not cheat!' description = f'RoboSats - Taker bond for order ID {order.id}. These sats will return to you if you do not cheat!'
invoice, payment_hash, expires_at = LNNode.gen_hodl_invoice(num_satoshis = bond_satoshis, description=description)
# Gen HODL Invoice
invoice, payment_hash, expires_at = LNNode.gen_hodl_invoice(bond_satoshis, description, BOND_EXPIRY*3600)
order.maker_bond = LNPayment.objects.create( order.taker_bond = LNPayment.objects.create(
concept = LNPayment.Concepts.MAKEBOND, concept = LNPayment.Concepts.TAKEBOND,
type = LNPayment.Types.HODL, type = LNPayment.Types.HODL,
sender = user, sender = user,
receiver = User.objects.get(username=ESCROW_USERNAME), receiver = User.objects.get(username=ESCROW_USERNAME),
@ -147,8 +185,7 @@ class Logics():
num_satoshis = bond_satoshis, num_satoshis = bond_satoshis,
description = description, description = description,
payment_hash = payment_hash, payment_hash = payment_hash,
expires_at = expires_at, expires_at = expires_at)
)
order.save() order.save()
return True, {'invoice':invoice,'bond_satoshis':bond_satoshis} return True, {'invoice':invoice,'bond_satoshis':bond_satoshis}

View File

@ -49,7 +49,6 @@ class LNPayment(models.Model):
# payment info # payment info
invoice = models.CharField(max_length=300, unique=False, null=True, default=None, blank=True) invoice = models.CharField(max_length=300, unique=False, null=True, default=None, blank=True)
payment_hash = models.CharField(max_length=300, unique=False, null=True, default=None, blank=True) payment_hash = models.CharField(max_length=300, unique=False, null=True, default=None, blank=True)
preimage = models.CharField(max_length=300, unique=False, null=True, default=None, blank=True)
description = models.CharField(max_length=300, unique=False, null=True, default=None, blank=True) description = models.CharField(max_length=300, unique=False, null=True, default=None, blank=True)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
expires_at = models.DateTimeField() expires_at = models.DateTimeField()
@ -79,22 +78,21 @@ class Order(models.Model):
PUB = 1, 'Public' PUB = 1, 'Public'
DEL = 2, 'Deleted' DEL = 2, 'Deleted'
TAK = 3, 'Waiting for taker bond' # only needed when taker is a buyer TAK = 3, 'Waiting for taker bond' # only needed when taker is a buyer
UCA = 4, 'Unilaterally cancelled' UCA = 4, 'Cancelled'
RET = 5, 'Returned to order book' # Probably same as 1 in most cases. WF2 = 5, 'Waiting for trade collateral and buyer invoice'
WF2 = 6, 'Waiting for trade collateral and buyer invoice' WTC = 6, 'Waiting only for seller trade collateral'
WTC = 7, 'Waiting only for trade collateral' WBI = 7, 'Waiting only for buyer invoice'
WBI = 8, 'Waiting only for buyer invoice' EXF = 8, 'Sending fiat - In chatroom'
EXF = 9, 'Exchanging fiat / In chat' CCA = 9, 'Collaboratively cancelled'
CCA = 10, 'Collaboratively cancelled' FSE = 10, 'Fiat sent - In chatroom'
FSE = 11, 'Fiat sent' FCO = 11, 'Fiat confirmed'
FCO = 12, 'Fiat confirmed' SUC = 12, 'Sucessfully settled'
SUC = 13, 'Sucessfully settled' FAI = 13, 'Failed lightning network routing'
FAI = 14, 'Failed lightning network routing' UPI = 14, 'Updated invoice'
UPI = 15, 'Updated invoice' DIS = 15, 'In dispute'
DIS = 16, 'In dispute' MLD = 16, 'Maker lost dispute'
MLD = 17, 'Maker lost dispute' TLD = 17, 'Taker lost dispute'
TLD = 18, 'Taker lost dispute' EXP = 18, 'Expired'
EXP = 19, 'Expired'
# order info # order info
status = models.PositiveSmallIntegerField(choices=Status.choices, null=False, default=Status.WFB) status = models.PositiveSmallIntegerField(choices=Status.choices, null=False, default=Status.WFB)
@ -117,11 +115,11 @@ class Order(models.Model):
t0_satoshis = models.PositiveBigIntegerField(null=True, validators=[MinValueValidator(MIN_TRADE), MaxValueValidator(MAX_TRADE)], blank=True) # sats at creation t0_satoshis = models.PositiveBigIntegerField(null=True, validators=[MinValueValidator(MIN_TRADE), MaxValueValidator(MAX_TRADE)], blank=True) # sats at creation
last_satoshis = models.PositiveBigIntegerField(null=True, validators=[MinValueValidator(0), MaxValueValidator(MAX_TRADE*2)], blank=True) # sats last time checked. Weird if 2* trade max... last_satoshis = models.PositiveBigIntegerField(null=True, validators=[MinValueValidator(0), MaxValueValidator(MAX_TRADE*2)], blank=True) # sats last time checked. Weird if 2* trade max...
# order participants # order participants
maker = models.ForeignKey(User, related_name='maker', on_delete=models.CASCADE, null=True, default=None) # unique = True, a maker can only make one order maker = models.ForeignKey(User, related_name='maker', on_delete=models.CASCADE, null=True, default=None) # unique = True, a maker can only make one order
taker = models.ForeignKey(User, related_name='taker', on_delete=models.SET_NULL, null=True, default=None, blank=True) # unique = True, a taker can only take one order taker = models.ForeignKey(User, related_name='taker', on_delete=models.SET_NULL, null=True, default=None, blank=True) # unique = True, a taker can only take one order
is_pending_cancel = models.BooleanField(default=False, null=False) # When collaborative cancel is needed and one partner has cancelled.
# order collateral # order collateral
maker_bond = models.ForeignKey(LNPayment, related_name='maker_bond', on_delete=models.SET_NULL, null=True, default=None, blank=True) maker_bond = models.ForeignKey(LNPayment, related_name='maker_bond', on_delete=models.SET_NULL, null=True, default=None, blank=True)
taker_bond = models.ForeignKey(LNPayment, related_name='taker_bond', on_delete=models.SET_NULL, null=True, default=None, blank=True) taker_bond = models.ForeignKey(LNPayment, related_name='taker_bond', on_delete=models.SET_NULL, null=True, default=None, blank=True)

View File

@ -11,12 +11,7 @@ class MakeOrderSerializer(serializers.ModelSerializer):
model = Order model = Order
fields = ('type','currency','amount','payment_method','is_explicit','premium','satoshis') fields = ('type','currency','amount','payment_method','is_explicit','premium','satoshis')
class UpdateOrderSerializer(serializers.ModelSerializer): class UpdateOrderSerializer(serializers.Serializer):
class Meta: invoice = serializers.CharField(max_length=300, allow_null=True, allow_blank=True, default=None)
model = Order action = serializers.ChoiceField(choices=('take','dispute','cancel','confirm','rate'), allow_null=False)
fields = ('id','buyer_invoice') rating = serializers.ChoiceField(choices=('1','2','3','4','5'), allow_null=True, allow_blank=True, default=None)
class UpdateInvoiceSerializer(serializers.ModelSerializer):
class Meta:
model = LNPayment
fields = ['invoice']

View File

@ -3,7 +3,7 @@ from .views import OrderMakerView, OrderView, UserView, BookView
urlpatterns = [ urlpatterns = [
path('make/', OrderMakerView.as_view()), path('make/', OrderMakerView.as_view()),
path('order/', OrderView.as_view({'get':'get','post':'take_or_update'})), path('order/', OrderView.as_view({'get':'get','post':'take_update_confirm_dispute_cancel'})),
path('usergen/', UserView.as_view()), path('usergen/', UserView.as_view()),
path('book/', BookView.as_view()), path('book/', BookView.as_view()),
] ]

View File

@ -7,9 +7,9 @@ from rest_framework.response import Response
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User from django.contrib.auth.models import User
from .serializers import ListOrderSerializer, MakeOrderSerializer, UpdateInvoiceSerializer from .serializers import ListOrderSerializer, MakeOrderSerializer, UpdateOrderSerializer
from .models import Order from .models import Order
from .logics import Logics from .logics import EXP_MAKER_BOND_INVOICE, Logics
from .nick_generator.nick_generator import NickGenerator from .nick_generator.nick_generator import NickGenerator
from robohash import Robohash from robohash import Robohash
@ -23,7 +23,7 @@ from django.utils import timezone
from decouple import config from decouple import config
EXPIRATION_MAKE = config('EXPIRATION_MAKE') EXP_MAKER_BOND_INVOICE = int(config('EXP_MAKER_BOND_INVOICE'))
avatar_path = Path('frontend/static/assets/avatars') avatar_path = Path('frontend/static/assets/avatars')
avatar_path.mkdir(parents=True, exist_ok=True) avatar_path.mkdir(parents=True, exist_ok=True)
@ -36,44 +36,39 @@ class OrderMakerView(CreateAPIView):
def post(self,request): def post(self,request):
serializer = self.serializer_class(data=request.data) serializer = self.serializer_class(data=request.data)
if serializer.is_valid(): if not serializer.is_valid(): return Response(status=status.HTTP_400_BAD_REQUEST)
otype = serializer.data.get('type')
currency = serializer.data.get('currency')
amount = serializer.data.get('amount')
payment_method = serializer.data.get('payment_method')
premium = serializer.data.get('premium')
satoshis = serializer.data.get('satoshis')
is_explicit = serializer.data.get('is_explicit')
valid, context = Logics.validate_already_maker_or_taker(request.user) type = serializer.data.get('type')
if not valid: currency = serializer.data.get('currency')
return Response(context, status=status.HTTP_409_CONFLICT) amount = serializer.data.get('amount')
payment_method = serializer.data.get('payment_method')
premium = serializer.data.get('premium')
satoshis = serializer.data.get('satoshis')
is_explicit = serializer.data.get('is_explicit')
# Creates a new order in db valid, context = Logics.validate_already_maker_or_taker(request.user)
order = Order( if not valid: return Response(context, status=status.HTTP_409_CONFLICT)
type=otype,
status=Order.Status.WFB,
currency=currency,
amount=amount,
payment_method=payment_method,
premium=premium,
satoshis=satoshis,
is_explicit=is_explicit,
expires_at=timezone.now()+timedelta(minutes=EXPIRATION_MAKE),
maker=request.user)
order.t0_satoshis=Logics.satoshis_now(order) # TODO reate Order class method when new instance is created! # Creates a new order
order.last_satoshis=Logics.satoshis_now(order) order = Order(
order.save() type=type,
currency=currency,
amount=amount,
payment_method=payment_method,
premium=premium,
satoshis=satoshis,
is_explicit=is_explicit,
expires_at=timezone.now()+timedelta(minutes=EXP_MAKER_BOND_INVOICE),
maker=request.user)
if not serializer.is_valid(): order.last_satoshis = order.t0_satoshis = Logics.satoshis_now(order) # TODO move to Order class method when new instance is created!
return Response(status=status.HTTP_400_BAD_REQUEST)
order.save()
return Response(ListOrderSerializer(order).data, status=status.HTTP_201_CREATED) return Response(ListOrderSerializer(order).data, status=status.HTTP_201_CREATED)
class OrderView(viewsets.ViewSet): class OrderView(viewsets.ViewSet):
serializer_class = UpdateInvoiceSerializer serializer_class = UpdateOrderSerializer
lookup_url_kwarg = 'order_id' lookup_url_kwarg = 'order_id'
def get(self, request, format=None): def get(self, request, format=None):
@ -88,7 +83,7 @@ class OrderView(viewsets.ViewSet):
if len(order) == 1 : if len(order) == 1 :
order = order[0] order = order[0]
# If order expired # 1) If order expired
if order.status == Order.Status.EXP: if order.status == Order.Status.EXP:
return Response({'bad_request':'This order has expired'},status.HTTP_400_BAD_REQUEST) return Response({'bad_request':'This order has expired'},status.HTTP_400_BAD_REQUEST)
@ -99,11 +94,11 @@ class OrderView(viewsets.ViewSet):
data['is_taker'] = order.taker == request.user data['is_taker'] = order.taker == request.user
data['is_participant'] = data['is_maker'] or data['is_taker'] data['is_participant'] = data['is_maker'] or data['is_taker']
# If not a participant and order is not public, forbid. # 2) If not a participant and order is not public, forbid.
if not data['is_participant'] and order.status != Order.Status.PUB: 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) return Response({'bad_request':'Not allowed to see this order'},status.HTTP_403_FORBIDDEN)
# non participants can view some details, but only if PUB # 3) Non participants can view details (but only if PUB)
elif not data['is_participant'] and order.status != Order.Status.PUB: elif not data['is_participant'] and order.status != Order.Status.PUB:
return Response(data, status=status.HTTP_200_OK) return Response(data, status=status.HTTP_200_OK)
@ -114,45 +109,73 @@ class OrderView(viewsets.ViewSet):
data['taker_nick'] = str(order.taker) data['taker_nick'] = str(order.taker)
data['status_message'] = Order.Status(order.status).label data['status_message'] = Order.Status(order.status).label
# If status is 'waiting for maker bond', reply with a hodl invoice too. # 4) If status is 'waiting for maker bond', reply with a MAKER HODL invoice.
if order.status == Order.Status.WFB and data['is_maker']: if order.status == Order.Status.WFB and data['is_maker']:
valid, context = Logics.gen_maker_hodl_invoice(order, request.user) valid, context = Logics.gen_maker_hodl_invoice(order, request.user)
if valid: data = {**data, **context} if valid else Response(context, status.HTTP_400_BAD_REQUEST)
data = {**data, **context}
else: # 5) If status is 'Public' and user is taker/buyer, reply with a TAKER HODL invoice.
Response(context, status=status.HTTP_400_BAD_REQUEST) elif order.status == Order.Status.PUB 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)
# 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)
# 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)
return Response(data, status=status.HTTP_200_OK) return Response(data, status=status.HTTP_200_OK)
return Response({'Order Not Found':'Invalid Order Id'},status=status.HTTP_404_NOT_FOUND) return Response({'Order Not Found':'Invalid Order Id'},status=status.HTTP_404_NOT_FOUND)
def take_update_confirm_dispute_cancel(self, request, format=None):
def take_or_update(self, request, format=None):
order_id = request.GET.get(self.lookup_url_kwarg) order_id = request.GET.get(self.lookup_url_kwarg)
serializer = UpdateInvoiceSerializer(data=request.data) serializer = UpdateOrderSerializer(data=request.data)
if not serializer.is_valid(): return Response(status=status.HTTP_400_BAD_REQUEST)
order = Order.objects.get(id=order_id) order = Order.objects.get(id=order_id)
if serializer.is_valid(): # action is either 1)'take', 2)'confirm', 3)'cancel', 4)'dispute' , 5)'update' (invoice) 6)'rate' (counterparty)
invoice = serializer.data.get('invoice') action = serializer.data.get('action')
invoice = serializer.data.get('invoice')
rating = serializer.data.get('rating')
# 1) If action is take, it is be taker request!
if action == 'take':
if order.status == Order.Status.PUB:
valid, context = Logics.validate_already_maker_or_taker(request.user)
if not valid: return Response(context, status=status.HTTP_409_CONFLICT)
Logics.take(order, request.user)
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)
# If this is an empty POST request (no invoice), it must be taker request! # 3) If action is cancel
if not invoice and order.status == Order.Status.PUB: elif action == 'cancel':
valid, context = Logics.validate_already_maker_or_taker(request.user) pass
if not valid: return Response(context, status=status.HTTP_409_CONFLICT)
Logics.take(order, request.user) # 4) If action is confirm
elif action == 'confirm':
pass
# An invoice came in! update it # 5) If action is dispute
elif invoice: elif action == 'dispute':
print(invoice) pass
updated = Logics.update_invoice(order=order,user=request.user,invoice=invoice)
if not updated: # 6) If action is dispute
return Response({'bad_request':'Invalid Lightning Network Invoice. It starts by LNTB...'}) elif action == 'rate' and rating:
pass
# Something else is going on. Probably not allowed.
# If nothing... something else is going on. Probably not allowed!
else: else:
return Response({'bad_request':'Not allowed'}) return Response({'bad_request':'Not allowed'})
@ -264,6 +287,7 @@ class BookView(ListAPIView):
user = User.objects.filter(id=data['maker']) user = User.objects.filter(id=data['maker'])
if len(user) == 1: if len(user) == 1:
data['maker_nick'] = user[0].username data['maker_nick'] = user[0].username
# Non participants should not see the status or who is the taker # Non participants should not see the status or who is the taker
for key in ('status','taker'): for key in ('status','taker'):
del data[key] del data[key]

View File

@ -87,8 +87,10 @@ export default class OrderPage extends Component {
console.log(this.state) console.log(this.state)
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken')}, headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),},
body: JSON.stringify({}), body: JSON.stringify({
'action':'take',
}),
}; };
fetch('/api/order/' + '?order_id=' + this.orderId, requestOptions) fetch('/api/order/' + '?order_id=' + this.orderId, requestOptions)
.then((response) => response.json()) .then((response) => response.json())