diff --git a/api/admin.py b/api/admin.py index db2e118f..0b45bd9a 100644 --- a/api/admin.py +++ b/api/admin.py @@ -46,7 +46,7 @@ class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin): "maker_link", "taker_link", "status", - "amount", + "amt", "currency_link", "t0_satoshis", "is_disputed", @@ -69,7 +69,13 @@ class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin): "trade_escrow", ) list_filter = ("is_disputed", "is_fiat_sent", "type", "currency", "status") - search_fields = ["id","amount"] + search_fields = ["id","amount","min_amount","max_amount"] + + def amt(self, obj): + if obj.has_range and obj.amount == None: + return str(float(obj.min_amount))+"-"+ str(float(obj.max_amount)) + else: + return float(obj.amount) @admin.register(LNPayment) class LNPaymentAdmin(AdminChangeLinksMixin, admin.ModelAdmin): diff --git a/api/logics.py b/api/logics.py index dd607c21..0e058efc 100644 --- a/api/logics.py +++ b/api/logics.py @@ -118,16 +118,16 @@ class Logics: elif max_sats > MAX_TRADE: return False, { "bad_request": - "Your order upper range value (max_amount) is too big. It is worth " + - "{:,}".format(max_sats) + + "Your order maximum amount is too big. It is worth " + + "{:,}".format(int(max_sats)) + " Sats now, but the limit is " + "{:,}".format(MAX_TRADE) + " Sats" } elif min_sats < MIN_TRADE: return False, { "bad_request": - "Your order lower range value (min_mount) is too small. It is worth " + - "{:,}".format(min_sats) + + "Your order minimum amount is too small. It is worth " + + "{:,}".format(int(min_sats)) + " Sats now, but the limit is " + "{:,}".format(MAX_TRADE) + " Sats" } @@ -139,6 +139,15 @@ class Logics: return True, None + def validate_amount_within_range(order, amount): + if amount > float(order.max_amount) or amount < float(order.min_amount): + return False, { + "bad_request": + "The amount specified is outside the range specified by the maker" + } + + return True, None + def user_activity_status(last_seen): if last_seen > (timezone.now() - timedelta(minutes=2)): return "Active" @@ -148,7 +157,7 @@ class Logics: return "Inactive" @classmethod - def take(cls, order, user): + def take(cls, order, user, amount=None): is_penalized, time_out = cls.is_penalized(user) if is_penalized: return False, { @@ -156,6 +165,8 @@ class Logics: f"You need to wait {time_out} seconds to take an order", } else: + if order.has_range: + order.amount= amount order.taker = user order.status = Order.Status.TAK order.expires_at = timezone.now() + timedelta( @@ -702,6 +713,8 @@ class Logics: order.status = Order.Status.PUB order.expires_at = order.created_at + timedelta( seconds=order.t_to_expire(Order.Status.PUB)) + if order.has_range: + order.amount = None order.save() # send_message.delay(order.id,'order_published') # too spammy return diff --git a/api/models.py b/api/models.py index db2eaf71..d7094ca2 100644 --- a/api/models.py +++ b/api/models.py @@ -339,7 +339,11 @@ class Order(models.Model): taker_platform_rated = models.BooleanField(default=False, null=False) def __str__(self): - return f"Order {self.id}: {self.Types(self.type).label} BTC for {float(self.amount)} {self.currency}" + if self.has_range and self.amount == None: + amt = str(float(self.min_amount))+"-"+ str(float(self.max_amount)) + else: + amt = float(self.amount) + return f"Order {self.id}: {self.Types(self.type).label} BTC for {amt} {self.currency}" def t_to_expire(self, status): diff --git a/api/serializers.py b/api/serializers.py index 7104c8a8..7933c67c 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -21,7 +21,7 @@ class ListOrderSerializer(serializers.ModelSerializer): "is_explicit", "premium", "satoshis", - "bondless_taker" + "bondless_taker", "maker", "taker", ) @@ -75,6 +75,7 @@ class UpdateOrderSerializer(serializers.Serializer): allow_blank=True, default=None, ) + amount = serializers.DecimalField(max_digits=18, decimal_places=8, allow_null=True, required=False, default=None) class ClaimRewardSerializer(serializers.Serializer): invoice = serializers.CharField(max_length=2000, diff --git a/api/views.py b/api/views.py index 20572b06..406735c8 100644 --- a/api/views.py +++ b/api/views.py @@ -390,6 +390,10 @@ class OrderView(viewsets.ViewSet): """ order_id = request.GET.get(self.lookup_url_kwarg) + import sys + sys.stdout.write('AAAAAA') + print('BBBBB1') + serializer = UpdateOrderSerializer(data=request.data) if not serializer.is_valid(): return Response(status=status.HTTP_400_BAD_REQUEST) @@ -410,7 +414,17 @@ class OrderView(viewsets.ViewSet): request.user) if not valid: return Response(context, status=status.HTTP_409_CONFLICT) - valid, context = Logics.take(order, request.user) + + # For order with amount range, set the amount now. + if order.has_range: + amount = float(serializer.data.get("amount")) + valid, context = Logics.validate_amount_within_range(order, amount) + if not valid: + return Response(context, status=status.HTTP_400_BAD_REQUEST) + + valid, context = Logics.take(order, request.user, amount) + else: + valid, context = Logics.take(order, request.user) if not valid: return Response(context, status=status.HTTP_403_FORBIDDEN) diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index 6b2d7367..f1af1514 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -78,6 +78,15 @@ export default class BookPage extends Component { if(status=='Seen recently'){return("warning")} if(status=='Inactive'){return('error')} } + amountToString = (amount,has_range,min_amount,max_amount) => { + if (has_range){ + console.log(this.pn(parseFloat(Number(min_amount).toPrecision(2)))) + console.log(this.pn(parseFloat(Number(min_amount).toPrecision(2)))+'-'+this.pn(parseFloat(Number(max_amount).toPrecision(2)))) + return this.pn(parseFloat(Number(min_amount).toPrecision(2)))+'-'+this.pn(parseFloat(Number(max_amount).toPrecision(2))) + }else{ + return this.pn(parseFloat(Number(amount).toPrecision(3))) + } + } bookListTableDesktop=()=>{ return ( @@ -90,7 +99,10 @@ export default class BookPage extends Component { robot: order.maker_nick, robot_status: order.maker_status, type: order.type ? "Seller": "Buyer", - amount: parseFloat(parseFloat(order.amount).toFixed(5)), + amount: order.amount, + has_range: order.has_range, + min_amount: order.min_amount, + max_amount: order.max_amount, currency: this.getCurrencyCode(order.currency), payment_method: order.payment_method, price: order.price, @@ -123,9 +135,9 @@ export default class BookPage extends Component { ); } }, { field: 'type', headerName: 'Is', width: 60 }, - { field: 'amount', headerName: 'Amount', type: 'number', width: 80, + { field: 'amount', headerName: 'Amount', type: 'number', width: 90, renderCell: (params) => {return ( -