Merge pull request #4 from Reckless-Satoshi/make-order-api-endpoint

Implement initial API with MakeOrder endpoint.

Has Order model and post-only view.
This commit is contained in:
Reckless_Satoshi 2022-01-01 22:44:33 +00:00 committed by GitHub
commit d5d706b99d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 148 additions and 2 deletions

2
.gitignore vendored
View File

@ -635,3 +635,5 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# Django
*migrations*

0
api/__init__.py Normal file
View File

3
api/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
api/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class ApiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'api'

View File

71
api/models.py Normal file
View File

@ -0,0 +1,71 @@
from django.db import models
from django.contrib.auth.models import User
from django.core.validators import MaxValueValidator, MinValueValidator
#############################
# TODO
# Load hparams from .env file
min_satoshis_trade = 10*1000
max_satoshis_trade = 500*1000
class Order(models.Model):
class Types(models.IntegerChoices):
BUY = 0, 'BUY'
SELL = 1, 'SELL'
class Currencies(models.IntegerChoices):
USD = 1, 'USD'
EUR = 2, 'EUR'
ETH = 3, 'ETH'
class Status(models.TextChoices):
WFB = 0, 'Waiting for bond'
PUB = 1, 'Published in order book'
DEL = 2, 'Deleted from order book'
TAK = 3, 'Taken'
UCA = 4, 'Unilaterally cancelled'
RET = 5, 'Returned to order book' # Probably same as 1 in most cases.
WF2 = 6, 'Waiting for trade collateral and buyer invoice'
WTC = 7, 'Waiting only for trade collateral'
WBI = 8, 'Waiting only for buyer invoice'
EXF = 9, 'Exchanging fiat / In chat'
CCA = 10, 'Collaboratively cancelled'
FSE = 11, 'Fiat sent'
FCO = 12, 'Fiat confirmed'
SUC = 13, 'Sucessfully settled'
FAI = 14, 'Failed lightning network routing'
UPI = 15, 'Updated invoice'
DIS = 16, 'In dispute'
MLD = 17, 'Maker lost dispute'
TLD = 18, 'Taker lost dispute'
EXP = 19, 'Expired'
# order info, id = models.CharField(max_length=64, unique=True, null=False)
status = models.PositiveSmallIntegerField(choices=Status.choices, default=Status.WFB)
created_at = models.DateTimeField(auto_now_add=True)
# order details
type = models.PositiveSmallIntegerField(choices=Types.choices, null=False)
currency = models.PositiveSmallIntegerField(choices=Currencies.choices, null=False)
amount = models.DecimalField(max_digits=9, decimal_places=4, validators=[MinValueValidator(0.00001)])
premium = models.DecimalField(max_digits=3, decimal_places=2, default=0, null=True, validators=[MinValueValidator(-100), MaxValueValidator(1000)])
satoshis = models.PositiveBigIntegerField(null=True, validators=[MinValueValidator(min_satoshis_trade), MaxValueValidator(max_satoshis_trade)])
# order participants
maker = models.ForeignKey(User, related_name='maker', on_delete=models.SET_NULL, 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) # unique = True, a taker can only take one order
# order collateral
has_maker_bond = models.BooleanField(default=False, null=False)
has_taker_bond = models.BooleanField(default=False, null=False)
has_trade_collat = models.BooleanField(default=False, null=False)
maker_bond_secret = models.CharField(max_length=300, unique=False, null=True, default=None)
taker_bond_secret = models.CharField(max_length=300, unique=False, null=True, default=None)
trade_collat_secret = models.CharField(max_length=300, unique=False, null=True, default=None)
# buyer payment LN invoice
has_invoice = models.BooleanField(default=False, null=False) # has invoice and is valid
invoice = models.CharField(max_length=300, unique=False, null=True, default=None)

12
api/serializers.py Normal file
View File

@ -0,0 +1,12 @@
from rest_framework import serializers
from .models import Order
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ('id','status','created_at','type','currency','amount','premium','satoshis','maker')
class MakeOrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ('type','currency','amount','premium','satoshis')

3
api/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

6
api/urls.py Normal file
View File

@ -0,0 +1,6 @@
from django.urls import path
from .views import MakeOrder
urlpatterns = [
path('make/', MakeOrder.as_view())
]

40
api/views.py Normal file
View File

@ -0,0 +1,40 @@
from rest_framework import generics, status
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import OrderSerializer, MakeOrderSerializer
from .models import Order
# Create your views here.
class MakeOrder(APIView):
serializer_class = MakeOrderSerializer
def post(self,request, format=None):
serializer = self.serializer_class(data=request.data)
print(serializer)
if serializer.is_valid():
otype = serializer.data.get('type')
currency = serializer.data.get('currency')
amount = serializer.data.get('amount')
premium = serializer.data.get('premium')
satoshis = serializer.data.get('satoshis')
#################
# TODO
# query if the user is already a maker or taker, return error
# Creates a new order in db
order = Order(
type=otype,
currency=currency,
amount=amount,
premium=premium,
satoshis=satoshis)
order.save()
if not serializer.is_valid():
return Response(status=status.HTTP_400_BAD_REQUEST)
return Response(OrderSerializer(order).data, status=status.HTTP_201_CREATED)

View File

@ -37,6 +37,8 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'api',
]
MIDDLEWARE = [

View File

@ -14,8 +14,9 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
]
path('api/', include('api.urls')),
]