Implement backend handle range amounts, order take amount input and order book ranges

This commit is contained in:
Reckless_Satoshi 2022-03-22 10:49:57 -07:00
parent bf80986005
commit 8ae2406275
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
9 changed files with 263 additions and 103 deletions

View File

@ -46,7 +46,7 @@ class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin):
"maker_link", "maker_link",
"taker_link", "taker_link",
"status", "status",
"amount", "amt",
"currency_link", "currency_link",
"t0_satoshis", "t0_satoshis",
"is_disputed", "is_disputed",
@ -69,7 +69,13 @@ class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin):
"trade_escrow", "trade_escrow",
) )
list_filter = ("is_disputed", "is_fiat_sent", "type", "currency", "status") list_filter = ("is_disputed", "is_fiat_sent", "type", "currency", "status")
search_fields = ["id","amount"] search_fields = ["id","amount","min_amount","max_amount"]
def amt(self, obj):
if obj.has_range and obj.amount == None:
return str(float(obj.min_amount))+"-"+ str(float(obj.max_amount))
else:
return float(obj.amount)
@admin.register(LNPayment) @admin.register(LNPayment)
class LNPaymentAdmin(AdminChangeLinksMixin, admin.ModelAdmin): class LNPaymentAdmin(AdminChangeLinksMixin, admin.ModelAdmin):

View File

