Skip to content

Commit

Permalink
Fix move order model constrains to env to settings.py
Browse files Browse the repository at this point in the history
  • Loading branch information
Reckless-Satoshi committed Oct 4, 2023
1 parent bed01c6 commit 57d1524
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 67 deletions.
23 changes: 5 additions & 18 deletions .env-sample
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,6 @@ MAKER_FEE_SPLIT=0.125
# Leaving the default value (20%) will grant the DevFund contributor badge.
DEVFUND = 0.2

# Bond size as percentage (%)
DEFAULT_BOND_SIZE = 3
MIN_BOND_SIZE = 1
MAX_BOND_SIZE = 15

# Time out penalty for canceling takers in SECONDS
PENALTY_TIMEOUT = 60
# Time between routing attempts of buyer invoice in MINUTES
Expand All @@ -109,9 +104,11 @@ DISABLE_ORDER_LOGS = False
# Coordinator activity limits
MAX_PUBLIC_ORDERS = 100

# Trade limits in satoshis
MIN_TRADE = 20000
MAX_TRADE = 5000000
# Coordinator Order size limits in Satoshi
# Minimum order size (must be bigger than DB constrain in /robosats/settings.py MIN_TRADE, currently 20_000 Sats)
MIN_ORDER_SIZE = 20000
# Minimum order size (must be smaller than DB constrain in /robosats/settings.py MAX_TRADE, currently 5_000_000 Sats)
MAX_ORDER_SIZE = 5000000

# For CLTV_expiry calculation
# Assume 8 min/block assumed
Expand All @@ -123,16 +120,6 @@ MAX_MINING_NETWORK_SPEEDUP_EXPECTED = 1.7
EXP_MAKER_BOND_INVOICE = 300
EXP_TAKER_BOND_INVOICE = 200

# Time a order is public in the book HOURS
DEFAULT_PUBLIC_ORDER_DURATION = 24
MAX_PUBLIC_ORDER_DURATION = 24
MIN_PUBLIC_ORDER_DURATION = 0.166

# Default time to provide a valid invoice and the trade escrow MINUTES
INVOICE_AND_ESCROW_DURATION = 180
# Time to confim chat and confirm fiat (time to Fiat Sent confirmation) HOURS
FIAT_EXCHANGE_DURATION = 24

# ROUTING
# Proportional routing fee limit (fraction of total payout: % / 100)
PROPORTIONAL_ROUTING_FEE_LIMIT = 0.001
Expand Down
23 changes: 10 additions & 13 deletions api/logics.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
ESCROW_USERNAME = config("ESCROW_USERNAME")
PENALTY_TIMEOUT = int(config("PENALTY_TIMEOUT"))

MIN_TRADE = int(config("MIN_TRADE"))
MAX_TRADE = int(config("MAX_TRADE"))
MIN_ORDER_SIZE = config("MIN_ORDER_SIZE", cast=int, default=20_000)
MAX_ORDER_SIZE = config("MAX_ORDER_SIZE", cast=int, default=5_000_000)

EXP_MAKER_BOND_INVOICE = int(config("EXP_MAKER_BOND_INVOICE"))
EXP_TAKER_BOND_INVOICE = int(config("EXP_TAKER_BOND_INVOICE"))
Expand All @@ -29,9 +29,6 @@
config("MAX_MINING_NETWORK_SPEEDUP_EXPECTED")
)

INVOICE_AND_ESCROW_DURATION = int(config("INVOICE_AND_ESCROW_DURATION"))
FIAT_EXCHANGE_DURATION = int(config("FIAT_EXCHANGE_DURATION"))


