mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-31 02:21:35 +00:00
Add address submission and validation checks
This commit is contained in:
parent
c4396f504a
commit
8f93c8f7b6
@ -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"""
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
<Paper elevation={2}>
|
||||
<Tabs value={this.state.receiveTab} variant="fullWidth" sx={{width:290}}>
|
||||
<Tab disableRipple={true} label={<div style={{display:'flex', alignItems:'center', justifyContent:'center', flexWrap:'wrap'}}><BoltIcon/> Lightning</div>} onClick={() => this.setState({receiveTab:0})}/>
|
||||
<Tab label={<div style={{display:'flex', alignItems:'center', justifyContent:'center', flexWrap:'wrap'}}><LinkIcon/> Onchain</div>} disabled={!this.props.data.swap_allowed} onClick={() => this.setState({receiveTab:1, miningFee: this.props.data.suggested_mining_fee_rate})} />
|
||||
<Tab label={<div style={{display:'flex', alignItems:'center', justifyContent:'center', flexWrap:'wrap'}}><LinkIcon/> Onchain</div>} disabled={!this.props.data.swap_allowed} onClick={() => this.setState({receiveTab:1, miningFee: parseFloat(this.props.data.suggested_mining_fee_rate)})} />
|
||||
</Tabs>
|
||||
</Paper>
|
||||
</ListItem>
|
||||
@ -777,7 +777,7 @@ class TradeBox extends Component {
|
||||
<div style={{height:10}}/>
|
||||
|
||||
<Grid item xs={12} align="center">
|
||||
<Button onClick={null} variant='contained' color='primary'>{t("Submit")}</Button>
|
||||
<Button onClick={this.handleClickSubmitAddressButton} variant='contained' color='primary'>{t("Submit")}</Button>
|
||||
</Grid>
|
||||
</div>
|
||||
<List>
|
||||
|
Loading…
Reference in New Issue
Block a user