2022-01-02 00:37:04 +00:00
import React , { Component } from 'react' ;
2022-04-05 14:25:53 +00:00
import { withTranslation , Trans } from "react-i18next" ;
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-04-05 14:25:53 +00:00
2022-03-29 23:16:59 +00:00
import getFlags from './getFlags' ;
2022-04-17 20:33:43 +00:00
import AutocompletePayments from './AutocompletePayments' ;
2022-04-05 14:25:53 +00:00
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-04-05 14:25:53 +00:00
import currencyDict from '../../static/assets/currencies.json' ;
2022-03-15 23:33:58 +00:00
2022-04-15 16:22:49 +00:00
import { getCookie } from "../utils/cookies" ;
2022-04-20 19:32:41 +00:00
import { pn } from "../utils/prettyNumbers" ;
2022-01-10 10:13:54 +00:00
2022-04-05 14:25:53 +00:00
class MakerPage extends Component {
2022-01-02 00:37:04 +00:00
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-04-15 16:22:49 +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
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-03-21 15:51:26 +00:00
getLimits ( ) {
this . setState ( { loadingLimits : true } )
fetch ( '/api/limits/' )
. then ( ( response ) => response . json ( ) )
. then ( ( data ) => this . setState ( {
2022-04-15 16:22:49 +00:00
limits : data ,
2022-03-21 15:51:26 +00:00
loadingLimits : false ,
2022-04-15 16:22:49 +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 ( {
2022-04-15 16:22:49 +00:00
type : e . target . value ,
2022-01-02 00:37:04 +00:00
} ) ;
}
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 ( {
2022-04-15 16:22:49 +00:00
minAmount : parseFloat ( Number ( this . state . limits [ e . target . value ] [ 'max_amount' ] * 0.25 ) . toPrecision ( 2 ) ) ,
2022-03-22 17:49:57 +00:00
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 ( {
2022-04-15 16:22:49 +00:00
amount : e . target . value ,
2022-01-02 00:37:04 +00:00
} ) ;
}
2022-03-24 13:41:32 +00:00
handleMinAmountChange = ( e ) => {
this . setState ( {
2022-04-15 16:22:49 +00:00
minAmount : parseFloat ( Number ( e . target . value ) . toPrecision ( e . target . value < 100 ? 2 : 3 ) ) ,
2022-03-24 13:41:32 +00:00
} ) ;
}
handleMaxAmountChange = ( e ) => {
this . setState ( {
2022-04-15 16:22:49 +00:00
maxAmount : parseFloat ( Number ( e . target . value ) . toPrecision ( e . target . value < 100 ? 2 : 3 ) ) ,
2022-03-24 13:41:32 +00:00
} ) ;
}
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-04-15 16:22:49 +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-03-30 20:01:26 +00:00
if ( value . length > 50 ) {
2022-03-30 10:57:56 +00:00
this . setState ( {
2022-04-15 16:22:49 +00:00
badPaymentMethod : true ,
2022-03-30 10:57:56 +00:00
} ) ;
} else {
2022-01-02 09:40:19 +00:00
this . setState ( {
2022-03-30 20:01:26 +00:00
payment _method : value . substring ( 0 , 53 ) ,
2022-04-15 16:22:49 +00:00
badPaymentMethod : value . length > 50 ,
2022-01-02 09:40:19 +00:00
} ) ;
}
2022-03-30 10:57:56 +00:00
}
2022-01-02 00:37:04 +00:00
handlePremiumChange = ( e ) => {
2022-04-05 14:25:53 +00:00
const { t } = this . props ;
var max = 999 ;
var min = - 100 ;
2022-02-01 00:45:58 +00:00
if ( e . target . value > 999 ) {
2022-04-05 14:25:53 +00:00
var bad _premium = t ( "Must be less than {{max}}%" , { max : max } )
2022-02-01 00:45:58 +00:00
}
2022-04-05 14:25:53 +00:00
if ( e . target . value <= - 100 ) {
var bad _premium = t ( "Must be more than {{min}}%" , { min : min } )
2022-02-01 00:45:58 +00:00
}
2022-01-02 00:37:04 +00:00
this . setState ( {
2022-02-01 00:45:58 +00:00
premium : e . target . value ,
2022-04-15 16:22:49 +00:00
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-04-05 14:25:53 +00:00
const { t } = this . props ;
2022-02-01 00:45:58 +00:00
if ( e . target . value > this . maxTradeSats ) {
2022-04-05 14:25:53 +00:00
var bad _sats = t ( "Must be less than {{maxSats}" , { maxSats : pn ( this . maxTradeSats ) } )
2022-02-01 00:45:58 +00:00
}
if ( e . target . value < this . minTradeSats ) {
2022-04-05 14:25:53 +00:00
var bad _sats = t ( "Must be more than {{minSats}}" , { minSats : pn ( this . minTradeSats ) } )
2022-02-01 00:45:58 +00:00
}
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 ,
2022-04-15 16:22:49 +00:00
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-04-15 16:22:49 +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-04-15 16:22:49 +00:00
2022-01-04 13:47:37 +00:00
handleClickExplicit = ( e ) => {
2022-04-05 14:25:53 +00:00
if ( ! this . state . enableAmountRange ) {
this . setState ( {
2022-04-15 16:22:49 +00:00
is _explicit : true ,
2022-04-05 14:25:53 +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 ,
2022-03-30 14:26:13 +00:00
amount : this . state . has _range ? null : 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
getCurrencyCode ( val ) {
2022-04-05 14:25:53 +00:00
return currencyDict [ 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 = ( ) => {
2022-04-05 14:25:53 +00:00
const { t } = this . props ;
2022-03-15 18:20:57 +00:00
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" >
Spanish translation (#96)
* Translate tp Spanish (#93)
* update_es.json
* Update es.json
Translate eng to esp from line 222 to end
Co-authored-by: mamifiero <99733022+mamifiero@users.noreply.github.com>
* Fit book and maker UI for variable length text
* Correction and style of the Spanish translation (#95)
* Correction and style of the Spanish translation
The following terms have been unified and adjusted only in Spanish, but can be done in English base too:
* Satoshis, satoshis, sats = Sats (in honour of RoboSats)
* Robot (always first capital letter in honour of RoboSats)
* Lightning, lightning, LN, Lightning Network = Lightningç
* Telegram, TG = Telegram
* Trade, Swap = Trade (Intercambio)
* Trade counterpart, Peer, Trading peer = Peer (Compañero)
* Hold invoice, Bond & Fidelity Bond = Bond (Fianza)
* Trade collateral, Collateral, Trade escrow, Escrow = Collateral (Colateral)
* Burner contact method, Burner email = Burner contact method (Método de contacto de usar y tirar)
* Hidden service (deprecated), Onion services, .onion site = Onion site (sitio cebolla)
https://tb-manual.torproject.org/es/onion-services/
* Tor Browser (Navegador Tor)
https://tb-manual.torproject.org/es/about/
* Craiglist is not common on spanish countries, so now inserted WallaPop
* Update es.json
Co-authored-by: decentralized.b <58108487+decentralizedb@users.noreply.github.com>
Co-authored-by: mamifiero <99733022+mamifiero@users.noreply.github.com>
Co-authored-by: ibertario <68381662+ibertario@users.noreply.github.com>
2022-04-15 16:15:57 +00:00
< FormHelperText sx = { { align : "center" } } >
2022-04-05 14:25:53 +00:00
{ t ( "Buy or Sell Bitcoin?" ) }
2022-03-15 18:20:57 +00:00
< / F o r m H e l p e r T e x t >
< RadioGroup row defaultValue = "0" onChange = { this . handleTypeChange } >
2022-04-15 16:22:49 +00:00
< FormControlLabel
value = "0"
2022-03-15 18:20:57 +00:00
control = { < Radio color = "primary" / > }
2022-04-05 14:25:53 +00:00
label = { t ( "Buy" ) }
2022-03-15 18:20:57 +00:00
labelPlacement = "Top"
/ >
2022-04-15 16:22:49 +00:00
< FormControlLabel
value = "1"
2022-03-15 18:20:57 +00:00
control = { < Radio color = "secondary" / > }
2022-04-05 14:25:53 +00:00
label = { t ( "Sell" ) }
2022-03-15 18:20:57 +00:00
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-04-15 16:22:49 +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-04-05 14:25:53 +00:00
< Tooltip placement = "top" enterTouchDelay = "500" enterDelay = "700" enterNextDelay = "2000" title = { t ( "Amount of fiat to exchange for bitcoin" ) } >
2022-03-15 18:20:57 +00:00
< 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-04-15 16:22:49 +00:00
error = { this . state . amount <= 0 & this . state . amount != "" }
2022-04-05 14:25:53 +00:00
helperText = { this . state . amount <= 0 & this . state . amount != "" ? t ( "Invalid" ) : null }
label = { t ( "Amount" ) }
2022-04-15 16:22:49 +00:00
type = "number"
2022-03-15 18:20:57 +00:00
required = "true"
2022-03-21 15:51:26 +00:00
value = { this . state . amount }
2022-03-15 18:20:57 +00:00
inputProps = { {
2022-04-15 16:22:49 +00:00
min : 0 ,
2022-03-15 18:20:57 +00:00
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-04-15 16:22:49 +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 } >
2022-04-05 14:25:53 +00:00
{ Object . entries ( currencyDict )
2022-03-15 18:20:57 +00:00
. 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-04-05 14:25:53 +00:00
< Tooltip placement = "top" enterTouchDelay = "300" enterDelay = "700" enterNextDelay = "2000" title = { t ( "Enter your preferred fiat payment methods. Fast methods are highly recommended." ) } >
2022-03-29 23:16:59 +00:00
< AutocompletePayments
onAutocompleteChange = { this . handlePaymentMethodChange }
2022-03-30 10:57:56 +00:00
optionsType = { this . state . currency == 1000 ? "swap" : "fiat" }
2022-03-29 23:16:59 +00:00
error = { this . state . badPaymentMethod }
2022-04-05 14:25:53 +00:00
helperText = { this . state . badPaymentMethod ? t ( "Must be shorter than 65 characters" ) : "" }
label = { this . state . currency == 1000 ? t ( "Swap Destination(s)" ) : t ( "Fiat Payment Method(s)" ) }
2022-04-15 23:26:39 +00:00
listHeaderText = { t ( "You can add new methods" ) }
2022-04-05 14:25:53 +00:00
addNewButtonText = { t ( "Add New" ) }
2022-03-29 23:16:59 +00:00
/ >
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' >
2022-04-05 14:25:53 +00:00
{ t ( "Choose a Pricing Method" ) }
2022-03-15 18:20:57 +00:00
< / d i v >
< / F o r m H e l p e r T e x t >
< RadioGroup row defaultValue = "relative" >
2022-04-05 14:25:53 +00:00
< Tooltip placement = "top" enterTouchDelay = "0" enterDelay = "1000" enterNextDelay = "2000" title = { t ( "Let the price move with the market" ) } >
2022-04-15 16:22:49 +00:00
< FormControlLabel
value = "relative"
2022-03-15 18:20:57 +00:00
control = { < Radio color = "primary" / > }
2022-04-05 14:25:53 +00:00
label = { t ( "Relative" ) }
2022-03-15 18:20:57 +00:00
labelPlacement = "Top"
onClick = { this . handleClickRelative }
/ >
< / T o o l t i p >
2022-04-05 14:25:53 +00:00
< Tooltip placement = "top" enterTouchDelay = "0" enterDelay = "1000" enterNextDelay = "2000" title = { t ( "Set a fix amount of satoshis" ) } >
2022-03-25 00:09:55 +00:00
< FormControlLabel
2022-04-15 16:22:49 +00:00
disabled = { this . state . enableAmountRange }
value = "explicit"
2022-03-15 18:20:57 +00:00
control = { < Radio color = "secondary" / > }
2022-04-05 14:25:53 +00:00
label = { t ( "Explicit" ) }
2022-03-15 18:20:57 +00:00
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-04-05 14:25:53 +00:00
label = { t ( "Satoshis" ) }
2022-03-15 18:20:57 +00:00
error = { this . state . badSatoshis }
helperText = { this . state . badSatoshis }
2022-04-15 16:22:49 +00:00
type = "number"
2022-03-15 18:20:57 +00:00
required = "true"
2022-04-15 16:22:49 +00:00
value = { this . state . satoshis }
2022-01-03 19:15:13 +00:00
inputProps = { {
2022-04-15 16:22:49 +00:00
min : this . minTradeSats ,
max : this . maxTradeSats ,
2022-03-15 18:20:57 +00:00
style : { textAlign : "center" }
2022-01-03 19:15:13 +00:00
} }
2022-03-15 18:20:57 +00:00
onChange = { this . handleSatoshisChange }
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' : '' } } >
2022-04-15 16:22:49 +00:00
< 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 }
2022-04-05 14:25:53 +00:00
label = { t ( "Premium over Market (%)" ) }
2022-04-15 16:22:49 +00:00
type = "number"
2022-01-31 22:42:43 +00:00
inputProps = { {
2022-04-15 16:22:49 +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 ( ) ;
2022-04-15 16:22:49 +00:00
2022-03-18 21:21:13 +00:00
var total _secs = hours * 60 * 60 + minutes * 60 ;
this . setState ( {
changedPublicExpiryTime : true ,
2022-04-15 16:22:49 +00:00
publicExpiryTime : date ,
2022-03-18 21:21:13 +00:00
publicDuration : total _secs ,
badDuration : false ,
} ) ;
2022-04-15 16:22:49 +00:00
2022-03-18 21:21:13 +00:00
}
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-04-15 16:22:49 +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-04-01 14:52:44 +00:00
minAmountError = ( ) => {
return this . state . minAmount < this . getMinAmount ( ) || this . state . maxAmount < this . state . minAmount || this . state . minAmount < this . state . maxAmount / ( this . maxRangeAmountMultiple + 0.15 ) || this . state . minAmount * ( this . minRangeAmountMultiple - 0.1 ) > this . state . maxAmount
}
maxAmountError = ( ) => {
return this . state . maxAmount > this . getMaxAmount ( ) || this . state . maxAmount < this . state . minAmount || this . state . minAmount < this . state . maxAmount / ( this . maxRangeAmountMultiple + 0.15 ) || this . state . minAmount * ( this . minRangeAmountMultiple - 0.1 ) > this . state . maxAmount
}
2022-03-24 13:41:32 +00:00
rangeText = ( ) => {
2022-04-05 14:25:53 +00:00
const { t } = this . props ;
2022-03-24 13:41:32 +00:00
return (
< div style = { { display : 'flex' , alignItems : 'center' , flexWrap : 'wrap' } } >
2022-04-05 14:25:53 +00:00
< span style = { { width : 40 } } > { t ( "From" ) } < / s p a n >
2022-03-24 13:41:32 +00:00
< TextField
variant = "standard"
2022-04-15 16:22:49 +00:00
type = "number"
2022-03-24 13:41:32 +00:00
size = "small"
value = { this . state . minAmount }
onChange = { this . handleMinAmountChange }
2022-04-01 14:52:44 +00:00
error = { this . minAmountError ( ) }
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
/ >
Spanish translation (#96)
* Translate tp Spanish (#93)
* update_es.json
* Update es.json
Translate eng to esp from line 222 to end
Co-authored-by: mamifiero <99733022+mamifiero@users.noreply.github.com>
* Fit book and maker UI for variable length text
* Correction and style of the Spanish translation (#95)
* Correction and style of the Spanish translation
The following terms have been unified and adjusted only in Spanish, but can be done in English base too:
* Satoshis, satoshis, sats = Sats (in honour of RoboSats)
* Robot (always first capital letter in honour of RoboSats)
* Lightning, lightning, LN, Lightning Network = Lightningç
* Telegram, TG = Telegram
* Trade, Swap = Trade (Intercambio)
* Trade counterpart, Peer, Trading peer = Peer (Compañero)
* Hold invoice, Bond & Fidelity Bond = Bond (Fianza)
* Trade collateral, Collateral, Trade escrow, Escrow = Collateral (Colateral)
* Burner contact method, Burner email = Burner contact method (Método de contacto de usar y tirar)
* Hidden service (deprecated), Onion services, .onion site = Onion site (sitio cebolla)
https://tb-manual.torproject.org/es/onion-services/
* Tor Browser (Navegador Tor)
https://tb-manual.torproject.org/es/about/
* Craiglist is not common on spanish countries, so now inserted WallaPop
* Update es.json
Co-authored-by: decentralized.b <58108487+decentralizedb@users.noreply.github.com>
Co-authored-by: mamifiero <99733022+mamifiero@users.noreply.github.com>
Co-authored-by: ibertario <68381662+ibertario@users.noreply.github.com>
2022-04-15 16:15:57 +00:00
< span style = { { width : t ( "to" ) . length * 8 , align : "center" } } > { t ( "to" ) } < / s p a n >
2022-03-24 13:41:32 +00:00
< TextField
variant = "standard"
size = "small"
2022-04-15 16:22:49 +00:00
type = "number"
2022-03-24 13:41:32 +00:00
value = { this . state . maxAmount }
2022-04-01 14:52:44 +00:00
error = { this . maxAmountError ( ) }
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
/ >
Spanish translation (#96)
* Translate tp Spanish (#93)
* update_es.json
* Update es.json
Translate eng to esp from line 222 to end
Co-authored-by: mamifiero <99733022+mamifiero@users.noreply.github.com>
* Fit book and maker UI for variable length text
* Correction and style of the Spanish translation (#95)
* Correction and style of the Spanish translation
The following terms have been unified and adjusted only in Spanish, but can be done in English base too:
* Satoshis, satoshis, sats = Sats (in honour of RoboSats)
* Robot (always first capital letter in honour of RoboSats)
* Lightning, lightning, LN, Lightning Network = Lightningç
* Telegram, TG = Telegram
* Trade, Swap = Trade (Intercambio)
* Trade counterpart, Peer, Trading peer = Peer (Compañero)
* Hold invoice, Bond & Fidelity Bond = Bond (Fianza)
* Trade collateral, Collateral, Trade escrow, Escrow = Collateral (Colateral)
* Burner contact method, Burner email = Burner contact method (Método de contacto de usar y tirar)
* Hidden service (deprecated), Onion services, .onion site = Onion site (sitio cebolla)
https://tb-manual.torproject.org/es/onion-services/
* Tor Browser (Navegador Tor)
https://tb-manual.torproject.org/es/about/
* Craiglist is not common on spanish countries, so now inserted WallaPop
* Update es.json
Co-authored-by: decentralized.b <58108487+decentralizedb@users.noreply.github.com>
Co-authored-by: mamifiero <99733022+mamifiero@users.noreply.github.com>
Co-authored-by: ibertario <68381662+ibertario@users.noreply.github.com>
2022-04-15 16:15:57 +00:00
< span style = { { width : this . state . currencyCode . length * 9 + 4 , align : "right" } } > { this . state . currencyCode } < / s p a n >
2022-03-24 13:41:32 +00:00
< / d i v >
)
}
2022-03-15 18:20:57 +00:00
AdvancedMakerOptions = ( ) => {
2022-04-05 14:25:53 +00:00
const { t } = this . props ;
2022-03-15 18:20:57 +00:00
return (
2022-03-24 13:41:32 +00:00
< Paper elevation = { 12 } style = { { padding : 8 , width : '280px' , align : 'center' } } >
2022-04-15 16:22:49 +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-04-05 14:25:53 +00:00
< Tooltip enterTouchDelay = "0" placement = "top" align = "center" title = { t ( "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-04-05 14:25:53 +00:00
< Checkbox onChange = { ( e ) => this . setState ( { enableAmountRange : e . target . checked , is _explicit : false } ) & ( e . target . checked ? this . getLimits ( ) : null ) } / >
{ this . state . enableAmountRange & this . state . minAmount != null ? < this . rangeText / > : t ( "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 } / > }
2022-04-05 14:25:53 +00:00
label = { t ( "Public Duration (HH:mm)" ) }
2022-03-22 17:49:57 +00:00
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" >
2022-04-05 14:25:53 +00:00
< Tooltip enterDelay = "800" enterTouchDelay = "0" placement = "top" title = { t ( "Set the skin-in-the-game, increase for higher safety assurance" ) } >
2022-03-22 17:49:57 +00:00
< FormHelperText >
< div align = "center" style = { { display : 'flex' , flexWrap : 'wrap' , transform : 'translate(20%, 0)' } } >
2022-04-05 14:25:53 +00:00
{ t ( "Fidelity Bond Size" ) } < LockIcon sx = { { height : 20 , width : 20 } } / >
2022-03-22 17:49:57 +00:00
< / 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-04-05 14:25:53 +00:00
< Tooltip enterTouchDelay = "0" title = { t ( "COMING SOON - High risk! Limited to {{limitSats}}K Sats" , { limitSats : this . maxBondlessSats / 1000 } ) } >
2022-03-15 23:33:58 +00:00
< FormControlLabel
2022-04-05 14:25:53 +00:00
label = { t ( "Allow bondless takers" ) }
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 ) ;
2022-04-05 14:25:53 +00:00
const { t } = this . props ;
2022-03-24 13:41:32 +00:00
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" >
2022-04-05 14:25:53 +00:00
< Tab label = { t ( "Order" ) } { ... this . a11yProps ( 0 ) } / >
< Tab label = { t ( "Customize" ) } { ... this . a11yProps ( 1 ) } / >
2022-03-24 13:53:11 +00:00
< / T a b s >
2022-03-24 13:41:32 +00:00
< / B o x >
2022-04-15 16:22:49 +00:00
2022-03-24 13:41:32 +00:00
< 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-04-05 14:25:53 +00:00
const { t } = this . props ;
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-04-15 16:22:49 +00:00
{ ( this . state . amount == null & ( this . state . enableAmountRange == false || this . state . loadingLimits ) ||
2022-04-01 14:52:44 +00:00
this . state . enableAmountRange & ( this . minAmountError ( ) || this . maxAmountError ( ) ) ||
2022-04-15 16:22:49 +00:00
this . state . amount <= 0 & ! this . state . enableAmountRange ||
( this . state . is _explicit & ( this . state . badSatoshis != null || this . state . satoshis == null ) ) ||
2022-02-02 09:29:05 +00:00
( ! this . state . is _explicit & this . state . badPremium != null ) )
?
2022-04-05 14:25:53 +00:00
< Tooltip enterTouchDelay = "0" title = { t ( "You must fill the order correctly" ) } >
< div > < Button disabled color = "primary" variant = "contained" onClick = { this . handleCreateOfferButtonPressed } > { t ( "Create Order" ) } < / B u t t o n > < / d i v >
2022-02-02 09:29:05 +00:00
< / T o o l t i p >
:
2022-04-05 14:25:53 +00:00
< Button color = "primary" variant = "contained" onClick = { this . handleCreateOfferButtonPressed } > { t ( "Create Order" ) } < / B u t t o n >
2022-04-15 16:22:49 +00:00
}
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-04-15 16:22:49 +00:00
{ this . state . type == 0 ?
2022-04-05 14:25:53 +00:00
t ( "Create a BTC buy order for " )
:
t ( "Create a BTC sell order for " )
2022-04-15 16:22:49 +00:00
}
{ this . state . enableAmountRange & this . state . minAmount != null ?
this . state . minAmount + "-" + this . state . maxAmount
:
pn ( this . state . amount ) }
2022-04-05 14:25:53 +00:00
{ " " + this . state . currencyCode }
2022-04-15 16:22:49 +00:00
{ this . state . is _explicit ?
2022-04-05 14:25:53 +00:00
t ( " of {{satoshis}} Satoshis" , { satoshis : pn ( this . state . satoshis ) } )
2022-04-15 16:22:49 +00:00
:
( this . state . premium == 0 ? t ( " at market price" ) :
( this . state . premium > 0 ?
2022-04-05 14:25:53 +00:00
t ( " at a {{premium}}% premium" , { premium : this . state . premium } )
:
t ( " at a {{discount}}% discount" , { discount : - this . state . premium } ) )
2022-01-02 00:37:04 +00:00
)
}
< / 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-04-05 14:25:53 +00:00
{ t ( "Back" ) }
2022-01-03 23:05:19 +00:00
< / 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-04-05 14:25:53 +00:00
}
2022-04-15 16:22:49 +00:00
export default withTranslation ( ) ( MakerPage ) ;