class Logics:
@classmethod
Expand Down Expand Up @@ -90,20 +87,20 @@ def validate_already_maker_or_taker(cls, user):
def validate_order_size(cls, order):
"""Validates if order size in Sats is within limits at t0"""
if not order.has_range:
if order.t0_satoshis > MAX_TRADE:
if order.t0_satoshis > MAX_ORDER_SIZE:
return False, {
"bad_request": "Your order is too big. It is worth "
+ "{:,}".format(order.t0_satoshis)
+ " Sats now, but the limit is "
+ "{:,}".format(MAX_TRADE)
+ "{:,}".format(MAX_ORDER_SIZE)
+ " Sats"
}
if order.t0_satoshis < MIN_TRADE:
if order.t0_satoshis < MIN_ORDER_SIZE:
return False, {
"bad_request": "Your order is too small. It is worth "
+ "{:,}".format(order.t0_satoshis)
+ " Sats now, but the limit is "
+ "{:,}".format(MIN_TRADE)
+ "{:,}".format(MIN_ORDER_SIZE)
+ " Sats"
}
elif order.has_range:
Expand All @@ -117,20 +114,20 @@ def validate_order_size(cls, order):
return False, {
"bad_request": "Maximum range amount must be at least 50 percent higher than the minimum amount"
}
elif max_sats > MAX_TRADE:
elif max_sats > MAX_ORDER_SIZE:
return False, {
"bad_request": "Your order maximum amount is too big. It is worth "
+ "{:,}".format(int(max_sats))
+ " Sats now, but the limit is "
+ "{:,}".format(MAX_TRADE)
+ "{:,}".format(MAX_ORDER_SIZE)
+ " Sats"
}
elif min_sats < MIN_TRADE:
elif min_sats < MIN_ORDER_SIZE:
return False, {
"bad_request": "Your order minimum amount is too small. It is worth "
+ "{:,}".format(int(min_sats))
+ " Sats now, but the limit is "
+ "{:,}".format(MIN_TRADE)
+ "{:,}".format(MIN_ORDER_SIZE)
+ " Sats"
}
elif min_sats < max_sats / 15:
Expand Down
38 changes: 21 additions & 17 deletions api/models/order.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import uuid

from decouple import config
from django.conf import settings
from django.contrib.auth.models import User
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from django.utils import timezone

MIN_TRADE = config("MIN_TRADE", cast=int, default=20_000)
MAX_TRADE = config("MAX_TRADE", cast=int, default=1_000_000)
FIAT_EXCHANGE_DURATION = config("FIAT_EXCHANGE_DURATION", cast=int, default=24)


class Order(models.Model):
class Types(models.IntegerChoices):
Expand Down Expand Up @@ -85,28 +82,30 @@ class ExpiryReasons(models.IntegerChoices):
# explicit
satoshis = models.PositiveBigIntegerField(
null=True,
validators=[MinValueValidator(MIN_TRADE), MaxValueValidator(MAX_TRADE)],
validators=[
MinValueValidator(settings.MIN_TRADE),
MaxValueValidator(settings.MAX_TRADE),
],
blank=True,
)
# optionally makers can choose the public order duration length (seconds)
public_duration = models.PositiveBigIntegerField(
default=60 * 60 * config("DEFAULT_PUBLIC_ORDER_DURATION", cast=int, default=24)
- 1,
default=60 * 60 * settings.DEFAULT_PUBLIC_ORDER_DURATION - 1,
null=False,
validators=[
MinValueValidator(
60 * 60 * config("MIN_PUBLIC_ORDER_DURATION", cast=float, default=0.166)
60 * 60 * settings.MIN_PUBLIC_ORDER_DURATION
), # Min is 10 minutes
MaxValueValidator(
60 * 60 * config("MAX_PUBLIC_ORDER_DURATION", cast=float, default=24)
60 * 60 * settings.MAX_PUBLIC_ORDER_DURATION
), # Max is 24 Hours
],
blank=False,
)

