2022-01-02 00:37:04 +00:00
|
|
|
import React, { Component } from 'react';
|
2022-01-09 22:17:15 +00:00
|
|
|
import { Paper, Alert, AlertTitle, Button , Grid, Typography, TextField, Select, FormHelperText, MenuItem, FormControl, Radio, FormControlLabel, RadioGroup, Menu} from "@mui/material"
|
2022-01-02 00:37:04 +00:00
|
|
|
import { Link } from 'react-router-dom'
|
2022-01-02 00:19:18 +00:00
|
|
|
|
2022-01-02 00:37:04 +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-02 00:19:18 +00:00
|
|
|
}
|
2022-01-02 00:37:04 +00:00
|
|
|
return cookieValue;
|
|
|
|
}
|
|
|
|
const csrftoken = getCookie('csrftoken');
|
2022-01-02 00:19:18 +00:00
|
|
|
|
2022-01-10 10:13:54 +00:00
|
|
|
// pretty numbers
|
|
|
|
function pn(x) {
|
|
|
|
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
|
|
}
|
|
|
|
|
2022-01-02 00:37:04 +00:00
|
|
|
export default class MakerPage extends Component {
|
|
|
|
defaultCurrency = 1;
|
|
|
|
defaultCurrencyCode = 'USD';
|
2022-01-10 01:12:58 +00:00
|
|
|
defaultPaymentMethod = "not specified";
|
2022-01-02 00:37:04 +00:00
|
|
|
defaultPremium = 0;
|
2022-01-10 01:12:58 +00:00
|
|
|
minTradeSats = 10000;
|
|
|
|
maxTradeSats = 500000;
|
2022-01-02 00:37:04 +00:00
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state={
|
2022-01-02 13:35:31 +00:00
|
|
|
isExplicit: false,
|
2022-01-02 00:37:04 +00:00
|
|
|
type: 0,
|
|
|
|
currency: this.defaultCurrency,
|
|
|
|
currencyCode: this.defaultCurrencyCode,
|
2022-01-02 09:40:19 +00:00
|
|
|
payment_method: this.defaultPaymentMethod,
|
2022-01-02 00:37:04 +00:00
|
|
|
premium: 0,
|
|
|
|
satoshis: null,
|
2022-01-08 11:51:55 +00:00
|
|
|
currencies_dict: {"1":"USD"}
|
2022-01-02 00:37:04 +00:00
|
|
|
}
|
2022-01-08 11:51:55 +00:00
|
|
|
this.getCurrencyDict()
|
2022-01-02 00:37:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleTypeChange=(e)=>{
|
|
|
|
this.setState({
|
|
|
|
type: e.target.value,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
handleCurrencyChange=(e)=>{
|
|
|
|
this.setState({
|
|
|
|
currency: e.target.value,
|
2022-01-08 11:51:55 +00:00
|
|
|
currencyCode: this.getCurrencyCode(e.target.value),
|
2022-01-02 00:37:04 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
handleAmountChange=(e)=>{
|
|
|
|
this.setState({
|
|
|
|
amount: e.target.value,
|
|
|
|
});
|
|
|
|
}
|
2022-01-02 09:40:19 +00:00
|
|
|
handlePaymentMethodChange=(e)=>{
|
|
|
|
this.setState({
|
|
|
|
payment_method: e.target.value,
|
|
|
|
});
|
|
|
|
}
|
2022-01-02 00:37:04 +00:00
|
|
|
handlePremiumChange=(e)=>{
|
|
|
|
this.setState({
|
|
|
|
premium: e.target.value,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
handleSatoshisChange=(e)=>{
|
2022-01-10 01:12:58 +00:00
|
|
|
var bad_sats = e.target.value > this.maxTradeSats ?
|
2022-01-10 10:13:54 +00:00
|
|
|
("Must be less than "+pn(this.maxTradeSats)):
|
2022-01-10 01:12:58 +00:00
|
|
|
(e.target.value < this.minTradeSats ?
|
2022-01-10 10:13:54 +00:00
|
|
|
("Must be more than "+pn(this.minTradeSats)): null)
|
2022-01-10 01:12:58 +00:00
|
|
|
|
2022-01-02 00:37:04 +00:00
|
|
|
this.setState({
|
2022-01-10 01:12:58 +00:00
|
|
|
satoshis: e.target.value,
|
|
|
|
badSatoshis: bad_sats,
|
|
|
|
})
|
|
|
|
;
|
2022-01-02 00:19:18 +00:00
|
|
|
}
|
2022-01-02 00:37:04 +00:00
|
|
|
handleClickRelative=(e)=>{
|
|
|
|
this.setState({
|
2022-01-02 13:35:31 +00:00
|
|
|
isExplicit: false,
|
2022-01-02 00:37:04 +00:00
|
|
|
satoshis: null,
|
|
|
|
premium: 0,
|
|
|
|
});
|
|
|
|
}
|
2022-01-04 13:47:37 +00:00
|
|
|
handleClickExplicit=(e)=>{
|
2022-01-02 00:37:04 +00:00
|
|
|
this.setState({
|
2022-01-02 13:35:31 +00:00
|
|
|
isExplicit: true,
|
2022-01-02 00:37:04 +00:00
|
|
|
premium: null,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
handleCreateOfferButtonPressed=()=>{
|
2022-01-10 10:36:37 +00:00
|
|
|
this.state.amount == null ? this.setState({amount: 0}) : null;
|
|
|
|
|
2022-01-02 00:37:04 +00:00
|
|
|
console.log(this.state)
|
|
|
|
const requestOptions = {
|
|
|
|
method: 'POST',
|
2022-01-05 00:13:08 +00:00
|
|
|
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken')},
|
2022-01-02 00:37:04 +00:00
|
|
|
body: JSON.stringify({
|
|
|
|
type: this.state.type,
|
|
|
|
currency: this.state.currency,
|
|
|
|
amount: this.state.amount,
|
2022-01-02 09:40:19 +00:00
|
|
|
payment_method: this.state.payment_method,
|
2022-01-02 13:35:31 +00:00
|
|
|
is_explicit: this.state.isExplicit,
|
2022-01-02 00:37:04 +00:00
|
|
|
premium: this.state.premium,
|
|
|
|
satoshis: this.state.satoshis,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
fetch("/api/make/",requestOptions)
|
|
|
|
.then((response) => response.json())
|
2022-01-07 11:31:33 +00:00
|
|
|
.then((data) => (this.setState({badRequest:data.bad_request})
|
|
|
|
& (data.id ? this.props.history.push('/order/' + data.id) :"")));
|
2022-01-02 00:37:04 +00:00
|
|
|
}
|
|
|
|
|
2022-01-08 11:51:55 +00:00
|
|
|
getCurrencyDict() {
|
2022-01-09 14:29:10 +00:00
|
|
|
fetch('/static/assets/currencies.json')
|
2022-01-08 11:51:55 +00:00
|
|
|
.then((response) => response.json())
|
|
|
|
.then((data) =>
|
|
|
|
this.setState({
|
|
|
|
currencies_dict: data
|
|
|
|
}));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
getCurrencyCode(val){
|
|
|
|
return this.state.currencies_dict[val.toString()]
|
2022-01-02 00:37:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
return (
|
2022-01-10 01:12:58 +00:00
|
|
|
<Grid container xs={12} align="center" spacing={1}>
|
2022-01-03 19:15:13 +00:00
|
|
|
<Grid item xs={12} align="center">
|
2022-01-10 01:12:58 +00:00
|
|
|
<Typography component="h2" variant="h2">
|
|
|
|
Order Maker
|
2022-01-03 19:15:13 +00:00
|
|
|
</Typography>
|
|
|
|
</Grid>
|
2022-01-10 01:12:58 +00:00
|
|
|
<Grid item xs={12} align="center" spacing={1}>
|
|
|
|
<Paper elevation={12} style={{ padding: 8, width:350, align:'center'}}>
|
|
|
|
<Grid item xs={12} align="center" spacing={1}>
|
2022-01-03 19:15:13 +00:00
|
|
|
<FormControl component="fieldset">
|
2022-01-10 01:12:58 +00:00
|
|
|
<FormHelperText>
|
|
|
|
Buy or Sell Bitcoin?
|
|
|
|
</FormHelperText>
|
2022-01-03 19:15:13 +00:00
|
|
|
<RadioGroup row defaultValue="0" onChange={this.handleTypeChange}>
|
|
|
|
<FormControlLabel
|
|
|
|
value="0"
|
|
|
|
control={<Radio color="primary"/>}
|
|
|
|
label="Buy"
|
|
|
|
labelPlacement="Top"
|
|
|
|
/>
|
|
|
|
<FormControlLabel
|
|
|
|
value="1"
|
|
|
|
control={<Radio color="secondary"/>}
|
|
|
|
label="Sell"
|
|
|
|
labelPlacement="Top"
|
|
|
|
/>
|
|
|
|
</RadioGroup>
|
|
|
|
</FormControl>
|
|
|
|
</Grid>
|
2022-01-10 01:12:58 +00:00
|
|
|
<Grid container xs={11} align="center">
|
2022-01-10 10:27:34 +00:00
|
|
|
<TextField
|
|
|
|
error={this.state.amount == 0}
|
|
|
|
helperText={this.state.amount == 0 ? 'Must be more than 0' : null}
|
2022-01-10 01:12:58 +00:00
|
|
|
label="Amount"
|
|
|
|
type="number"
|
|
|
|
required="true"
|
|
|
|
inputProps={{
|
|
|
|
min:0 ,
|
|
|
|
style: {textAlign:"center"}
|
|
|
|
}}
|
|
|
|
onChange={this.handleAmountChange}
|
|
|
|
/>
|
|
|
|
<Select
|
|
|
|
required="true"
|
|
|
|
defaultValue={this.defaultCurrency}
|
|
|
|
inputProps={{
|
|
|
|
style: {textAlign:"center"}
|
|
|
|
}}
|
|
|
|
onChange={this.handleCurrencyChange}
|
|
|
|
>
|
|
|
|
{
|
|
|
|
Object.entries(this.state.currencies_dict)
|
|
|
|
.map( ([key, value]) => <MenuItem value={parseInt(key)}>{value}</MenuItem> )
|
|
|
|
}
|
|
|
|
</Select>
|
2022-01-03 19:15:13 +00:00
|
|
|
|
2022-01-10 01:12:58 +00:00
|
|
|
</Grid>
|
|
|
|
<br/>
|
2022-01-03 19:15:13 +00:00
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<FormControl >
|
2022-01-03 14:27:25 +00:00
|
|
|
<TextField
|
2022-01-03 19:15:13 +00:00
|
|
|
label="Payment Method(s)"
|
|
|
|
type="text"
|
|
|
|
require={true}
|
|
|
|
inputProps={{
|
2022-01-07 18:22:52 +00:00
|
|
|
style: {textAlign:"center"},
|
2022-01-08 00:29:04 +00:00
|
|
|
maxLength: 35
|
2022-01-03 19:15:13 +00:00
|
|
|
}}
|
|
|
|
onChange={this.handlePaymentMethodChange}
|
|
|
|
/>
|
|
|
|
</FormControl>
|
|
|
|
</Grid>
|
2022-01-10 01:12:58 +00:00
|
|
|
|
2022-01-03 19:15:13 +00:00
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<FormControl component="fieldset">
|
2022-01-10 01:12:58 +00:00
|
|
|
<FormHelperText >
|
|
|
|
<div align='center'>
|
|
|
|
Choose a Pricing Method
|
|
|
|
</div>
|
|
|
|
</FormHelperText>
|
2022-01-03 19:15:13 +00:00
|
|
|
<RadioGroup row defaultValue="relative">
|
|
|
|
<FormControlLabel
|
|
|
|
value="relative"
|
|
|
|
control={<Radio color="primary"/>}
|
|
|
|
label="Relative"
|
|
|
|
labelPlacement="Top"
|
|
|
|
onClick={this.handleClickRelative}
|
2022-01-03 14:27:25 +00:00
|
|
|
/>
|
2022-01-03 19:15:13 +00:00
|
|
|
<FormControlLabel
|
|
|
|
value="explicit"
|
|
|
|
control={<Radio color="secondary"/>}
|
|
|
|
label="Explicit"
|
|
|
|
labelPlacement="Top"
|
2022-01-04 13:47:37 +00:00
|
|
|
onClick={this.handleClickExplicit}
|
2022-01-03 14:27:25 +00:00
|
|
|
/>
|
2022-01-03 19:15:13 +00:00
|
|
|
</RadioGroup>
|
|
|
|
</FormControl>
|
|
|
|
</Grid>
|
|
|
|
{/* conditional shows either Premium % field or Satoshis field based on pricing method */}
|
|
|
|
{ this.state.isExplicit
|
|
|
|
? <Grid item xs={12} align="center">
|
|
|
|
<TextField
|
2022-01-10 01:12:58 +00:00
|
|
|
label="Satoshis"
|
|
|
|
error={this.state.badSatoshis}
|
2022-01-10 10:13:54 +00:00
|
|
|
helperText={this.state.badSatoshis}
|
2022-01-03 19:15:13 +00:00
|
|
|
type="number"
|
|
|
|
required="true"
|
|
|
|
inputProps={{
|
|
|
|
// TODO read these from .env file
|
2022-01-10 01:12:58 +00:00
|
|
|
min:this.minTradeSats ,
|
|
|
|
max:this.maxTradeSats ,
|
2022-01-03 19:15:13 +00:00
|
|
|
style: {textAlign:"center"}
|
|
|
|
}}
|
|
|
|
onChange={this.handleSatoshisChange}
|
|
|
|
// defaultValue={this.defaultSatoshis}
|
|
|
|
/>
|
|
|
|
</Grid>
|
|
|
|
: <Grid item xs={12} align="center">
|
|
|
|
<TextField
|
|
|
|
label="Premium over Market (%)"
|
|
|
|
type="number"
|
|
|
|
// defaultValue={this.defaultPremium}
|
|
|
|
inputProps={{
|
|
|
|
style: {textAlign:"center"}
|
|
|
|
}}
|
|
|
|
onChange={this.handlePremiumChange}
|
|
|
|
/>
|
|
|
|
</Grid>
|
|
|
|
}
|
|
|
|
</Paper>
|
2022-01-10 01:12:58 +00:00
|
|
|
</Grid>
|
2022-01-02 00:37:04 +00:00
|
|
|
<Grid item xs={12} align="center">
|
2022-01-03 23:05:19 +00:00
|
|
|
<Button color="primary" variant="contained" onClick={this.handleCreateOfferButtonPressed} >
|
2022-01-02 09:40:19 +00:00
|
|
|
Create Order
|
|
|
|
</Button>
|
2022-01-07 11:31:33 +00:00
|
|
|
</Grid>
|
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
{this.state.badRequest ?
|
|
|
|
<Typography component="subtitle2" variant="subtitle2" color="secondary">
|
|
|
|
{this.state.badRequest} <br/>
|
|
|
|
</Typography>
|
|
|
|
: ""}
|
2022-01-02 00:37:04 +00:00
|
|
|
<Typography component="subtitle2" variant="subtitle2">
|
|
|
|
<div align='center'>
|
|
|
|
Create a BTC {this.state.type==0 ? "buy":"sell"} order for {this.state.amount} {this.state.currencyCode}
|
2022-01-02 13:35:31 +00:00
|
|
|
{this.state.isExplicit ? " of " + this.state.satoshis + " Satoshis" :
|
2022-01-02 00:37:04 +00:00
|
|
|
(this.state.premium == 0 ? " at market price" :
|
|
|
|
(this.state.premium > 0 ? " at a " + this.state.premium + "% premium":" at a " + -this.state.premium + "% discount")
|
|
|
|
)
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
</Typography>
|
2022-01-03 23:05:19 +00:00
|
|
|
<Grid item xs={12} align="center">
|
|
|
|
<Button color="secondary" variant="contained" to="/" component={Link}>
|
|
|
|
Back
|
|
|
|
</Button>
|
|
|
|
</Grid>
|
2022-01-02 00:37:04 +00:00
|
|
|
</Grid>
|
|
|
|
</Grid>
|
|
|
|
);
|
|
|
|
}
|
2022-01-02 00:19:18 +00:00
|
|
|
}
|