2022-01-08 13:08:03 +00:00
|
|
|
import React, { Component } from "react";
|
2022-01-09 14:07:05 +00:00
|
|
|
import { Paper, Button, Grid, Typography, TextField, List, ListItem, ListItemText, Divider} from "@material-ui/core"
|
2022-01-09 01:23:13 +00:00
|
|
|
import QRCode from "react-qr-code";
|
2022-01-08 13:08:03 +00:00
|
|
|
|
2022-01-09 14:07:05 +00:00
|
|
|
function getCookie(name) {
|
|
|
|
let cookieValue = null;
|
|
|
|
if (document.cookie && document.cookie !== '') {
|
|
|
|
const cookies = document.cookie.split(';');
|
|
|
|
for (let i = 0; i < cookies.length; i++) {
|
|
|
|
const cookie = cookies[i].trim();
|
|
|
|
// Does this cookie string begin with the name we want?
|
|
|
|
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
|
|
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-01-09 01:23:13 +00:00
|
|
|
}
|
2022-01-09 14:07:05 +00:00
|
|
|
return cookieValue;
|
|
|
|
}
|
|
|
|
const csrftoken = getCookie('csrftoken');
|
2022-01-09 01:23:13 +00:00
|
|
|
|
2022-01-09 14:07:05 +00:00
|
|
|
// pretty numbers
|
|
|
|
function pn(x) {
|
|
|
|
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
|
|
}
|
2022-01-09 01:23:13 +00:00
|
|
|
|
2022-01-09 14:07:05 +00:00
|
|
|
export default class TradeBox extends Component {
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2022-01-09 01:23:13 +00:00
|
|
|
}
|
|
|
|
|
2022-01-09 12:14:11 +00:00
|
|
|
showQRInvoice=()=>{
|
2022-01-08 13:08:03 +00:00
|
|
|
return (
|
|
|
|
<Grid container spacing={1}>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Typography component="body2" variant="body2">
|
|
|
|
Robots around here usually show commitment
|
|
|
|
</Typography>
|
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="center">
|
2022-01-09 14:07:05 +00:00
|
|
|
{this.props.data.isMaker ?
|
2022-01-08 13:08:03 +00:00
|
|
|
<Typography component="subtitle1" variant="subtitle1">
|
2022-01-09 14:07:05 +00:00
|
|
|
<b>Lock {pn(this.props.data.bondSatoshis)} Sats to PUBLISH order </b>
|
2022-01-08 13:08:03 +00:00
|
|
|
</Typography>
|
|
|
|
:
|
|
|
|
<Typography component="subtitle1" variant="subtitle1">
|
2022-01-09 14:07:05 +00:00
|
|
|
<b>Lock {pn(this.props.data.bondSatoshis)} Sats to TAKE the order </b>
|
2022-01-08 13:08:03 +00:00
|
|
|
</Typography>
|
|
|
|
}
|
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="center">
|
2022-01-09 14:07:05 +00:00
|
|
|
<QRCode value={this.props.data.bondInvoice} size={305}/>
|
2022-01-08 13:08:03 +00:00
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<TextField
|
|
|
|
hiddenLabel
|
|
|
|
variant="filled"
|
|
|
|
size="small"
|
2022-01-09 14:07:05 +00:00
|
|
|
defaultValue={this.props.data.bondInvoice}
|
2022-01-08 13:08:03 +00:00
|
|
|
disabled="true"
|
2022-01-08 15:34:09 +00:00
|
|
|
helperText="This is a HODL LN invoice. It will not be charged if the order succeeds or expires.
|
|
|
|
It will be charged if the order is cancelled or you lose a dispute."
|
2022-01-08 13:08:03 +00:00
|
|
|
color = "secondary"
|
|
|
|
/>
|
|
|
|
</Grid>
|
|
|
|
</Grid>
|
|
|
|
);
|
|
|
|
}
|
2022-01-09 12:14:11 +00:00
|
|
|
showEscrowQRInvoice=()=>{
|
2022-01-08 17:19:30 +00:00
|
|
|
return (
|
|
|
|
<Grid container spacing={1}>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Typography component="subtitle1" variant="subtitle1">
|
2022-01-09 14:07:05 +00:00
|
|
|
<b>Deposit {pn(this.props.data.escrowSatoshis)} Sats as trade collateral </b>
|
2022-01-08 17:19:30 +00:00
|
|
|
</Typography>
|
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="center">
|
2022-01-09 14:07:05 +00:00
|
|
|
<QRCode value={this.props.data.escrowInvoice} size={305}/>
|
2022-01-08 17:19:30 +00:00
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<TextField
|
|
|
|
hiddenLabel
|
|
|
|
variant="filled"
|
|
|
|
size="small"
|
2022-01-09 14:07:05 +00:00
|
|
|
defaultValue={this.props.data.escrowInvoice}
|
2022-01-08 17:19:30 +00:00
|
|
|
disabled="true"
|
2022-01-09 12:14:11 +00:00
|
|
|
helperText="This is a HODL LN invoice. It will be charged once the buyer confirms he sent the fiat."
|
2022-01-08 17:19:30 +00:00
|
|
|
color = "secondary"
|
|
|
|
/>
|
|
|
|
</Grid>
|
|
|
|
</Grid>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-01-09 01:23:13 +00:00
|
|
|
showTakerFound=()=>{
|
|
|
|
|
2022-01-09 14:07:05 +00:00
|
|
|
// TODO Make some sound here! The maker might have been waiting for long
|
2022-01-09 01:23:13 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<Grid container spacing={1}>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Typography component="subtitle1" variant="subtitle1">
|
|
|
|
<b>A taker has been found! </b>
|
|
|
|
</Typography>
|
|
|
|
</Grid>
|
|
|
|
<Divider/>
|
|
|
|
<Grid item xs={12} align="center">
|
2022-01-09 15:28:12 +00:00
|
|
|
<Typography component="body2" variant="body2">
|
2022-01-09 01:23:13 +00:00
|
|
|
Please wait for the taker to confirm his commitment by locking a bond.
|
|
|
|
</Typography>
|
|
|
|
</Grid>
|
|
|
|
</Grid>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-01-08 15:34:09 +00:00
|
|
|
showMakerWait=()=>{
|
|
|
|
return (
|
|
|
|
<Grid container spacing={1}>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Typography component="subtitle1" variant="subtitle1">
|
|
|
|
<b> Your order is public, wait for a taker. </b>
|
|
|
|
</Typography>
|
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
|
|
|
|
<List dense="true">
|
|
|
|
<Divider/>
|
|
|
|
<ListItem>
|
|
|
|
<Typography component="body2" variant="body2" align="left">
|
|
|
|
<p>Be patient while robots check the book.
|
|
|
|
It might take some time. This box will ring 🔊 once a robot takes your order. </p>
|
|
|
|
<p>Please note that if your premium is too high, or if your currency or payment
|
|
|
|
methods are not popular, your order might expire untaken. Your bond will
|
|
|
|
return to you (no action needed).</p>
|
|
|
|
</Typography>
|
|
|
|
</ListItem>
|
|
|
|
|
|
|
|
{/* TODO API sends data for a more confortable wait */}
|
|
|
|
<Divider/>
|
|
|
|
<ListItem>
|
|
|
|
<ListItemText primary={999} secondary="Robots looking at the book"/>
|
|
|
|
</ListItem>
|
|
|
|
|
|
|
|
<Divider/>
|
|
|
|
<ListItem>
|
2022-01-09 14:07:05 +00:00
|
|
|
<ListItemText primary={999} secondary={"Active orders for " + this.props.data.currencyCode}/>
|
2022-01-08 15:34:09 +00:00
|
|
|
</ListItem>
|
|
|
|
|
|
|
|
<Divider/>
|
|
|
|
<ListItem>
|
|
|
|
<ListItemText primary="33%" secondary="Premium percentile" />
|
|
|
|
</ListItem>
|
|
|
|
</List>
|
|
|
|
</Grid>
|
|
|
|
</Grid>
|
|
|
|
)
|
|
|
|
}
|
2022-01-08 13:08:03 +00:00
|
|
|
|
2022-01-09 14:07:05 +00:00
|
|
|
handleInputInvoiceChanged=(e)=>{
|
|
|
|
this.setState({
|
|
|
|
invoice: e.target.value,
|
|
|
|
});
|
|
|
|
}
|
2022-01-09 12:14:11 +00:00
|
|
|
|
2022-01-09 15:28:12 +00:00
|
|
|
// Fix this, clunky because it takes time. this.props.data does not refresh until next refresh of OrderPage.
|
|
|
|
|
2022-01-09 14:07:05 +00:00
|
|
|
handleClickSubmitInvoiceButton=()=>{
|
|
|
|
const requestOptions = {
|
|
|
|
method: 'POST',
|
|
|
|
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),},
|
|
|
|
body: JSON.stringify({
|
|
|
|
'action':'update_invoice',
|
|
|
|
'invoice': this.state.invoice,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
|
|
|
|
.then((response) => response.json())
|
|
|
|
.then((data) => (this.props.data = data));
|
|
|
|
}
|
2022-01-09 12:14:11 +00:00
|
|
|
|
2022-01-09 14:07:05 +00:00
|
|
|
showInputInvoice(){
|
|
|
|
return (
|
2022-01-09 12:14:11 +00:00
|
|
|
|
2022-01-09 14:07:05 +00:00
|
|
|
// TODO Camera option to read QR
|
|
|
|
|
|
|
|
<Grid container spacing={1}>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Typography component="subtitle1" variant="subtitle1">
|
|
|
|
<b> Submit a LN invoice for {pn(this.props.data.invoiceAmount)} Sats </b>
|
|
|
|
</Typography>
|
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="left">
|
|
|
|
<Typography component="body2" variant="body2">
|
|
|
|
The taker is committed! Before letting you send {" "+ parseFloat(parseFloat(this.props.data.amount).toFixed(4))+
|
|
|
|
" "+ this.props.data.currencyCode}, we want to make sure you are able to receive the BTC. Please provide a
|
|
|
|
valid invoice for {pn(this.props.data.invoiceAmount)} Satoshis.
|
|
|
|
</Typography>
|
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<TextField
|
|
|
|
label={"Payout Lightning Invoice"}
|
|
|
|
required
|
|
|
|
inputProps={{
|
|
|
|
style: {textAlign:"center"}
|
|
|
|
}}
|
|
|
|
multiline
|
|
|
|
onChange={this.handleInputInvoiceChanged}
|
|
|
|
/>
|
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Button variant='contained' color='primary' onClick={this.handleClickSubmitInvoiceButton}>Submit</Button>
|
|
|
|
</Grid>
|
|
|
|
</Grid>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
showWaitingForEscrow(){
|
|
|
|
|
2022-01-09 15:28:12 +00:00
|
|
|
return(
|
|
|
|
<Grid container spacing={1}>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Typography component="subtitle1" variant="subtitle1">
|
|
|
|
<b>Your invoice looks good!</b>
|
|
|
|
</Typography>
|
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Typography component="body2" variant="body2" align="left">
|
|
|
|
<p>We are waiting for the seller to deposit the full trade BTC amount
|
|
|
|
into the escrow.</p>
|
|
|
|
<p> Just hang on for a moment. If the seller does not deposit,
|
|
|
|
you will get your bond back automatically.</p>
|
|
|
|
</Typography>
|
|
|
|
</Grid>
|
|
|
|
</Grid>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
showWaitingForBuyerInvoice(){
|
|
|
|
|
|
|
|
return(
|
|
|
|
<Grid container spacing={1}>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Typography component="subtitle1" variant="subtitle1">
|
|
|
|
<b>The trade collateral is locked! :D </b>
|
|
|
|
</Typography>
|
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Typography component="body2" variant="body2" align="left">
|
|
|
|
<p> We are waiting for the buyer to post a lightning invoice. Once
|
|
|
|
he does, you will be able to directly communicate the fiat payment
|
|
|
|
details. </p>
|
|
|
|
<p> Just hang on for a moment. If the buyer does not cooperate,
|
|
|
|
you will get back the trade collateral and your bond automatically.</p>
|
|
|
|
</Typography>
|
|
|
|
</Grid>
|
|
|
|
</Grid>
|
|
|
|
)
|
2022-01-09 14:07:05 +00:00
|
|
|
}
|
2022-01-09 12:14:11 +00:00
|
|
|
|
2022-01-09 15:28:12 +00:00
|
|
|
handleClickFiatConfirmButton=()=>{
|
|
|
|
const requestOptions = {
|
|
|
|
method: 'POST',
|
|
|
|
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),},
|
|
|
|
body: JSON.stringify({
|
|
|
|
'action':'confirm',
|
|
|
|
'invoice': this.state.invoice,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
|
|
|
|
.then((response) => response.json())
|
|
|
|
.then((data) => (this.props.data = data));
|
|
|
|
}
|
2022-01-09 12:14:11 +00:00
|
|
|
|
|
|
|
|
2022-01-09 15:28:12 +00:00
|
|
|
showFiatSentButton(){
|
|
|
|
return(
|
|
|
|
<Grid container spacing={1}>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Button variant='contained' color='primary' onClick={this.handleClickFiatConfirmButton}>Confirm {this.props.data.currencyCode} was sent. </Button>
|
|
|
|
</Grid>
|
|
|
|
</Grid>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-01-09 12:35:19 +00:00
|
|
|
// showFiatReceivedButton(){
|
2022-01-09 12:14:11 +00:00
|
|
|
|
2022-01-09 12:35:19 +00:00
|
|
|
// }
|
2022-01-09 12:14:11 +00:00
|
|
|
|
2022-01-09 12:35:19 +00:00
|
|
|
// showOpenDisputeButton(){
|
2022-01-09 12:14:11 +00:00
|
|
|
|
2022-01-09 12:35:19 +00:00
|
|
|
// }
|
2022-01-09 12:14:11 +00:00
|
|
|
|
2022-01-09 12:35:19 +00:00
|
|
|
// showRateSelect(){
|
2022-01-09 12:14:11 +00:00
|
|
|
|
2022-01-09 12:35:19 +00:00
|
|
|
// }
|
2022-01-09 12:14:11 +00:00
|
|
|
|
|
|
|
|
2022-01-08 13:08:03 +00:00
|
|
|
render() {
|
|
|
|
return (
|
2022-01-08 15:34:09 +00:00
|
|
|
<Grid container spacing={1} style={{ width:330}}>
|
2022-01-08 13:08:03 +00:00
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Typography component="h5" variant="h5">
|
|
|
|
TradeBox
|
|
|
|
</Typography>
|
|
|
|
<Paper elevation={12} style={{ padding: 8,}}>
|
2022-01-09 12:14:11 +00:00
|
|
|
{/* Maker and taker Bond request */}
|
2022-01-09 14:07:05 +00:00
|
|
|
{this.props.data.bondInvoice ? this.showQRInvoice() : ""}
|
2022-01-09 12:14:11 +00:00
|
|
|
|
|
|
|
{/* Waiting for taker and taker bond request */}
|
2022-01-09 14:07:05 +00:00
|
|
|
{this.props.data.isMaker & this.props.data.statusCode == 1 ? this.showMakerWait() : ""}
|
|
|
|
{this.props.data.isMaker & this.props.data.statusCode == 3 ? this.showTakerFound() : ""}
|
2022-01-09 12:14:11 +00:00
|
|
|
|
|
|
|
{/* Send Invoice (buyer) and deposit collateral (seller) */}
|
2022-01-09 14:07:05 +00:00
|
|
|
{this.props.data.isSeller & this.props.data.escrowInvoice != null ? this.showEscrowQRInvoice() : ""}
|
|
|
|
{this.props.data.isBuyer & this.props.data.invoiceAmount != null ? this.showInputInvoice() : ""}
|
|
|
|
{this.props.data.isBuyer & this.props.data.statusCode == 7 ? this.showWaitingForEscrow() : ""}
|
|
|
|
{this.props.data.isSeller & this.props.data.statusCode == 8 ? this.showWaitingForBuyerInvoice() : ""}
|
2022-01-09 12:14:11 +00:00
|
|
|
|
|
|
|
{/* In Chatroom */}
|
2022-01-09 14:07:05 +00:00
|
|
|
{this.props.data.isBuyer & this.props.data.statusCode == 9 ? this.showChat() & this.showFiatSentButton() : ""}
|
|
|
|
{this.props.data.isSeller & this.props.data.statusCode ==9 ? this.showChat() : ""}
|
|
|
|
{this.props.data.isBuyer & this.props.data.statusCode == 10 ? this.showChat() & this.showOpenDisputeButton() : ""}
|
|
|
|
{this.props.data.isSeller & this.props.data.statusCode == 10 ? this.showChat() & this.showFiatReceivedButton() & this.showOpenDisputeButton(): ""}
|
2022-01-09 12:14:11 +00:00
|
|
|
|
|
|
|
{/* Trade Finished */}
|
2022-01-09 14:07:05 +00:00
|
|
|
{this.props.data.isSeller & this.props.data.statusCode > 12 & this.props.data.statusCode < 15 ? this.showRateSelect() : ""}
|
2022-01-09 12:14:11 +00:00
|
|
|
{/* TODO */}
|
|
|
|
{/* */}
|
|
|
|
{/* */}
|
|
|
|
|
2022-01-09 12:35:19 +00:00
|
|
|
|
2022-01-08 13:08:03 +00:00
|
|
|
</Paper>
|
|
|
|
</Grid>
|
|
|
|
</Grid>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|