2022-01-02 00:37:04 +00:00
import React , { Component } from 'react' ;
2022-03-27 11:39:33 +00:00
import { InputAdornment , LinearProgress , Link , Checkbox , Slider , Box , Tab , Tabs , SliderThumb , Tooltip , Paper , Button , Grid , Typography , TextField , Select , FormHelperText , MenuItem , FormControl , Radio , FormControlLabel , RadioGroup } from "@mui/material"
2022-03-15 23:33:58 +00:00
import { LocalizationProvider , TimePicker } from '@mui/lab' ;
2022-03-15 20:40:54 +00:00
import DateFnsUtils from "@date-io/date-fns" ;
2022-03-24 13:41:32 +00:00
import { Link as LinkRouter } from 'react-router-dom'
2022-03-22 17:49:57 +00:00
import { styled } from '@mui/material/styles' ;
2022-03-29 23:16:59 +00:00
import getFlags from './getFlags' ;
import AutocompletePayments from './autocompletePayments' ;
2022-03-15 23:33:58 +00:00
import LockIcon from '@mui/icons-material/Lock' ;
2022-03-27 11:39:33 +00:00
import HourglassTopIcon from '@mui/icons-material/HourglassTop' ;
2022-03-15 23:33:58 +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 ) {
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-03-15 23:33:58 +00:00
maxBondlessSats = 50000 ;
2022-03-22 19:45:44 +00:00
maxRangeAmountMultiple = 4.8 ;
2022-03-22 17:49:57 +00:00
minRangeAmountMultiple = 1.6 ;
2022-03-15 23:33:58 +00:00
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-03-15 18:20:57 +00:00
currencies _dict : { "1" : "USD" } ,
showAdvanced : false ,
allowBondless : false ,
2022-03-18 21:21:13 +00:00
publicExpiryTime : new Date ( 0 , 0 , 0 , 23 , 59 ) ,
2022-03-16 13:23:48 +00:00
enableAmountRange : false ,
2022-03-15 23:33:58 +00:00
minAmount : null ,
bondSize : 1 ,
2022-03-21 15:51:26 +00:00
limits : null ,
minAmount : null ,
maxAmount : null ,
loadingLimits : false ,
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
}
2022-03-21 15:51:26 +00:00
getLimits ( ) {
this . setState ( { loadingLimits : true } )
fetch ( '/api/limits/' )
. then ( ( response ) => response . json ( ) )
. then ( ( data ) => this . setState ( {
limits : data ,
loadingLimits : false ,
2022-03-24 17:29:51 +00:00
minAmount : this . state . amount ? parseFloat ( ( this . state . amount / 2 ) . toPrecision ( 2 ) ) : parseFloat ( Number ( data [ this . state . currency ] [ 'max_amount' ] * 0.25 ) . toPrecision ( 2 ) ) ,
2022-03-24 13:41:32 +00:00
maxAmount : this . state . amount ? this . state . amount : parseFloat ( Number ( data [ this . state . currency ] [ 'max_amount' ] * 0.75 ) . toPrecision ( 2 ) ) ,
2022-03-22 17:49:57 +00:00
} ) ) ;
2022-03-21 15:51:26 +00:00
}
2022-03-24 13:41:32 +00:00
a11yProps ( index ) {
return {
id : ` simple-tab- ${ index } ` ,
'aria-controls' : ` simple-tabpanel- ${ index } ` ,
} ;
}
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
} ) ;
2022-03-22 17:49:57 +00:00
if ( this . state . enableAmountRange ) {
this . setState ( {
minAmount : parseFloat ( Number ( this . state . limits [ e . target . value ] [ 'max_amount' ] * 0.25 ) . toPrecision ( 2 ) ) ,
maxAmount : parseFloat ( Number ( this . state . limits [ e . target . value ] [ 'max_amount' ] * 0.75 ) . toPrecision ( 2 ) ) ,
} )
}
2022-01-02 00:37:04 +00:00
}
handleAmountChange = ( e ) => {
this . setState ( {
amount : e . target . value ,
} ) ;
}
2022-03-24 13:41:32 +00:00
handleMinAmountChange = ( e ) => {
this . setState ( {
minAmount : parseFloat ( Number ( e . target . value ) . toPrecision ( e . target . value < 100 ? 2 : 3 ) ) ,
} ) ;
}
handleMaxAmountChange = ( e ) => {
this . setState ( {
maxAmount : parseFloat ( Number ( e . target . value ) . toPrecision ( e . target . value < 100 ? 2 : 3 ) ) ,
} ) ;
}
2022-03-16 13:23:48 +00:00
2022-03-22 17:49:57 +00:00
handleRangeAmountChange = ( e , newValue , activeThumb ) => {
2022-03-21 15:51:26 +00:00
var maxAmount = this . getMaxAmount ( ) ;
var minAmount = this . getMinAmount ( ) ;
var lowerValue = e . target . value [ 0 ] ;
var upperValue = e . target . value [ 1 ] ;
var minRange = this . minRangeAmountMultiple ;
var maxRange = this . maxRangeAmountMultiple ;
if ( lowerValue > maxAmount / minRange ) {
lowerValue = maxAmount / minRange
}
if ( upperValue < minRange * minAmount ) {
upperValue = minRange * minAmount
}
if ( lowerValue > upperValue / minRange ) {
if ( activeThumb === 0 ) {
upperValue = minRange * lowerValue
} else {
lowerValue = upperValue / minRange
}
} else if ( lowerValue < upperValue / maxRange ) {
if ( activeThumb === 0 ) {
upperValue = maxRange * lowerValue
} else {
lowerValue = upperValue / maxRange
}
}
2022-03-24 13:41:32 +00:00
2022-03-16 13:23:48 +00:00
this . setState ( {
2022-03-24 13:41:32 +00:00
minAmount : parseFloat ( Number ( lowerValue ) . toPrecision ( lowerValue < 100 ? 2 : 3 ) ) ,
maxAmount : parseFloat ( Number ( upperValue ) . toPrecision ( upperValue < 100 ? 2 : 3 ) ) ,
2022-03-16 13:23:48 +00:00
} ) ;
}
2022-03-29 23:16:59 +00:00
handlePaymentMethodChange = ( value ) => {
2022-01-02 09:40:19 +00:00
this . setState ( {
2022-03-29 23:16:59 +00:00
payment _method : value ,
badPaymentMethod : 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-03-21 23:27:36 +00:00
has _range : this . state . enableAmountRange ,
min _amount : this . state . minAmount ,
max _amount : this . state . maxAmount ,
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-03-18 21:21:13 +00:00
public _duration : this . state . publicDuration ,
2022-03-18 22:09:38 +00:00
bond _size : this . state . bondSize ,
2022-03-21 23:27:36 +00:00
bondless _taker : this . state . allowBondless ,
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-03-15 23:33:58 +00:00
handleInputBondSizeChange = ( event ) => {
this . setState ( { bondSize : event . target . value === '' ? 1 : Number ( event . target . value ) } ) ;
} ;
2022-03-15 18:20:57 +00:00
StandardMakerOptions = ( ) => {
return (
2022-03-24 13:41:32 +00:00
< Paper elevation = { 12 } style = { { padding : 8 , width : '260px' , align : 'center' } } >
2022-03-15 18:20:57 +00:00
< Grid item xs = { 12 } align = "center" spacing = { 1 } >
2022-03-29 23:16:59 +00:00
< div style = { { position : 'relative' , left : '5px' } } >
2022-03-15 18:20:57 +00:00
< FormControl component = "fieldset" >
< FormHelperText >
Buy or Sell Bitcoin ?
< / F o r m H e l p e r T e x t >
< 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 >
2022-03-29 23:16:59 +00:00
< / d i v >
2022-03-15 18:20:57 +00:00
< / G r i d >
2022-03-24 13:41:32 +00:00
2022-03-15 18:20:57 +00:00
< Grid containter xs = { 12 } alignItems = "stretch" style = { { display : "flex" } } >
2022-03-29 23:16:59 +00:00
< div style = { { maxWidth : 150 } } >
2022-03-15 18:20:57 +00:00
< Tooltip placement = "top" enterTouchDelay = "500" enterDelay = "700" enterNextDelay = "2000" title = "Amount of fiat to exchange for bitcoin" >
< TextField
2022-03-21 15:51:26 +00:00
disabled = { this . state . enableAmountRange }
2022-03-21 23:27:36 +00:00
variant = { this . state . enableAmountRange ? 'filled' : 'outlined' }
2022-03-21 15:51:26 +00:00
error = { this . state . amount <= 0 & this . state . amount != "" }
helperText = { this . state . amount <= 0 & this . state . amount != "" ? 'Invalid' : null }
2022-03-15 18:20:57 +00:00
label = "Amount"
type = "number"
required = "true"
2022-03-21 15:51:26 +00:00
value = { this . state . amount }
2022-03-15 18:20:57 +00:00
inputProps = { {
min : 0 ,
style : { textAlign : "center" }
} }
onChange = { this . handleAmountChange }
/ >
< / T o o l t i p >
< / d i v >
< div >
< Select
2022-03-29 23:16:59 +00:00
sx = { { width : '120px' } }
2022-03-15 18:20:57 +00:00
required = "true"
defaultValue = { this . defaultCurrency }
2022-01-10 01:12:58 +00:00
inputProps = { {
style : { textAlign : "center" }
} }
2022-03-15 18:20:57 +00:00
onChange = { this . handleCurrencyChange } >
{ Object . entries ( this . state . currencies _dict )
. map ( ( [ key , value ] ) => < MenuItem value = { parseInt ( key ) } >
< div style = { { display : 'flex' , alignItems : 'center' , flexWrap : 'wrap' } } > { getFlags ( value ) } { " " + value } < / d i v >
< / 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-03-15 18:20:57 +00:00
< / G r i d >
< Grid item xs = { 12 } align = "center" >
2022-03-29 23:16:59 +00:00
< Tooltip placement = "top" enterTouchDelay = "300" enterDelay = "700" enterNextDelay = "2000" title = "Enter your preferred fiat payment methods. Fast methods are highly recommended." >
{ / * < T e x t F i e l d
2022-03-15 18:20:57 +00:00
sx = { { width : 240 } }
label = { this . state . currency == 1000 ? "Swap Destination (e.g. rBTC)" : "Fiat Payment Method(s)" }
error = { this . state . badPaymentMethod }
helperText = { this . state . badPaymentMethod ? "Must be shorter than 35 characters" : "" }
type = "text"
require = { true }
inputProps = { {
style : { textAlign : "center" } ,
maxLength : 35
} }
onChange = { this . handlePaymentMethodChange }
2022-03-29 23:16:59 +00:00
/> */ }
< AutocompletePayments
onAutocompleteChange = { this . handlePaymentMethodChange }
// inputProps={{
// style: {textAlign:"center"},
// maxLength: 35
// }}
type = "text"
error = { this . state . badPaymentMethod }
helperText = { this . state . badPaymentMethod ? "Must be shorter than 35 characters" : "" }
label = { this . state . currency == 1000 ? "Swap Destination (e.g. rBTC)" : "Fiat Payment Method(s)" }
/ >
2022-03-15 18:20:57 +00:00
< / T o o l t i p >
< / G r i d >
< Grid item xs = { 12 } align = "center" >
< FormControl component = "fieldset" >
< 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 >
< RadioGroup row defaultValue = "relative" >
< Tooltip placement = "top" enterTouchDelay = "0" enterDelay = "1000" enterNextDelay = "2000" title = "Let the price move with the market" >
< FormControlLabel
value = "relative"
control = { < Radio color = "primary" / > }
label = "Relative"
labelPlacement = "Top"
onClick = { this . handleClickRelative }
/ >
< / T o o l t i p >
< Tooltip placement = "top" enterTouchDelay = "0" enterDelay = "1000" enterNextDelay = "2000" title = "Set a fix amount of satoshis" >
2022-03-25 00:09:55 +00:00
< FormControlLabel
disabled = { this . state . enableAmountRange }
2022-03-15 18:20:57 +00:00
value = "explicit"
control = { < Radio color = "secondary" / > }
label = "Explicit"
labelPlacement = "Top"
onClick = { this . handleClickExplicit }
/ >
< / T o o l t i p >
< / 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-03 19:15:13 +00:00
< Grid item xs = { 12 } align = "center" >
2022-03-15 18:20:57 +00:00
< div style = { { display : this . state . is _explicit ? '' : 'none' } } >
< TextField
2022-02-01 00:45:58 +00:00
sx = { { width : 240 } }
2022-03-15 18:20:57 +00:00
label = "Satoshis"
error = { this . state . badSatoshis }
helperText = { this . state . badSatoshis }
type = "number"
required = "true"
value = { this . state . satoshis }
2022-01-03 19:15:13 +00:00
inputProps = { {
2022-03-15 18:20:57 +00:00
// TODO read these from .env file
min : this . minTradeSats ,
max : this . maxTradeSats ,
style : { textAlign : "center" }
2022-01-03 19:15:13 +00:00
} }
2022-03-15 18:20:57 +00:00
onChange = { this . handleSatoshisChange }
// defaultValue={this.defaultSatoshis}
2022-01-03 19:15:13 +00:00
/ >
2022-03-15 18:20:57 +00:00
< / d i v >
< div style = { { display : this . state . is _explicit ? 'none' : '' } } >
< TextField
2022-02-01 00:45:58 +00:00
sx = { { width : 240 } }
2022-03-15 18:20:57 +00:00
error = { this . state . badPremium }
helperText = { this . state . badPremium }
label = "Premium over Market (%)"
2022-01-31 22:42:43 +00:00
type = "number"
2022-03-15 18:20:57 +00:00
// defaultValue={this.defaultPremium}
2022-01-31 22:42:43 +00:00
inputProps = { {
2022-03-15 18:20:57 +00:00
min : - 100 ,
max : 999 ,
2022-01-31 22:42:43 +00:00
style : { textAlign : "center" }
} }
2022-03-15 18:20:57 +00:00
onChange = { this . handlePremiumChange }
2022-01-31 22:42:43 +00:00
/ >
2022-03-15 18:20:57 +00:00
< / d i v >
< / G r i d >
< / P a p e r >
)
}
2022-03-18 21:21:13 +00:00
handleChangePublicDuration = ( date ) => {
let d = new Date ( date ) ,
hours = d . getHours ( ) ,
minutes = d . getMinutes ( ) ;
var total _secs = hours * 60 * 60 + minutes * 60 ;
this . setState ( {
changedPublicExpiryTime : true ,
publicExpiryTime : date ,
publicDuration : total _secs ,
badDuration : false ,
} ) ;
}
2022-03-21 15:51:26 +00:00
getMaxAmount = ( ) => {
if ( this . state . limits == null ) {
var max _amount = null
} else {
2022-03-25 00:09:55 +00:00
var max _amount = this . state . limits [ this . state . currency ] [ 'max_amount' ] * ( 1 + this . state . premium / 100 )
2022-03-21 15:51:26 +00:00
}
2022-03-22 17:49:57 +00:00
// times 0.98 to allow a bit of margin with respect to the backend minimum
return parseFloat ( Number ( max _amount * 0.98 ) . toPrecision ( 2 ) )
2022-03-21 15:51:26 +00:00
}
getMinAmount = ( ) => {
if ( this . state . limits == null ) {
var min _amount = null
} else {
2022-03-25 00:09:55 +00:00
var min _amount = this . state . limits [ this . state . currency ] [ 'min_amount' ] * ( 1 + this . state . premium / 100 )
2022-03-21 15:51:26 +00:00
}
2022-03-22 17:49:57 +00:00
// times 1.1 to allow a bit of margin with respect to the backend minimum
return parseFloat ( Number ( min _amount * 1.1 ) . toPrecision ( 2 ) )
2022-03-21 15:51:26 +00:00
}
2022-03-22 17:49:57 +00:00
RangeSlider = styled ( Slider ) ( ( { theme } ) => ( {
color : 'primary' ,
height : 3 ,
padding : '13px 0' ,
'& .MuiSlider-thumb' : {
height : 27 ,
width : 27 ,
backgroundColor : '#fff' ,
border : '1px solid currentColor' ,
'&:hover' : {
boxShadow : '0 0 0 8px rgba(58, 133, 137, 0.16)' ,
} ,
'& .range-bar' : {
height : 9 ,
width : 1 ,
backgroundColor : 'currentColor' ,
marginLeft : 1 ,
marginRight : 1 ,
} ,
} ,
'& .MuiSlider-track' : {
height : 3 ,
} ,
'& .MuiSlider-rail' : {
color : theme . palette . mode === 'dark' ? '#bfbfbf' : '#d8d8d8' ,
opacity : theme . palette . mode === 'dark' ? undefined : 1 ,
height : 3 ,
} ,
} ) ) ;
2022-03-21 15:51:26 +00:00
2022-03-22 17:49:57 +00:00
RangeThumbComponent ( props ) {
const { children , ... other } = props ;
return (
< SliderThumb { ... other } >
{ children }
< span className = "range-bar" / >
< span className = "range-bar" / >
< span className = "range-bar" / >
< / S l i d e r T h u m b >
) ;
}
2022-03-24 13:41:32 +00:00
rangeText = ( ) => {
2022-03-24 17:29:51 +00:00
2022-03-24 13:41:32 +00:00
return (
< div style = { { display : 'flex' , alignItems : 'center' , flexWrap : 'wrap' } } >
< span style = { { width : 40 } } > From < / s p a n >
< TextField
variant = "standard"
2022-03-24 17:29:51 +00:00
type = "number"
2022-03-24 13:41:32 +00:00
size = "small"
value = { this . state . minAmount }
onChange = { this . handleMinAmountChange }
2022-03-24 17:29:51 +00:00
error = { this . state . minAmount < this . getMinAmount ( ) || this . state . maxAmount < this . state . minAmount }
2022-03-25 19:47:01 +00:00
sx = { { width : this . state . minAmount . toString ( ) . length * 9 , maxWidth : 40 } }
2022-03-24 13:41:32 +00:00
/ >
< span style = { { width : 20 } } > to < / s p a n >
< TextField
variant = "standard"
size = "small"
2022-03-24 17:29:51 +00:00
type = "number"
2022-03-24 13:41:32 +00:00
value = { this . state . maxAmount }
2022-03-24 17:29:51 +00:00
error = { this . state . maxAmount > this . getMaxAmount ( ) || this . state . maxAmount < this . state . minAmount }
2022-03-24 13:41:32 +00:00
onChange = { this . handleMaxAmountChange }
2022-03-25 19:47:01 +00:00
sx = { { width : this . state . maxAmount . toString ( ) . length * 9 , maxWidth : 50 } }
2022-03-24 13:41:32 +00:00
/ >
< span > { this . state . currencyCode } < / s p a n >
< / d i v >
)
}
2022-03-15 18:20:57 +00:00
AdvancedMakerOptions = ( ) => {
return (
2022-03-24 13:41:32 +00:00
< Paper elevation = { 12 } style = { { padding : 8 , width : '280px' , align : 'center' } } >
2022-03-18 22:09:38 +00:00
2022-03-15 23:33:58 +00:00
< Grid container xs = { 12 } spacing = { 1 } >
2022-03-18 22:09:38 +00:00
< Grid item xs = { 12 } align = "center" spacing = { 1 } >
2022-03-16 13:23:48 +00:00
< FormControl align = "center" >
< FormHelperText >
2022-03-21 23:27:36 +00:00
< Tooltip enterTouchDelay = "0" placement = "top" align = "center" title = { "Let the taker chose an amount within the range" } >
2022-03-21 15:51:26 +00:00
< div align = "center" style = { { display : 'flex' , alignItems : 'center' , flexWrap : 'wrap' } } >
2022-03-25 00:30:40 +00:00
< Checkbox onChange = { ( e ) => this . setState ( { enableAmountRange : e . target . checked } ) & ( e . target . checked ? this . getLimits ( ) : null ) } / >
2022-03-24 13:41:32 +00:00
{ this . state . enableAmountRange & this . state . minAmount != null ? < this . rangeText / > : "Enable Amount Range" }
2022-03-16 13:23:48 +00:00
< / d i v >
< / T o o l t i p >
< / F o r m H e l p e r T e x t >
2022-03-21 15:51:26 +00:00
< div style = { { display : this . state . loadingLimits == true ? '' : 'none' } } >
< LinearProgress / >
< / d i v >
< div style = { { display : this . state . loadingLimits == false ? '' : 'none' } } >
2022-03-22 17:49:57 +00:00
< this . RangeSlider
2022-03-21 15:51:26 +00:00
disableSwap = { true }
2022-03-22 17:49:57 +00:00
sx = { { width : 200 , align : "center" } }
2022-03-21 15:51:26 +00:00
disabled = { ! this . state . enableAmountRange || this . state . loadingLimits }
value = { [ this . state . minAmount , this . state . maxAmount ] }
2022-03-24 13:41:32 +00:00
step = { ( this . getMaxAmount ( ) - this . getMinAmount ( ) ) / 5000 }
2022-03-21 23:27:36 +00:00
valueLabelDisplay = "auto"
2022-03-22 17:49:57 +00:00
components = { { Thumb : this . RangeThumbComponent } }
2022-03-24 13:41:32 +00:00
valueLabelFormat = { ( x ) => ( parseFloat ( Number ( x ) . toPrecision ( x < 100 ? 2 : 3 ) ) + " " + this . state . currencyCode ) }
2022-03-21 15:51:26 +00:00
marks = { this . state . limits == null ?
2022-03-16 13:23:48 +00:00
null
:
2022-03-21 15:51:26 +00:00
[ { value : this . getMinAmount ( ) , label : this . getMinAmount ( ) + " " + this . state . currencyCode } ,
{ value : this . getMaxAmount ( ) , label : this . getMaxAmount ( ) + " " + this . state . currencyCode } ] }
min = { this . getMinAmount ( ) }
max = { this . getMaxAmount ( ) }
onChange = { this . handleRangeAmountChange }
2022-03-16 13:23:48 +00:00
/ >
2022-03-21 15:51:26 +00:00
< / d i v >
2022-03-16 13:23:48 +00:00
< / F o r m C o n t r o l >
< / G r i d >
2022-03-15 23:33:58 +00:00
2022-03-22 17:49:57 +00:00
< Grid item xs = { 12 } align = "center" spacing = { 1 } >
< LocalizationProvider dateAdapter = { DateFnsUtils } >
< TimePicker
2022-03-24 13:41:32 +00:00
sx = { { width : 210 , align : "center" } }
2022-03-22 17:49:57 +00:00
ampm = { false }
openTo = "hours"
views = { [ 'hours' , 'minutes' ] }
inputFormat = "HH:mm"
mask = "__:__"
2022-03-27 11:39:33 +00:00
components = { {
OpenPickerIcon : HourglassTopIcon
} }
open = { this . state . openTimePicker }
InputProps = { {
endAdornment : (
< InputAdornment position = "end" >
< HourglassTopIcon / >
< / I n p u t A d o r n m e n t > )
} }
2022-03-22 17:49:57 +00:00
renderInput = { ( props ) => < TextField { ... props } / > }
label = "Public Duration (HH:mm)"
value = { this . state . publicExpiryTime }
onChange = { this . handleChangePublicDuration }
minTime = { new Date ( 0 , 0 , 0 , 0 , 10 ) }
maxTime = { new Date ( 0 , 0 , 0 , 23 , 59 ) }
/ >
< / L o c a l i z a t i o n P r o v i d e r >
< / G r i d >
< Grid item xs = { 12 } align = "center" spacing = { 1 } >
< FormControl align = "center" >
< Tooltip enterDelay = "800" enterTouchDelay = "0" placement = "top" title = { "Set the skin-in-the-game, increase for higher safety assurance" } >
< FormHelperText >
< div align = "center" style = { { display : 'flex' , flexWrap : 'wrap' , transform : 'translate(20%, 0)' } } >
Fidelity Bond Size < LockIcon sx = { { height : 20 , width : 20 } } / >
< / d i v >
< / F o r m H e l p e r T e x t >
< / T o o l t i p >
< Slider
sx = { { width : 220 , align : "center" } }
aria - label = "Bond Size (%)"
defaultValue = { 1 }
valueLabelDisplay = "auto"
valueLabelFormat = { ( x ) => ( x + '%' ) }
step = { 0.25 }
marks = { [ { value : 1 , label : '1%' } , { value : 5 , label : '5%' } , { value : 10 , label : '10%' } , { value : 15 , label : '15%' } ] }
min = { 1 }
max = { 15 }
onChange = { ( e ) => this . setState ( { bondSize : e . target . value } ) }
/ >
< / F o r m C o n t r o l >
< / G r i d >
2022-03-15 23:33:58 +00:00
< Grid item xs = { 12 } align = "center" spacing = { 1 } >
2022-03-18 21:21:13 +00:00
< Tooltip enterTouchDelay = "0" title = { "COMING SOON - High risk! Limited to " + this . maxBondlessSats / 1000 + "K Sats" } >
2022-03-15 23:33:58 +00:00
< FormControlLabel
2022-03-24 13:41:32 +00:00
label = { < a > Allow bondless taker ( < Link href = "https://git.robosats.com" target = "_blank" > info < / L i n k > ) < / a > }
2022-03-15 23:33:58 +00:00
control = {
< Checkbox
2022-03-16 15:55:48 +00:00
disabled
//disabled={this.state.type==0}
2022-03-15 23:33:58 +00:00
color = "secondary"
checked = { this . state . allowBondless }
onChange = { ( ) => this . setState ( { allowBondless : ! this . state . allowBondless } ) }
/ >
}
/ >
< / T o o l t i p >
< / G r i d >
2022-03-15 18:20:57 +00:00
< / G r i d >
< / P a p e r >
)
}
2022-03-24 13:41:32 +00:00
makeOrderBox = ( ) => {
const [ value , setValue ] = React . useState ( this . state . showAdvanced ) ;
const handleChange = ( event , newValue ) => {
this . setState ( { showAdvanced : newValue } )
setValue ( newValue ) ;
} ;
return (
2022-03-24 13:53:11 +00:00
< Box sx = { { width : this . state . showAdvanced ? '270px' : '252px' } } >
< Box sx = { { borderBottom : 1 , borderColor : 'divider' , position : 'relative' , left : '5px' } } >
< Tabs value = { value ? value : 0 } onChange = { handleChange } variant = "fullWidth" >
< Tab label = "Basic" { ... this . a11yProps ( 0 ) } / >
< Tab label = "Advanced" { ... this . a11yProps ( 1 ) } / >
< / T a b s >
2022-03-24 13:41:32 +00:00
< / B o x >
< Grid item xs = { 12 } align = "center" spacing = { 1 } >
< div style = { { display : this . state . showAdvanced == false ? '' : 'none' } } >
< this . StandardMakerOptions / >
< / d i v >
< div style = { { display : this . state . showAdvanced == true ? '' : 'none' } } >
< this . AdvancedMakerOptions / >
< / d i v >
< / G r i d >
< / B o x >
)
}
2022-03-15 18:20:57 +00:00
render ( ) {
2022-03-24 13:41:32 +00:00
2022-03-15 18:20:57 +00:00
return (
< 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
< / T y p o g r a p h y >
< /Grid> */ }
< Grid item xs = { 12 } align = "center" >
2022-03-24 13:41:32 +00:00
< this . makeOrderBox / >
2022-03-15 18:20:57 +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 */ }
2022-03-24 13:41:32 +00:00
{ ( this . state . amount == null & ( this . state . enableAmountRange == false & this . state . minAmount == null ) ||
2022-03-22 17:49:57 +00:00
this . state . amount <= 0 & ! this . state . enableAmountRange ||
2022-02-02 09:29:05 +00:00
( 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-03-21 23:27:36 +00:00
Create a BTC { this . state . type == 0 ? "buy" : "sell" } order for { this . state . enableAmountRange & this . state . minAmount != null ?
" " + this . state . minAmount + "-" + this . state . maxAmount : pn ( this . state . amount ) } { this . state . currencyCode }
2022-02-01 00:45:58 +00:00
{ 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" >
2022-03-24 13:41:32 +00:00
< Button color = "secondary" variant = "contained" to = "/" component = { LinkRouter } >
2022-01-03 23:05:19 +00:00
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
}