2022-01-02 00:37:04 +00:00
import React , { Component } from 'react' ;
2022-03-05 17:32:27 +00:00
import { Tooltip , Paper , Button , Grid , Typography , TextField , Select , FormHelperText , MenuItem , FormControl , Radio , FormControlLabel , RadioGroup } from "@mui/material"
2022-01-02 00:37:04 +00:00
import { Link } from 'react-router-dom'
2022-01-16 18:32:34 +00:00
import getFlags from './getFlags'
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 ) {
2022-02-01 00:45:58 +00:00
if ( x == null ) {
return ( null )
}
2022-02-17 02:45:18 +00:00
var parts = x . toString ( ) . split ( "." ) ;
parts [ 0 ] = parts [ 0 ] . replace ( /\B(?=(\d{3})+(?!\d))/g , "," ) ;
return parts . join ( "." ) ;
2022-01-10 10:13:54 +00:00
}
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-03-07 17:04:29 +00:00
minTradeSats = 20000 ;
maxTradeSats = 800000 ;
2022-01-02 00:37:04 +00:00
constructor ( props ) {
super ( props ) ;
this . state = {
2022-01-27 17:43:17 +00:00
is _explicit : 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 ( {
2022-02-01 00:45:58 +00:00
payment _method : e . target . value ,
badPaymentMethod : e . target . value . length > 35 ,
2022-01-02 09:40:19 +00:00
} ) ;
}
2022-01-02 00:37:04 +00:00
handlePremiumChange = ( e ) => {
2022-02-01 00:45:58 +00:00
if ( e . target . value > 999 ) {
var bad _premium = "Must be less than 999%"
}
if ( e . target . value < - 100 ) {
var bad _premium = "Must be more than -100%"
}
2022-01-02 00:37:04 +00:00
this . setState ( {
2022-02-01 00:45:58 +00:00
premium : e . target . value ,
badPremium : bad _premium ,
2022-01-02 00:37:04 +00:00
} ) ;
}
2022-02-01 00:45:58 +00:00
2022-01-02 00:37:04 +00:00
handleSatoshisChange = ( e ) => {
2022-02-01 00:45:58 +00:00
if ( e . target . value > this . maxTradeSats ) {
var bad _sats = "Must be less than " + pn ( this . maxTradeSats )
}
if ( e . target . value < this . minTradeSats ) {
var bad _sats = "Must be more than " + pn ( this . minTradeSats )
}
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-02-01 00:45:58 +00:00
} ) ;
2022-01-02 00:19:18 +00:00
}
2022-01-02 00:37:04 +00:00
handleClickRelative = ( e ) => {
this . setState ( {
2022-01-27 17:43:17 +00:00
is _explicit : false ,
2022-01-02 00:37:04 +00:00
} ) ;
2022-01-31 22:42:43 +00:00
this . handlePremiumChange ( ) ;
2022-01-02 00:37:04 +00:00
}
2022-01-31 22:42:43 +00:00
2022-01-04 13:47:37 +00:00
handleClickExplicit = ( e ) => {
2022-01-02 00:37:04 +00:00
this . setState ( {
2022-01-31 22:42:43 +00:00
is _explicit : true ,
2022-01-02 00:37:04 +00:00
} ) ;
2022-01-31 22:42:43 +00:00
this . handleSatoshisChange ( ) ;
2022-01-02 00:37:04 +00:00
}
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
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-27 17:43:17 +00:00
is _explicit : this . state . is _explicit ,
2022-02-01 00:45:58 +00:00
premium : this . state . is _explicit ? null : this . state . premium ,
satoshis : this . state . is _explicit ? this . state . satoshis : null ,
2022-01-02 00:37:04 +00:00
} ) ,
} ;
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
}
2022-02-01 00:45:58 +00:00
2022-01-02 00:37:04 +00:00
render ( ) {
return (
2022-02-04 01:37:24 +00:00
< Grid container xs = { 12 } align = "center" spacing = { 1 } sx = { { minWidth : 380 } } >
{ / * < G r i d i t e m x s = { 1 2 } a l i g n = " c e n t e r " s x = { { m i n W i d t h : 3 8 0 } } >
< Typography component = "h4" variant = "h4" >
ORDER MAKER
2022-01-03 19:15:13 +00:00
< / T y p o g r a p h y >
2022-02-04 01:37:24 +00:00
< /Grid> */ }
2022-01-10 01:12:58 +00:00
< Grid item xs = { 12 } align = "center" spacing = { 1 } >
2022-02-01 00:45:58 +00:00
< Paper elevation = { 12 } style = { { padding : 8 , width : 240 , align : 'center' } } >
2022-01-10 01:12:58 +00:00
< 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 ?
< / F o r m H e l p e r T e x t >
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"
/ >
< / R a d i o G r o u p >
< / F o r m C o n t r o l >
< / G r i d >
2022-02-01 00:45:58 +00:00
< Grid containter xs = { 12 } alignItems = "stretch" style = { { display : "flex" } } >
< div style = { { maxWidth : 140 } } >
2022-02-08 16:20:41 +00:00
< Tooltip placement = "top" enterTouchDelay = "500" enterDelay = "700" enterNextDelay = "2000" title = "Amount of fiat to exchange for bitcoin" >
2022-01-10 10:27:34 +00:00
< TextField
2022-02-01 00:45:58 +00:00
error = { this . state . amount <= 0 }
helperText = { this . state . amount <= 0 ? 'Invalid' : null }
2022-01-10 01:12:58 +00:00
label = "Amount"
type = "number"
required = "true"
inputProps = { {
min : 0 ,
style : { textAlign : "center" }
} }
onChange = { this . handleAmountChange }
2022-02-01 22:05:49 +00:00
/ >
< / T o o l t i p >
< / d i v >
2022-02-01 00:45:58 +00:00
< div >
< 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 ) } >
2022-02-19 18:44:02 +00:00
< div style = { { display : 'flex' , alignItems : 'center' , flexWrap : 'wrap' } } > { getFlags ( value ) } { " " + value } < / d i v >
2022-02-01 00:45:58 +00:00
< / M e n u I t e m > ) }
< / S e l e c t >
< / d i v >
2022-01-03 19:15:13 +00:00
2022-01-10 01:12:58 +00:00
< / G r i d >
< br / >
2022-01-03 19:15:13 +00:00
< Grid item xs = { 12 } align = "center" >
2022-02-27 21:35:37 +00:00
< Tooltip placement = "top" enterTouchDelay = "300" enterDelay = "700" enterNextDelay = "2000" title = "Enter your prefered fiat payment methods (instant recommended)" >
2022-01-03 14:27:25 +00:00
< TextField
2022-02-01 00:45:58 +00:00
sx = { { width : 240 } }
2022-02-27 21:35:37 +00:00
label = { this . state . currency == 1000 ? "Swap Destination (e.g. rBTC)" : "Fiat Payment Method(s)" }
2022-02-01 00:45:58 +00:00
error = { this . state . badPaymentMethod }
helperText = { this . state . badPaymentMethod ? "Must be shorter than 35 characters" : "" }
2022-01-03 19:15:13 +00:00
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 }
/ >
2022-02-01 22:05:49 +00:00
< / T o o l t i p >
2022-01-03 19:15:13 +00:00
< / G r i d >
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
< / d i v >
< / F o r m H e l p e r T e x t >
2022-01-03 19:15:13 +00:00
< RadioGroup row defaultValue = "relative" >
2022-02-08 16:20:41 +00:00
< Tooltip placement = "top" enterTouchDelay = "0" enterDelay = "1000" enterNextDelay = "2000" title = "Let the price move with the market" >
2022-01-03 19:15:13 +00:00
< FormControlLabel
value = "relative"
control = { < Radio color = "primary" / > }
label = "Relative"
labelPlacement = "Top"
onClick = { this . handleClickRelative }
2022-01-03 14:27:25 +00:00
/ >
2022-02-01 22:05:49 +00:00
< / T o o l t i p >
2022-02-08 16:20:41 +00:00
< Tooltip placement = "top" enterTouchDelay = "0" enterDelay = "1000" enterNextDelay = "2000" title = "Set a fix amount of satoshis" >
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-02-01 22:05:49 +00:00
< / T o o l t i p >
2022-01-03 19:15:13 +00:00
< / R a d i o G r o u p >
< / F o r m C o n t r o l >
< / G r i d >
{ /* conditional shows either Premium % field or Satoshis field based on pricing method */ }
2022-01-31 22:42:43 +00:00
< Grid item xs = { 12 } align = "center" >
< div style = { { display : this . state . is _explicit ? '' : 'none' } } >
2022-02-01 00:45:58 +00:00
< TextField
sx = { { width : 240 } }
2022-01-31 22:42:43 +00:00
label = "Satoshis"
error = { this . state . badSatoshis }
helperText = { this . state . badSatoshis }
type = "number"
required = "true"
value = { this . state . satoshis }
inputProps = { {
// TODO read these from .env file
min : this . minTradeSats ,
max : this . maxTradeSats ,
style : { textAlign : "center" }
} }
onChange = { this . handleSatoshisChange }
// defaultValue={this.defaultSatoshis}
/ >
< / d i v >
< div style = { { display : this . state . is _explicit ? 'none' : '' } } >
2022-01-03 19:15:13 +00:00
< TextField
2022-02-01 00:45:58 +00:00
sx = { { width : 240 } }
error = { this . state . badPremium }
helperText = { this . state . badPremium }
2022-01-03 19:15:13 +00:00
label = "Premium over Market (%)"
type = "number"
// defaultValue={this.defaultPremium}
inputProps = { {
2022-02-01 00:45:58 +00:00
min : - 100 ,
max : 999 ,
2022-01-03 19:15:13 +00:00
style : { textAlign : "center" }
} }
onChange = { this . handlePremiumChange }
/ >
2022-01-31 22:42:43 +00:00
< / d i v >
< / G r i d >
2022-01-03 19:15:13 +00:00
< / P a p e r >
2022-01-10 01:12:58 +00:00
< / G r i d >
2022-01-02 00:37:04 +00:00
< Grid item xs = { 12 } align = "center" >
2022-02-02 09:29:05 +00:00
{ /* conditions to disable the make button */ }
{ ( this . state . amount == null ||
this . state . amount <= 0 ||
( this . state . is _explicit & ( this . state . badSatoshis != null || this . state . satoshis == null ) ) ||
( ! this . state . is _explicit & this . state . badPremium != null ) )
?
< Tooltip enterTouchDelay = "0" title = "You must fill the form correctly" >
< div > < Button disabled color = "primary" variant = "contained" onClick = { this . handleCreateOfferButtonPressed } > Create Order < / B u t t o n > < / d i v >
< / T o o l t i p >
:
< Button color = "primary" variant = "contained" onClick = { this . handleCreateOfferButtonPressed } > Create Order < / B u t t o n >
}
2022-01-07 11:31:33 +00:00
< / G r i d >
< Grid item xs = { 12 } align = "center" >
{ this . state . badRequest ?
< Typography component = "subtitle2" variant = "subtitle2" color = "secondary" >
{ this . state . badRequest } < br / >
< / T y p o g r a p h y >
: "" }
2022-01-02 00:37:04 +00:00
< Typography component = "subtitle2" variant = "subtitle2" >
< div align = 'center' >
2022-02-01 00:45:58 +00:00
Create a BTC { this . state . type == 0 ? "buy" : "sell" } order for { pn ( this . state . amount ) } { this . state . currencyCode }
{ this . state . is _explicit ? " of " + pn ( 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" )
)
}
< / d i v >
< / T y p o g r a p h y >
2022-01-03 23:05:19 +00:00
< Grid item xs = { 12 } align = "center" >
< Button color = "secondary" variant = "contained" to = "/" component = { Link } >
Back
< / B u t t o n >
< / G r i d >
2022-01-02 00:37:04 +00:00
< / G r i d >
< / G r i d >
) ;
}
2022-01-02 00:19:18 +00:00
}