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 {