From 8f93c8f7b65e6b7454da90cd30c2383f04dba9c9 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Mon, 13 Jun 2022 15:27:09 -0700 Subject: [PATCH] Add address submission and validation checks --- api/logics.py | 80 +++++++++++++++++++++++++++-- api/models.py | 8 ++- api/views.py | 4 +- frontend/src/components/TradeBox.js | 6 +-- 4 files changed, 86 insertions(+), 12 deletions(-) diff --git a/api/logics.py b/api/logics.py index 09908954..9896cfa1 100644 --- a/api/logics.py +++ b/api/logics.py @@ -1,5 +1,5 @@ from datetime import timedelta -from tkinter import N +from tkinter import N, ON from django.utils import timezone from api.lightning.node import LNNode from django.db.models import Q, Sum @@ -7,6 +7,7 @@ from django.db.models import Q, Sum from api.models import OnchainPayment, Order, LNPayment, MarketTick, User, Currency from api.tasks import send_message from decouple import config +from api.utils import validate_onchain_address import gnupg @@ -550,7 +551,7 @@ class Logics: if suggested_mining_fee_rate > 50: suggested_mining_fee_rate = 50 - onchain_payment.suggested_mining_fee_rate = LNNode.estimate_fee(amount_sats=preliminary_amount)["mining_fee_rate"] + onchain_payment.suggested_mining_fee_rate = max(1.05, LNNode.estimate_fee(amount_sats=preliminary_amount)["mining_fee_rate"]) onchain_payment.swap_fee_rate = cls.compute_swap_fee_rate(onchain_payment.balance) onchain_payment.save() @@ -621,6 +622,67 @@ class Logics: return True, {"escrow_amount": escrow_amount} + @classmethod + def update_address(cls, order, user, address, mining_fee_rate): + + # Empty address? + if not address: + return False, { + "bad_address": + "You submitted an empty invoice" + } + # only the buyer can post a buyer address + if not cls.is_buyer(order, user): + return False, { + "bad_request": + "Only the buyer of this order can provide a payout address." + } + # not the right time to submit + if (not (order.taker_bond.status == order.maker_bond.status == + LNPayment.Status.LOCKED) + and not order.status == Order.Status.FAI): + return False, { + "bad_request": + "You cannot submit an adress are not locked." + } + # not a valid address (does not accept Taproot as of now) + if not validate_onchain_address(address): + return False, { + "bad_address": + "Does not look like a valid address" + } + if mining_fee_rate: + # not a valid mining fee + if float(mining_fee_rate) <= 1: + return False, { + "bad_address": + "The mining fee is too low." + } + elif float(mining_fee_rate) > 50: + return False, { + "bad_address": + "The mining fee is too high." + } + order.payout_tx.mining_fee_rate = float(mining_fee_rate) + # If not mining ee provider use backend's suggested fee rate + else: + order.payout_tx.mining_fee_rate = order.payout_tx.suggested_mining_fee_rate + + tx = order.payout_tx + tx.address = address + tx.mining_fee_sats = int(tx.mining_fee_rate * 141) + tx.num_satoshis = cls.payout_amount(order, user)[1]["invoice_amount"] + tx.sent_satoshis = int(float(tx.num_satoshis) - float(tx.num_satoshis) * float(tx.swap_fee_rate)/100 - float(tx.mining_fee_sats)) + tx.status = OnchainPayment.Status.VALID + tx.save() + + order.is_swap = True + order.save() + + cls.move_state_updated_payout_method(order) + + return True, None + @classmethod def update_invoice(cls, order, user, invoice): @@ -677,6 +739,15 @@ class Logics: }, ) + order.is_swap = False + order.save() + + cls.move_state_updated_payout_method(order) + + return True, None + + @classmethod + def move_state_updated_payout_method(cls,order): # If the order status is 'Waiting for invoice'. Move forward to 'chat' if order.status == Order.Status.WFI: order.status = Order.Status.CHA @@ -706,10 +777,9 @@ class Logics: order.payout.status = LNPayment.Status.FLIGHT order.payout.routing_attempts = 0 order.payout.save() - order.save() - + order.save() - return True, None + return True def add_profile_rating(profile, rating): """adds a new rating to a user profile""" diff --git a/api/models.py b/api/models.py index 9d3d7f1a..f7d02e2d 100644 --- a/api/models.py +++ b/api/models.py @@ -205,10 +205,14 @@ class OnchainPayment(models.Model): num_satoshis = models.PositiveBigIntegerField(null=True, validators=[ - MinValueValidator(0.7 * MIN_SWAP_AMOUNT), + MinValueValidator(0.5 * MIN_SWAP_AMOUNT), + MaxValueValidator(1.5 * MAX_TRADE), + ]) + sent_satoshis = models.PositiveBigIntegerField(null=True, + validators=[ + MinValueValidator(0.5 * MIN_SWAP_AMOUNT), MaxValueValidator(1.5 * MAX_TRADE), ]) - # fee in sats/vbyte with mSats decimals fee_msat suggested_mining_fee_rate = models.DecimalField(max_digits=6, decimal_places=3, diff --git a/api/views.py b/api/views.py index 0068c59a..78ba2049 100644 --- a/api/views.py +++ b/api/views.py @@ -337,7 +337,7 @@ class OrderView(viewsets.ViewSet): elif data["is_buyer"] and (order.status == Order.Status.WF2 or order.status == Order.Status.WFI): - # If the two bonds are locked, reply with an AMOUNT and onchain swap cost so he can send the buyer invoice/address + # If the two bonds are locked, reply with an AMOUNT and onchain swap cost so he can send the buyer invoice/address. if (order.maker_bond.status == order.taker_bond.status == LNPayment.Status.LOCKED): valid, context = Logics.payout_amount(order, request.user) @@ -467,7 +467,7 @@ class OrderView(viewsets.ViewSet): if not valid: return Response(context, status.HTTP_400_BAD_REQUEST) - # 2.b) If action is 'update invoice' + # 2.b) If action is 'update address' if action == "update_address": valid, context = Logics.update_address(order, request.user, address, mining_fee_rate) diff --git a/frontend/src/components/TradeBox.js b/frontend/src/components/TradeBox.js index 64ba4cd7..68aa7bc5 100644 --- a/frontend/src/components/TradeBox.js +++ b/frontend/src/components/TradeBox.js @@ -578,7 +578,7 @@ class TradeBox extends Component { }; fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions) .then((response) => response.json()) - .then((data) => this.setState({badAddress:data_address}) + .then((data) => this.setState({badAddress:data.bad_address}) & this.props.completeSetState(data)); } @@ -659,7 +659,7 @@ class TradeBox extends Component { Lightning} onClick={() => this.setState({receiveTab:0})}/> - Onchain} disabled={!this.props.data.swap_allowed} onClick={() => this.setState({receiveTab:1, miningFee: this.props.data.suggested_mining_fee_rate})} /> + Onchain} disabled={!this.props.data.swap_allowed} onClick={() => this.setState({receiveTab:1, miningFee: parseFloat(this.props.data.suggested_mining_fee_rate)})} /> @@ -777,7 +777,7 @@ class TradeBox extends Component {
- +