@ -118,16 +118,16 @@ class Logics:
elif max_sats > MAX_TRADE: elif max_sats > MAX_TRADE:
return False, { return False, {
"bad_request": "bad_request":
"Your order upper range value (max_amount) is too big. It is worth " + "Your order maximum amount is too big. It is worth " +
"{:,}".format(max_sats) + "{:,}".format(int(max_sats)) +
" Sats now, but the limit is " + "{:,}".format(MAX_TRADE) + " Sats now, but the limit is " + "{:,}".format(MAX_TRADE) +
" Sats" " Sats"
} }
elif min_sats < MIN_TRADE: elif min_sats < MIN_TRADE:
return False, { return False, {
"bad_request": "bad_request":
"Your order lower range value (min_mount) is too small. It is worth " + "Your order minimum amount is too small. It is worth " +
"{:,}".format(min_sats) + "{:,}".format(int(min_sats)) +
" Sats now, but the limit is " + "{:,}".format(MAX_TRADE) + " Sats now, but the limit is " + "{:,}".format(MAX_TRADE) +
" Sats" " Sats"
} }
@ -139,6 +139,15 @@ class Logics:
return True, None return True, None
def validate_amount_within_range(order, amount):
if amount > float(order.max_amount) or amount < float(order.min_amount):
return False, {
"bad_request":
"The amount specified is outside the range specified by the maker"
}
return True, None
def user_activity_status(last_seen): def user_activity_status(last_seen):
if last_seen > (timezone.now() - timedelta(minutes=2)): if last_seen > (timezone.now() - timedelta(minutes=2)):
return "Active" return "Active"
@ -148,7 +157,7 @@ class Logics:
return "Inactive" return "Inactive"
@classmethod @classmethod
def take(cls, order, user): def take(cls, order, user, amount=None):
is_penalized, time_out = cls.is_penalized(user) is_penalized, time_out = cls.is_penalized(user)
if is_penalized: if is_penalized:
return False, { return False, {
@ -156,6 +165,8 @@ class Logics:
f"You need to wait {time_out} seconds to take an order", f"You need to wait {time_out} seconds to take an order",
} }
else: else:
if order.has_range:
order.amount= amount
order.taker = user order.taker = user
order.status = Order.Status.TAK order.status = Order.Status.TAK
order.expires_at = timezone.now() + timedelta( order.expires_at = timezone.now() + timedelta(
@ -702,6 +713,8 @@ class Logics:
order.status = Order.Status.PUB order.status = Order.Status.PUB
order.expires_at = order.created_at + timedelta( order.expires_at = order.created_at + timedelta(
seconds=order.t_to_expire(Order.Status.PUB)) seconds=order.t_to_expire(Order.Status.PUB))
if order.has_range:
order.amount = None
order.save() order.save()
# send_message.delay(order.id,'order_published') # too spammy # send_message.delay(order.id,'order_published') # too spammy
return return

View File

@ -339,7 +339,11 @@ class Order(models.Model):
taker_platform_rated = models.BooleanField(default=False, null=False) taker_platform_rated = models.BooleanField(default=False, null=False)
def __str__(self): def __str__(self):
return f"Order {self.id}: {self.Types(self.type).label} BTC for {float(self.amount)} {self.currency}" if self.has_range and self.amount == None:
amt = str(float(self.min_amount))+"-"+ str(float(self.max_amount))
else:
amt = float(self.amount)
return f"Order {self.id}: {self.Types(self.type).label} BTC for {amt} {self.currency}"
def t_to_expire(self, status): def t_to_expire(self, status):

View File

@ -21,7 +21,7 @@ class ListOrderSerializer(serializers.ModelSerializer):
"is_explicit", "is_explicit",
"premium", "premium",
"satoshis", "satoshis",
"bondless_taker" "bondless_taker",
"maker", "maker",
"taker", "taker",
) )
@ -75,6 +75,7 @@ class UpdateOrderSerializer(serializers.Serializer):
allow_blank=True, allow_blank=True,
default=None, default=None,
) )
amount = serializers.DecimalField(max_digits=18, decimal_places=8, allow_null=True, required=False, default=None)
class ClaimRewardSerializer(serializers.Serializer): class ClaimRewardSerializer(serializers.Serializer):
invoice = serializers.CharField(max_length=2000, invoice = serializers.CharField(max_length=2000,

View File

@ -390,6 +390,10 @@ class OrderView(viewsets.ViewSet):
""" """
order_id = request.GET.get(self.lookup_url_kwarg) order_id = request.GET.get(self.lookup_url_kwarg)
import sys
sys.stdout.write('AAAAAA')
print('BBBBB1')
serializer = UpdateOrderSerializer(data=request.data) serializer = UpdateOrderSerializer(data=request.data)
if not serializer.is_valid(): if not serializer.is_valid():
return Response(status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_400_BAD_REQUEST)
@ -410,7 +414,17 @@ class OrderView(viewsets.ViewSet):
request.user) request.user)
if not valid: if not valid:
return Response(context, status=status.HTTP_409_CONFLICT) return Response(context, status=status.HTTP_409_CONFLICT)
valid, context = Logics.take(order, request.user)
# For order with amount range, set the amount now.
if order.has_range:
amount = float(serializer.data.get("amount"))
valid, context = Logics.validate_amount_within_range(order, amount)
if not valid:
return Response(context, status=status.HTTP_400_BAD_REQUEST)
valid, context = Logics.take(order, request.user, amount)
else:
valid, context = Logics.take(order, request.user)
if not valid: if not valid:
return Response(context, status=status.HTTP_403_FORBIDDEN) return Response(context, status=status.HTTP_403_FORBIDDEN)

View File

