diff --git a/api/logics.py b/api/logics.py index 7b181d6b..6faffd0a 100644 --- a/api/logics.py +++ b/api/logics.py @@ -234,12 +234,16 @@ class Logics: return (float(amount) / premium_rate) * 100 * 1000 * 1000 @classmethod - def satoshis_now(cls, order): + def satoshis_now(cls, order, take_amount=None): """checks trade amount in sats""" if order.is_explicit: satoshis_now = order.satoshis else: - amount = order.amount if order.amount is not None else order.max_amount + if take_amount is not None: + amount = take_amount + else: + amount = order.amount if order.amount is not None else order.max_amount + satoshis_now = cls.calc_sats( amount, order.currency.exchange_rate, order.premium ) @@ -1348,6 +1352,10 @@ class Logics: order.taker = take_order.taker order.taker_bond = take_order.taker_bond + + if order.has_range: + order.amount = take_order.amount + # THE TRADE AMOUNT IS FINAL WITH THE CONFIRMATION OF THE TAKER BOND! # (This is the last update to "last_satoshis", it becomes the escrow amount next) order.last_satoshis = cls.satoshis_now(order) @@ -1370,10 +1378,6 @@ class Logics: ] ) - if order.has_range: - order.amount = take_order.amount - order.save(update_fields=["amount"]) - order.taker_bond.status = LNPayment.Status.LOCKED order.taker_bond.save(update_fields=["status"]) @@ -1424,7 +1428,7 @@ class Logics: } # If there was no taker_bond object yet, generates one - take_order.last_satoshis = cls.satoshis_now(order) + take_order.last_satoshis = cls.satoshis_now(order, take_order.amount) take_order.last_satoshis_time = timezone.now() bond_satoshis = int(take_order.last_satoshis * order.bond_size / 100) pos_text = "Buying" if cls.is_buyer(order, user) else "Selling" diff --git a/api/views.py b/api/views.py index 2d5317cc..b3c69223 100644 --- a/api/views.py +++ b/api/views.py @@ -244,11 +244,11 @@ class OrderView(viewsets.ViewSet): data["penalty"] = request.user.robot.penalty_expiration # Add booleans if user is maker, taker, partipant, buyer or seller - is_pretaker = TakeOrder.objects.filter( + take_order = TakeOrder.objects.filter( taker=request.user, order=order, expires_at__gt=timezone.now() - ).exists() + ) data["is_maker"] = order.maker == request.user - data["is_taker"] = order.taker == request.user or is_pretaker + data["is_taker"] = order.taker == request.user or take_order.exists() data["is_participant"] = data["is_maker"] or data["is_taker"] # 3.a) If not a participant and order is not public, forbid. @@ -279,7 +279,12 @@ class OrderView(viewsets.ViewSet): # 4) If order is between public and WF2 if order.status >= Order.Status.PUB and order.status < Order.Status.WF2: data["price_now"], data["premium_now"] = Logics.price_and_premium_now(order) - data["satoshis_now"] = Logics.satoshis_now(order) + if take_order.exists(): + data["satoshis_now"] = Logics.satoshis_now( + order, take_order.first().amount + ) + else: + data["satoshis_now"] = Logics.satoshis_now(order) # 4. a) If maker and Public/Paused, add premium percentile # num similar orders, and maker information to enable telegram notifications. @@ -366,11 +371,12 @@ class OrderView(viewsets.ViewSet): # 6) If status is 'Public' and user is PRETAKER, reply with a TAKER hold invoice. elif ( order.status == Order.Status.PUB - and is_pretaker + and take_order.exists() and order.taker != request.user ): data["status"] = Order.Status.TAK data["total_secs_exp"] = order.t_to_expire(Order.Status.TAK) + data["amount"] = str(take_order.first().amount) valid, context = Logics.gen_taker_hold_invoice(order, request.user) diff --git a/tests/test_trade_pipeline.py b/tests/test_trade_pipeline.py index 7d3244c2..2775aa55 100644 --- a/tests/test_trade_pipeline.py +++ b/tests/test_trade_pipeline.py @@ -14,7 +14,7 @@ from control.tasks import compute_node_balance, do_accounting from tests.test_api import BaseAPITestCase from tests.utils.node import add_invoice, set_up_regtest_network from tests.utils.pgp import sign_message -from tests.utils.trade import Trade +from tests.utils.trade import Trade, maker_form_buy_with_range from api.admin import OrderAdmin @@ -456,6 +456,28 @@ class TradeTest(BaseAPITestCase): self.assert_order_logs(data["id"]) + def test_make_and_take_range_order(self): + """ + Tests a trade with a range from order creation to taken. + """ + trade = Trade( + self.client, + # latitude and longitud in Aruba. One of the countries blocked in the example conf. + maker_form=maker_form_buy_with_range, + ) + trade.publish_order() + trade.take_order() + data = trade.response.json() + + self.assertEqual(trade.response.status_code, 200) + self.assertResponse(trade.response) + + self.assertEqual(data["status_message"], Order.Status(Order.Status.PUB).label) + self.assertAlmostEqual(float(data["amount"]), 80) + + # Cancel order to avoid leaving pending HTLCs after a successful test + trade.cancel_order() + def test_make_and_take_order_multiple_takers(self): """ Tests a trade from order creation to taken.