mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-18 12:11:35 +00:00
Fix onchain payouts bug
This commit is contained in:
parent
aa445418d5
commit
5723cde20e
@ -16,6 +16,8 @@ from . import lightning_pb2_grpc as lightningstub
|
||||
from . import router_pb2 as routerrpc
|
||||
from . import router_pb2_grpc as routerstub
|
||||
|
||||
import time, random
|
||||
|
||||
#######
|
||||
# Should work with LND (c-lightning in the future if there are features that deserve the work)
|
||||
#######
|
||||
@ -127,7 +129,7 @@ class LNNode:
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def pay_onchain(cls, onchainpayment):
|
||||
def pay_onchain(cls, onchainpayment, valid_code=1, on_mempool_code=2):
|
||||
"""Send onchain transaction for buyer payouts"""
|
||||
|
||||
if config("DISABLE_ONCHAIN", cast=bool):
|
||||
@ -141,14 +143,24 @@ class LNNode:
|
||||
spend_unconfirmed=True,
|
||||
)
|
||||
|
||||
response = cls.lightningstub.SendCoins(
|
||||
request, metadata=[("macaroon", MACAROON.hex())]
|
||||
)
|
||||
# Cheap security measure to ensure there has been some non-deterministic time between request and DB check
|
||||
time.sleep(random.uniform(0.5, 10))
|
||||
|
||||
onchainpayment.txid = response.txid
|
||||
onchainpayment.save()
|
||||
if onchainpayment.status == valid_code:
|
||||
# Changing the state to "MEMPO" should be atomic with SendCoins.
|
||||
onchainpayment.status = on_mempool_code
|
||||
onchainpayment.save()
|
||||
response = cls.lightningstub.SendCoins(
|
||||
request, metadata=[("macaroon", MACAROON.hex())]
|
||||
)
|
||||
|
||||
return True
|
||||
onchainpayment.txid = response.txid
|
||||
onchainpayment.save()
|
||||
return True
|
||||
|
||||
elif onchainpayment.status == on_mempool_code:
|
||||
# Bug, double payment attempted
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def cancel_return_hold_invoice(cls, payment_hash):
|
||||
|
@ -734,7 +734,11 @@ class Logics:
|
||||
if not order.taker_bond:
|
||||
return False, {"bad_request": "Wait for your order to be taken."}
|
||||
if (
|
||||
not ( order.taker_bond.status == order.maker_bond.status == LNPayment.Status.LOCKED)
|
||||
not (
|
||||
order.taker_bond.status
|
||||
== order.maker_bond.status
|
||||
== LNPayment.Status.LOCKED
|
||||
)
|
||||
and not order.status == Order.Status.FAI
|
||||
):
|
||||
return False, {
|
||||
@ -753,7 +757,7 @@ class Logics:
|
||||
payout = LNNode.validate_ln_invoice(invoice, num_satoshis)
|
||||
|
||||
if not payout["valid"]:
|
||||
return False, payout['context']
|
||||
return False, payout["context"]
|
||||
|
||||
order.payout, _ = LNPayment.objects.update_or_create(
|
||||
concept=LNPayment.Concepts.PAYBUYER,
|
||||
@ -763,10 +767,10 @@ class Logics:
|
||||
receiver=user,
|
||||
# if there is a LNPayment matching these above, it updates that one with defaults below.
|
||||
defaults={
|
||||
"invoice":invoice,
|
||||
"status":LNPayment.Status.VALIDI,
|
||||
"num_satoshis":num_satoshis,
|
||||
"description": payout['description'],
|
||||
"invoice": invoice,
|
||||
"status": LNPayment.Status.VALIDI,
|
||||
"num_satoshis": num_satoshis,
|
||||
"description": payout["description"],
|
||||
"payment_hash": payout["payment_hash"],
|
||||
"created_at": payout["created_at"],
|
||||
"expires_at": payout["expires_at"],
|
||||
@ -1429,10 +1433,12 @@ class Logics:
|
||||
if not order.payout_tx.status == OnchainPayment.Status.VALID:
|
||||
return False
|
||||
|
||||
valid = LNNode.pay_onchain(order.payout_tx)
|
||||
valid = LNNode.pay_onchain(
|
||||
order.payout_tx,
|
||||
valid_code=OnchainPayment.Status.VALID,
|
||||
on_mempool_code=OnchainPayment.Status.MEMPO,
|
||||
)
|
||||
if valid:
|
||||
order.payout_tx.status = OnchainPayment.Status.MEMPO
|
||||
order.payout_tx.save()
|
||||
order.status = Order.Status.SUC
|
||||
order.save()
|
||||
send_message.delay(order.id, "trade_successful")
|
||||
|
@ -6,7 +6,6 @@ import {
|
||||
ToggleButtonGroup,
|
||||
ToggleButton,
|
||||
IconButton,
|
||||
Box,
|
||||
Link,
|
||||
Paper,
|
||||
Rating,
|
||||
@ -27,6 +26,7 @@ import {
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
} from '@mui/material';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import QRCode from 'react-qr-code';
|
||||
import Countdown, { zeroPad } from 'react-countdown';
|
||||
import Chat from './EncryptedChat';
|
||||
@ -61,6 +61,10 @@ class TradeBox extends Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
openConfirmFiatReceived: false,
|
||||
loadingButtonFiatSent: false,
|
||||
loadingButtonFiatReceived: false,
|
||||
loadingSubmitInvoice: false,
|
||||
loadingSubmitAddress: false,
|
||||
openConfirmDispute: false,
|
||||
receiveTab: 0,
|
||||
address: '',
|
||||
@ -232,7 +236,15 @@ class TradeBox extends Component {
|
||||
<Button onClick={this.handleClickCloseConfirmFiatReceived} autoFocus>
|
||||
{t('Go back')}
|
||||
</Button>
|
||||
<Button onClick={this.handleClickTotallyConfirmFiatReceived}>{t('Confirm')}</Button>
|
||||
<LoadingButton
|
||||
loading={this.state.loadingButtonFiatReceived}
|
||||
onClick={() => {
|
||||
this.setState({ loadingButtonFiatReceived: true });
|
||||
this.handleClickTotallyConfirmFiatReceived();
|
||||
}}
|
||||
>
|
||||
{t('Confirm')}
|
||||
</LoadingButton>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
@ -627,7 +639,7 @@ class TradeBox extends Component {
|
||||
};
|
||||
|
||||
handleClickSubmitInvoiceButton = () => {
|
||||
this.setState({ badInvoice: false });
|
||||
this.setState({ badInvoice: false, loadingSubmitInvoice: true });
|
||||
|
||||
apiClient
|
||||
.post('/api/order/?order_id=' + this.props.data.id, {
|
||||
@ -636,7 +648,8 @@ class TradeBox extends Component {
|
||||
})
|
||||
.then(
|
||||
(data) =>
|
||||
this.setState({ badInvoice: data.bad_invoice }) & this.props.completeSetState(data),
|
||||
this.setState({ badInvoice: data.bad_invoice, loadingSubmitInvoice: false }) &
|
||||
this.props.completeSetState(data),
|
||||
);
|
||||
};
|
||||
|
||||
@ -659,7 +672,7 @@ class TradeBox extends Component {
|
||||
};
|
||||
|
||||
handleClickSubmitAddressButton = () => {
|
||||
this.setState({ badInvoice: false });
|
||||
this.setState({ badInvoice: false, loadingSubmitAddress: true });
|
||||
|
||||
apiClient
|
||||
.post('/api/order/?order_id=' + this.props.data.id, {
|
||||
@ -669,7 +682,8 @@ class TradeBox extends Component {
|
||||
})
|
||||
.then(
|
||||
(data) =>
|
||||
this.setState({ badAddress: data.bad_address }) & this.props.completeSetState(data),
|
||||
this.setState({ badAddress: data.bad_address, loadingSubmitAddress: false }) &
|
||||
this.props.completeSetState(data),
|
||||
);
|
||||
};
|
||||
|
||||
@ -838,13 +852,14 @@ class TradeBox extends Component {
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} align='center'>
|
||||
<Button
|
||||
<LoadingButton
|
||||
loading={this.state.loadingSubmitInvoice}
|
||||
onClick={this.handleClickSubmitInvoiceButton}
|
||||
variant='contained'
|
||||
color='primary'
|
||||
>
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
</LoadingButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
@ -940,13 +955,14 @@ class TradeBox extends Component {
|
||||
<div style={{ height: 10 }} />
|
||||
|
||||
<Grid item xs={12} align='center'>
|
||||
<Button
|
||||
<LoadingButton
|
||||
loading={this.state.loadingSubmitAddress}
|
||||
onClick={this.handleClickSubmitAddressButton}
|
||||
variant='contained'
|
||||
color='primary'
|
||||
>
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
</LoadingButton>
|
||||
</Grid>
|
||||
</div>
|
||||
<List>
|
||||
@ -1192,7 +1208,10 @@ class TradeBox extends Component {
|
||||
.post('/api/order/?order_id=' + this.props.data.id, {
|
||||
action: 'confirm',
|
||||
})
|
||||
.then((data) => this.props.completeSetState(data));
|
||||
.then((data) => {
|
||||
this.props.completeSetState(data),
|
||||
this.setState({ loadingButtonFiatSent: false, loadingButtonFiatReceived: false });
|
||||
});
|
||||
};
|
||||
|
||||
handleRatingUserChange = (e) => {
|
||||
@ -1224,10 +1243,14 @@ class TradeBox extends Component {
|
||||
<Grid container spacing={1}>
|
||||
<Grid item xs={12} align='center'>
|
||||
<Button
|
||||
loading={this.state.loadingButtonFiatSent}
|
||||
defaultValue='confirm'
|
||||
variant='contained'
|
||||
color='secondary'
|
||||
onClick={this.handleClickConfirmButton}
|
||||
onClick={() => {
|
||||
this.setState({ loadingButtonFiatSent: true });
|
||||
this.handleClickConfirmButton();
|
||||
}}
|
||||
>
|
||||
{t('Confirm {{amount}} {{currencyCode}} sent', {
|
||||
currencyCode: this.props.data.currencyCode,
|
||||
@ -1249,7 +1272,8 @@ class TradeBox extends Component {
|
||||
const { t } = this.props;
|
||||
return (
|
||||
<Grid item xs={12} align='center'>
|
||||
<Button
|
||||
<LoadingButton
|
||||
loading={this.state.loadingButtonFiatReceived}
|
||||
defaultValue='confirm'
|
||||
variant='contained'
|
||||
color='secondary'
|
||||
@ -1265,7 +1289,7 @@ class TradeBox extends Component {
|
||||
),
|
||||
),
|
||||
})}
|
||||
</Button>
|
||||
</LoadingButton>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
@ -1732,13 +1756,14 @@ class TradeBox extends Component {
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} align='center'>
|
||||
<Button
|
||||
<LoadingButton
|
||||
loading={this.state.loadingSubmitInvoice}
|
||||
onClick={this.handleClickSubmitInvoiceButton}
|
||||
variant='contained'
|
||||
color='primary'
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
{t('Submit')}
|
||||
</LoadingButton>
|
||||
</Grid>
|
||||
{this.showBondIsReturned()}
|
||||
</Grid>
|
||||
|
@ -84,9 +84,11 @@ class UnsafeAlert extends Component {
|
||||
>
|
||||
<AlertTitle>{t('You are not using RoboSats privately')}</AlertTitle>
|
||||
<Trans i18nKey='desktop_unsafe_alert'>
|
||||
<a>Some features are disabled for your protection (e.g. chat) and you will not be
|
||||
able to complete a trade without them. To protect your privacy and fully enable
|
||||
RoboSats, use </a>
|
||||
<a>
|
||||
Some features are disabled for your protection (e.g. chat) and you will not be
|
||||
able to complete a trade without them. To protect your privacy and fully enable
|
||||
RoboSats, use{' '}
|
||||
</a>
|
||||
<Link href='https://www.torproject.org/download/' target='_blank'>
|
||||
Tor Browser
|
||||
</Link>
|
||||
|
@ -8,6 +8,7 @@ def basic(request, *args, **kwargs):
|
||||
context = {"ONION_LOCATION": config("ONION_LOCATION")}
|
||||
return render(request, "frontend/basic.html", context=context)
|
||||
|
||||
|
||||
def pro(request, *args, **kwargs):
|
||||
context = {"ONION_LOCATION": config("ONION_LOCATION")}
|
||||
return render(request, "frontend/pro.html", context=context)
|
||||
|
Loading…
Reference in New Issue
Block a user