@ -78,6 +78,15 @@ export default class BookPage extends Component {
if(status=='Seen recently'){return("warning")} if(status=='Seen recently'){return("warning")}
if(status=='Inactive'){return('error')} if(status=='Inactive'){return('error')}
} }
amountToString = (amount,has_range,min_amount,max_amount) => {
if (has_range){
console.log(this.pn(parseFloat(Number(min_amount).toPrecision(2))))
console.log(this.pn(parseFloat(Number(min_amount).toPrecision(2)))+'-'+this.pn(parseFloat(Number(max_amount).toPrecision(2))))
return this.pn(parseFloat(Number(min_amount).toPrecision(2)))+'-'+this.pn(parseFloat(Number(max_amount).toPrecision(2)))
}else{
return this.pn(parseFloat(Number(amount).toPrecision(3)))
}
}
bookListTableDesktop=()=>{ bookListTableDesktop=()=>{
return ( return (
@ -90,7 +99,10 @@ export default class BookPage extends Component {
robot: order.maker_nick, robot: order.maker_nick,
robot_status: order.maker_status, robot_status: order.maker_status,
type: order.type ? "Seller": "Buyer", type: order.type ? "Seller": "Buyer",
amount: parseFloat(parseFloat(order.amount).toFixed(5)), amount: order.amount,
has_range: order.has_range,
min_amount: order.min_amount,
max_amount: order.max_amount,
currency: this.getCurrencyCode(order.currency), currency: this.getCurrencyCode(order.currency),
payment_method: order.payment_method, payment_method: order.payment_method,
price: order.price, price: order.price,
@ -123,9 +135,9 @@ export default class BookPage extends Component {
); );
} }, } },
{ field: 'type', headerName: 'Is', width: 60 }, { field: 'type', headerName: 'Is', width: 60 },
{ field: 'amount', headerName: 'Amount', type: 'number', width: 80, { field: 'amount', headerName: 'Amount', type: 'number', width: 90,
renderCell: (params) => {return ( renderCell: (params) => {return (
<div style={{ cursor: "pointer" }}>{this.pn(params.row.amount)}</div> <div style={{ cursor: "pointer" }}>{this.amountToString(params.row.amount,params.row.has_range, params.row.min_amount, params.row.max_amount)}</div>
)}}, )}},
{ field: 'currency', headerName: 'Currency', width: 100, { field: 'currency', headerName: 'Currency', width: 100,
renderCell: (params) => {return ( renderCell: (params) => {return (
@ -163,7 +175,10 @@ export default class BookPage extends Component {
robot: order.maker_nick, robot: order.maker_nick,
robot_status: order.maker_status, robot_status: order.maker_status,
type: order.type ? "Seller": "Buyer", type: order.type ? "Seller": "Buyer",
amount: parseFloat(parseFloat(order.amount).toFixed(4)), amount: order.amount,
has_range: order.has_range,
min_amount: order.min_amount,
max_amount: order.max_amount,
currency: this.getCurrencyCode(order.currency), currency: this.getCurrencyCode(order.currency),
payment_method: order.payment_method, payment_method: order.payment_method,
price: order.price, price: order.price,
@ -191,10 +206,10 @@ export default class BookPage extends Component {
); );
} }, } },
{ field: 'type', headerName: 'Is', width: 60, hide:'true'}, { field: 'type', headerName: 'Is', width: 60, hide:'true'},
{ field: 'amount', headerName: 'Amount', type: 'number', width: 80, { field: 'amount', headerName: 'Amount', type: 'number', width: 90,
renderCell: (params) => {return ( renderCell: (params) => {return (
<Tooltip placement="right" enterTouchDelay="0" title={params.row.type}> <Tooltip placement="right" enterTouchDelay="0" title={params.row.type}>
<div style={{ cursor: "pointer" }}>{this.pn(params.row.amount)}</div> <div style={{ cursor: "pointer" }}>{this.amountToString(params.row.amount,params.row.has_range, params.row.min_amount, params.row.max_amount)}</div>
</Tooltip> </Tooltip>
)} }, )} },
{ field: 'currency', headerName: 'Currency', width: 100, { field: 'currency', headerName: 'Currency', width: 100,

View File

@ -1,12 +1,12 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { LinearProgress, Checkbox, Slider, Switch, Tooltip, Paper, Button , Grid, Typography, TextField, Select, FormHelperText, MenuItem, FormControl, Radio, FormControlLabel, RadioGroup} from "@mui/material" import { LinearProgress, Checkbox, Slider, SliderThumb, Switch, Tooltip, Paper, Button , Grid, Typography, TextField, Select, FormHelperText, MenuItem, FormControl, Radio, FormControlLabel, RadioGroup} from "@mui/material"
import { LocalizationProvider, TimePicker} from '@mui/lab'; import { LocalizationProvider, TimePicker} from '@mui/lab';
import DateFnsUtils from "@date-io/date-fns"; import DateFnsUtils from "@date-io/date-fns";
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { styled } from '@mui/material/styles';
import getFlags from './getFlags' import getFlags from './getFlags'
import LockIcon from '@mui/icons-material/Lock'; import LockIcon from '@mui/icons-material/Lock';
import SelfImprovementIcon from '@mui/icons-material/SelfImprovement';
function getCookie(name) { function getCookie(name) {
let cookieValue = null; let cookieValue = null;
@ -43,8 +43,8 @@ export default class MakerPage extends Component {
minTradeSats = 20000; minTradeSats = 20000;
maxTradeSats = 800000; maxTradeSats = 800000;
maxBondlessSats = 50000; maxBondlessSats = 50000;
maxRangeAmountMultiple = 5; maxRangeAmountMultiple = 4.9;
minRangeAmountMultiple = 1.5; minRangeAmountMultiple = 1.6;
constructor(props) { constructor(props) {
super(props); super(props);
@ -79,9 +79,8 @@ export default class MakerPage extends Component {
limits:data, limits:data,
loadingLimits:false, loadingLimits:false,
minAmount: parseFloat(Number(data[this.state.currency]['max_amount']*0.25).toPrecision(2)), minAmount: parseFloat(Number(data[this.state.currency]['max_amount']*0.25).toPrecision(2)),
maxAmount: parseFloat(Number(data[this.state.currency]['max_amount']*0.75).toPrecision(2)) maxAmount: parseFloat(Number(data[this.state.currency]['max_amount']*0.75).toPrecision(2)),
}) }));
& console.log(this.state.limits));
} }
handleTypeChange=(e)=>{ handleTypeChange=(e)=>{
@ -94,6 +93,12 @@ export default class MakerPage extends Component {
currency: e.target.value, currency: e.target.value,
currencyCode: this.getCurrencyCode(e.target.value), currencyCode: this.getCurrencyCode(e.target.value),
}); });
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)),
})
}
} }
handleAmountChange=(e)=>{ handleAmountChange=(e)=>{
this.setState({ this.setState({
@ -101,7 +106,7 @@ export default class MakerPage extends Component {
}); });
} }
handleRangeAmountChange = (e, activeThumb) => { handleRangeAmountChange = (e, newValue, activeThumb) => {
var maxAmount = this.getMaxAmount(); var maxAmount = this.getMaxAmount();
var minAmount = this.getMinAmount(); var minAmount = this.getMinAmount();
var lowerValue = e.target.value[0]; var lowerValue = e.target.value[0];
@ -379,7 +384,6 @@ export default class MakerPage extends Component {
} }
handleChangePublicDuration = (date) => { handleChangePublicDuration = (date) => {
console.log(date)
let d = new Date(date), let d = new Date(date),
hours = d.getHours(), hours = d.getHours(),
minutes = d.getMinutes(); minutes = d.getMinutes();
@ -401,7 +405,8 @@ export default class MakerPage extends Component {
}else{ }else{
var max_amount = this.state.limits[this.state.currency]['max_amount'] var max_amount = this.state.limits[this.state.currency]['max_amount']
} }
return parseFloat(Number(max_amount).toPrecision(2)) // times 0.98 to allow a bit of margin with respect to the backend minimum
return parseFloat(Number(max_amount*0.98).toPrecision(2))
} }
getMinAmount = () => { getMinAmount = () => {
@ -410,10 +415,52 @@ export default class MakerPage extends Component {
}else{ }else{
var min_amount = this.state.limits[this.state.currency]['min_amount'] var min_amount = this.state.limits[this.state.currency]['min_amount']
} }
return parseFloat(Number(min_amount).toPrecision(2)) // times 1.1 to allow a bit of margin with respect to the backend minimum
return parseFloat(Number(min_amount*1.1).toPrecision(2))
} }
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,
},
}));
RangeThumbComponent(props) {
const { children, ...other } = props;
return (
<SliderThumb {...other}>
{children}
<span className="range-bar" />
<span className="range-bar" />
<span className="range-bar" />
</SliderThumb>
);
}
AdvancedMakerOptions = () => { AdvancedMakerOptions = () => {
return( return(
<Paper elevation={12} style={{ padding: 8, width:250, align:'center'}}> <Paper elevation={12} style={{ padding: 8, width:250, align:'center'}}>
@ -421,6 +468,61 @@ export default class MakerPage extends Component {
<Grid container xs={12} spacing={1}> <Grid container xs={12} spacing={1}>
<Grid item xs={12} align="center" spacing={1}> <Grid item xs={12} align="center" spacing={1}>
<FormControl align="center">
<FormHelperText>
<Tooltip enterTouchDelay="0" placement="top" align="center"title={"Let the taker chose an amount within the range"}>
<div align="center" style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
<Checkbox onChange={(e)=>this.setState({enableAmountRange:e.target.checked}) & (e.target.checked ? this.getLimits() : null)}/>
{this.state.enableAmountRange & this.state.minAmount != null?
"From "+this.state.minAmount+" to "+this.state.maxAmount +" "+this.state.currencyCode: "Enable Amount Range"}
</div>
</Tooltip>
</FormHelperText>
<div style={{ display: this.state.loadingLimits == true ? '':'none'}}>
<LinearProgress />
</div>
<div style={{ display: this.state.loadingLimits == false ? '':'none'}}>
<this.RangeSlider
disableSwap={true}
sx={{width:200, align:"center"}}
disabled={!this.state.enableAmountRange || this.state.loadingLimits}
value={[this.state.minAmount, this.state.maxAmount]}
step={(this.getMaxAmount()-this.getMinAmount())/100}
valueLabelDisplay="auto"
components={{ Thumb: this.RangeThumbComponent }}
valueLabelFormat={(x) => (parseFloat(Number(x).toPrecision(2))+" "+this.state.currencyCode)}
marks={this.state.limits == null?
null
:
[{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}
/>
</div>
</FormControl>
</Grid>
<Grid item xs={12} align="center" spacing={1}>
<LocalizationProvider dateAdapter={DateFnsUtils}>
<TimePicker
ampm={false}
openTo="hours"
views={['hours', 'minutes']}
inputFormat="HH:mm"
mask="__:__"
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)}
/>
</LocalizationProvider>
</Grid>
<Grid item xs={12} align="center" spacing={1}>
<FormControl align="center"> <FormControl align="center">
<Tooltip enterDelay="800" enterTouchDelay="0" placement="top" title={"Set the skin-in-the-game, increase for higher safety assurance"}> <Tooltip enterDelay="800" enterTouchDelay="0" placement="top" title={"Set the skin-in-the-game, increase for higher safety assurance"}>
<FormHelperText> <FormHelperText>
@ -445,59 +547,6 @@ export default class MakerPage extends Component {
</FormControl> </FormControl>
</Grid> </Grid>
<Grid item xs={12} align="center" spacing={1}>
<LocalizationProvider dateAdapter={DateFnsUtils}>
<TimePicker
ampm={false}
openTo="hours"
views={['hours', 'minutes']}
inputFormat="HH:mm"
mask="__:__"
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)}
/>
</LocalizationProvider>
</Grid>
<Grid item xs={12} align="center" spacing={1}>
<FormControl align="center">
<FormHelperText>
<Tooltip enterTouchDelay="0" placement="top" align="center"title={"Let the taker chose an amount within the range"}>
<div align="center" style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
<Checkbox onChange={(e)=>this.setState({enableAmountRange:e.target.checked}) & (e.target.checked ? this.getLimits() : null)}/>
Amount Range
</div>
</Tooltip>
</FormHelperText>
<div style={{ display: this.state.loadingLimits == true ? '':'none'}}>
<LinearProgress />
</div>
<div style={{ display: this.state.loadingLimits == false ? '':'none'}}>
<Slider
disableSwap={true}
sx={{width:190, align:"center"}}
disabled={!this.state.enableAmountRange || this.state.loadingLimits}
value={[this.state.minAmount, this.state.maxAmount]}
step={(this.getMaxAmount()-this.getMinAmount())/100}
valueLabelDisplay="auto"
valueLabelFormat={(x) => (parseFloat(Number(x).toPrecision(2))+" "+this.state.currencyCode)}
marks={this.state.limits == null?
null
:
[{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}
/>
</div>
</FormControl>
</Grid>
<Grid item xs={12} align="center" spacing={1}> <Grid item xs={12} align="center" spacing={1}>
<Tooltip enterTouchDelay="0" title={"COMING SOON - High risk! Limited to "+ this.maxBondlessSats/1000 +"K Sats"}> <Tooltip enterTouchDelay="0" title={"COMING SOON - High risk! Limited to "+ this.maxBondlessSats/1000 +"K Sats"}>
<FormControlLabel <FormControlLabel
@ -554,8 +603,8 @@ export default class MakerPage extends Component {
<Grid item xs={12} align="center"> <Grid item xs={12} align="center">
{/* conditions to disable the make button */} {/* conditions to disable the make button */}
{(this.state.amount == null || {(this.state.amount == null & (this.state.enableAmountRange == false & this.state.minAmount != null) ||
this.state.amount <= 0 || this.state.amount <= 0 & !this.state.enableAmountRange ||
(this.state.is_explicit & (this.state.badSatoshis != null || this.state.satoshis == null)) || (this.state.is_explicit & (this.state.badSatoshis != null || this.state.satoshis == null)) ||
(!this.state.is_explicit & this.state.badPremium != null)) (!this.state.is_explicit & this.state.badPremium != null))
? ?

View File

@ -1,5 +1,5 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { Chip, Tooltip, Badge, Tab, Tabs, Alert, Paper, CircularProgress, Button , Grid, Typography, List, ListItem, ListItemIcon, ListItemText, ListItemAvatar, Avatar, Divider, Box, LinearProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material" import {TextField,Chip, Tooltip, Badge, Tab, Tabs, Alert, Paper, CircularProgress, Button , Grid, Typography, List, ListItem, ListItemIcon, ListItemText, ListItemAvatar, Avatar, Divider, Box, LinearProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material"
import Countdown, { zeroPad, calcTimeDelta } from 'react-countdown'; import Countdown, { zeroPad, calcTimeDelta } from 'react-countdown';
import MediaQuery from 'react-responsive' import MediaQuery from 'react-responsive'
@ -89,6 +89,7 @@ export default class OrderPage extends Component {
} }
var otherStateVars = { var otherStateVars = {
amount: newStateVars.amount ? newStateVars.amount : null,
loading: false, loading: false,
delay: this.setDelay(newStateVars.status), delay: this.setDelay(newStateVars.status),
currencyCode: this.getCurrencyCode(newStateVars.currency), currencyCode: this.getCurrencyCode(newStateVars.currency),
@ -157,32 +158,81 @@ export default class OrderPage extends Component {
} }
}; };
countdownTakeOrderRenderer = ({ seconds, completed }) => { handleTakeAmountChange = (e) => {
if(isNaN(seconds)){ if (e.target.value != "" & e.target.value != null){
return ( this.setState({takeAmount: parseFloat(e.target.value)})
<> }else{
this.setState({takeAmount: e.target.value})
}
}
amountHelperText=()=>{
if(this.state.takeAmount < this.state.min_amount & this.state.takeAmount != ""){
return "Too low"
}else if (this.state.takeAmount > this.state.max_amount & this.state.takeAmount != ""){
return "Too high"
}else{
return null
}
}
takeOrderButton = () => {
if(this.state.has_range){
return(
<Grid containter xs={12} align="center" alignItems="stretch" justifyContent="center" style={{ display: "flex"}}>
<this.InactiveMakerDialog/>
<div style={{maxWidth:120}}>
<Tooltip placement="top" enterTouchDelay="500" enterDelay="700" enterNextDelay="2000" title="Amount of fiat to exchange for bitcoin">
<Paper sx={{maxHeight:40}}>
<TextField
error={(this.state.takeAmount < this.state.min_amount || this.state.takeAmount > this.state.max_amount) & this.state.takeAmount != "" }
helperText={this.amountHelperText()}
label={"Amount "+this.state.currencyCode}
size="small"
type="number"
required="true"
value={this.state.takeAmount}
inputProps={{
min:this.state.min_amount ,
max:this.state.max_amount ,
style: {textAlign:"center"}
}}
onChange={this.handleTakeAmountChange}
/>
</Paper>
</Tooltip>
</div>
<div style={{height:38, top:'1px', position:'relative'}}>
<Button sx={{height:38}} variant='contained' color='primary'
onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}
disabled={this.state.takeAmount < this.state.min_amount || this.state.takeAmount > this.state.max_amount || this.state.takeAmount == "" || this.state.takeAmount == null } >
Take Order
</Button>
</div>
</Grid>
)
}else{
return(
<>
<this.InactiveMakerDialog/> <this.InactiveMakerDialog/>
<Button variant='contained' color='primary' <Button variant='contained' color='primary'
onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}> onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}>
Take Order Take Order
</Button> </Button>
</>) </>
)
} }
}
countdownTakeOrderRenderer = ({ seconds, completed }) => {
if(isNaN(seconds)){return (<this.takeOrderButton/>)}
if (completed) { if (completed) {
// Render a completed state // Render a completed state
return ( return ( <this.takeOrderButton/>);
<>
<this.InactiveMakerDialog/>
<Button variant='contained' color='primary'
onClick={this.state.maker_status=='Inactive' ? this.handleClickOpenInactiveMakerDialog : this.takeOrder}>
Take Order
</Button>
</>
);
} else{ } else{
return( return(
<Tooltip enterTouchDelay="0" title="Wait until you can take an order"><div> <Tooltip enterTouchDelay="0" title="Wait until you can take an order"><div>
<Button disabled={true} variant='contained' color='primary' onClick={this.takeOrder}>Take Order</Button> <Button disabled={true} variant='contained' color='primary'>Take Order</Button>
</div></Tooltip>) </div></Tooltip>)
} }
}; };
@ -212,12 +262,13 @@ export default class OrderPage extends Component {
takeOrder=()=>{ takeOrder=()=>{
this.setState({loading:true}) this.setState({loading:true})
console.log(this.state.takeAmount)
const requestOptions = { const requestOptions = {
method: 'POST', method: 'POST',
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),}, headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),},
body: JSON.stringify({ body: JSON.stringify({
'action':'take', 'action':'take',
'amount':this.state.takeAmount,
}), }),
}; };
fetch('/api/order/' + '?order_id=' + this.orderId, requestOptions) fetch('/api/order/' + '?order_id=' + this.orderId, requestOptions)
@ -483,10 +534,17 @@ export default class OrderPage extends Component {
<ListItemIcon> <ListItemIcon>
{getFlags(this.state.currencyCode)} {getFlags(this.state.currencyCode)}
</ListItemIcon> </ListItemIcon>
{this.state.has_range & this.state.amount == null ?
<ListItemText primary={parseFloat(Number(this.state.min_amount).toPrecision(2))
+"-" + parseFloat(Number(this.state.max_amount).toPrecision(2)) +" "+this.state.currencyCode} secondary="Amount range"/>
:
<ListItemText primary={parseFloat(parseFloat(this.state.amount).toFixed(4)) <ListItemText primary={parseFloat(parseFloat(this.state.amount).toFixed(4))
+" "+this.state.currencyCode} secondary="Amount"/> +" "+this.state.currencyCode} secondary="Amount"/>
}
</ListItem> </ListItem>
<Divider /> <Divider />
<ListItem> <ListItem>
<ListItemIcon> <ListItemIcon>
<PaymentsIcon/> <PaymentsIcon/>

File diff suppressed because one or more lines are too long