# optionally makers can choose the escrow lock / invoice submission step length (seconds)
escrow_duration = models.PositiveBigIntegerField(
default=60 * int(config("INVOICE_AND_ESCROW_DURATION")) - 1,
default=60 * settings.INVOICE_AND_ESCROW_DURATION - 1,
null=False,
validators=[
MinValueValidator(60 * 30), # Min is 30 minutes
Expand All @@ -119,24 +118,27 @@ class ExpiryReasons(models.IntegerChoices):
bond_size = models.DecimalField(
max_digits=4,
decimal_places=2,
default=config("DEFAULT_BOND_SIZE", cast=float, default=3),
default=settings.DEFAULT_BOND_SIZE,
null=False,
validators=[
MinValueValidator(config("MIN_BOND_SIZE", cast=float, default=1)), # 1 %
MaxValueValidator(config("MAX_BOND_SIZE", cast=float, default=1)), # 15 %
MinValueValidator(settings.MIN_BOND_SIZE), # 2 %
MaxValueValidator(settings.MAX_BOND_SIZE), # 15 %
],
blank=False,
)

# how many sats at creation and at last check (relevant for marked to market)
t0_satoshis = models.PositiveBigIntegerField(
null=True,
validators=[MinValueValidator(MIN_TRADE), MaxValueValidator(MAX_TRADE)],
validators=[
MinValueValidator(settings.MIN_TRADE),
MaxValueValidator(settings.MAX_TRADE),
],
blank=True,
) # sats at creation
last_satoshis = models.PositiveBigIntegerField(
null=True,
validators=[MinValueValidator(0), MaxValueValidator(MAX_TRADE * 2)],
validators=[MinValueValidator(0), MaxValueValidator(settings.MAX_TRADE * 2)],
blank=True,
) # sats last time checked. Weird if 2* trade max...
# timestamp of last_satoshis
Expand Down Expand Up @@ -267,8 +269,10 @@ def t_to_expire(self, status):
), # 'Waiting for trade collateral and buyer invoice'
7: int(self.escrow_duration), # 'Waiting only for seller trade collateral'
8: int(self.escrow_duration), # 'Waiting only for buyer invoice'
9: 60 * 60 * FIAT_EXCHANGE_DURATION, # 'Sending fiat - In chatroom'
10: 60 * 60 * FIAT_EXCHANGE_DURATION, # 'Fiat sent - In chatroom'
9: 60
* 60
* settings.FIAT_EXCHANGE_DURATION, # 'Sending fiat - In chatroom'
10: 60 * 60 * settings.FIAT_EXCHANGE_DURATION, # 'Fiat sent - In chatroom'
11: 1 * 24 * 60 * 60, # 'In dispute'
12: 0, # 'Collaboratively cancelled'
13: 100 * 24 * 60 * 60, # 'Sending satoshis to buyer'
Expand Down
10 changes: 4 additions & 6 deletions api/oas_schemas.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import textwrap

from decouple import config
from django.conf import settings
from drf_spectacular.utils import OpenApiExample, OpenApiParameter

from api.serializers import (
Expand All @@ -11,9 +12,6 @@

EXP_MAKER_BOND_INVOICE = int(config("EXP_MAKER_BOND_INVOICE"))
RETRY_TIME = int(config("RETRY_TIME"))
PUBLIC_DURATION = 60 * 60 * int(config("DEFAULT_PUBLIC_ORDER_DURATION")) - 1
ESCROW_DURATION = 60 * int(config("INVOICE_AND_ESCROW_DURATION"))
BOND_SIZE = int(config("DEFAULT_BOND_SIZE"))


class MakerViewSchema:
Expand All @@ -25,9 +23,9 @@ class MakerViewSchema:
Default values for the following fields if not specified:
- `public_duration` - **{PUBLIC_DURATION}**
- `escrow_duration` - **{ESCROW_DURATION}**
- `bond_size` - **{BOND_SIZE}**
- `public_duration` - **{settings.DEFAULT_PUBLIC_ORDER_DURATION}**
- `escrow_duration` - **{settings.INVOICE_AND_ESCROW_DURATION}**
- `bond_size` - **{settings.DEFAULT_BOND_SIZE}**
- `has_range` - **false**
- `premium` - **0**
"""
Expand Down
2 changes: 0 additions & 2 deletions api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
from .models import MarketTick, Order

RETRY_TIME = int(config("RETRY_TIME"))
MIN_PUBLIC_ORDER_DURATION_SECS = 60 * 60 * float(config("MIN_PUBLIC_ORDER_DURATION"))
MAX_PUBLIC_ORDER_DURATION_SECS = 60 * 60 * float(config("MAX_PUBLIC_ORDER_DURATION"))


class InfoSerializer(serializers.Serializer):
Expand Down
17 changes: 6 additions & 11 deletions api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,10 @@

EXP_MAKER_BOND_INVOICE = int(config("EXP_MAKER_BOND_INVOICE"))
RETRY_TIME = int(config("RETRY_TIME"))
PUBLIC_DURATION = 60 * 60 * int(config("DEFAULT_PUBLIC_ORDER_DURATION")) - 1
ESCROW_DURATION = 60 * int(config("INVOICE_AND_ESCROW_DURATION"))
BOND_SIZE = int(config("DEFAULT_BOND_SIZE"))

avatar_path = Path(settings.AVATAR_ROOT)
avatar_path.mkdir(parents=True, exist_ok=True)

# Create your views here.


class MakerView(CreateAPIView):
serializer_class = MakeOrderSerializer
Expand Down Expand Up @@ -113,11 +108,11 @@ def post(self, request):

# Optional params
if public_duration is None:
public_duration = PUBLIC_DURATION
public_duration = 60 * 60 * settings.DEFAULT_PUBLIC_ORDER_DURATION
if escrow_duration is None:
escrow_duration = ESCROW_DURATION
escrow_duration = 60 * settings.INVOICE_AND_ESCROW_DURATION
if bond_size is None:
bond_size = BOND_SIZE
bond_size = settings.DEFAULT_BOND_SIZE
if has_range is None:
has_range = False

Expand Down Expand Up @@ -787,7 +782,7 @@ def get(self, request):
context["taker_fee"] = float(config("FEE")) * (
1 - float(config("MAKER_FEE_SPLIT"))
)
context["bond_size"] = float(config("DEFAULT_BOND_SIZE"))
context["bond_size"] = settings.DEFAULT_BOND_SIZE
context["notice_severity"] = config("NOTICE_SEVERITY", cast=str, default="none")
context["notice_message"] = config("NOTICE_MESSAGE", cast=str, default="")

Expand Down Expand Up @@ -901,8 +896,8 @@ class LimitView(ListAPIView):
@extend_schema(**LimitViewSchema.get)
def get(self, request):
# Trade limits as BTC
min_trade = float(config("MIN_TRADE")) / 100_000_000
max_trade = float(config("MAX_TRADE")) / 100_000_000
min_trade = config("MIN_ORDER_SIZE", cast=int, default=20_000) / 100_000_000
max_trade = config("MAX_ORDER_SIZE", cast=int, default=5_000_000) / 100_000_000

payload = {}
queryset = Currency.objects.all().order_by("currency")
Expand Down
29 changes: 29 additions & 0 deletions robosats/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,32 @@
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"


#####################################################################
# RoboSats API settings. These should remain the same across
# all coordinators. Altering will require a DB migration.
# Do not change unless you know what you are doing.
# If there is a value here you would like to tweak or play with,
# there is possibly a better way to do it! E.g. the .env file

# Trade limits in satoshis to be applied as DB validator/constrain
MIN_TRADE = 20_000
MAX_TRADE = 5_000_000

# Time a order is public in the book HOURS
DEFAULT_PUBLIC_ORDER_DURATION = 24
# Max value API will accept for public duration (cannot be higher than 24h, hardcoded as DB validator)
MAX_PUBLIC_ORDER_DURATION = 24
# Max value API will accept for public duration (cannot be higher than 24h, hardcoded as DB validator)
MIN_PUBLIC_ORDER_DURATION = 0.166

# Bond size as percentage (%)
DEFAULT_BOND_SIZE = 3
MIN_BOND_SIZE = 2
MAX_BOND_SIZE = 15

# Default time to provide a valid invoice and the trade escrow MINUTES
INVOICE_AND_ESCROW_DURATION = 180
# Time to confirm chat and confirm fiat (time to Fiat Sent confirmation) HOURS
FIAT_EXCHANGE_DURATION = 24

0 comments on commit 57d1524

Please sign in to comment.