diff --git a/api/logics.py b/api/logics.py index 85ff5de5..4edb0c09 100644 --- a/api/logics.py +++ b/api/logics.py @@ -125,7 +125,7 @@ class Logics(): elif order.status == Order.Status.WFB: order.status = Order.Status.EXP cls.cancel_bond(order.maker_bond) - order.maker = None + order.maker = None # TODO with the new validate_already_maker_taker there is no need to kick out participants on expired orders. order.taker = None order.save() return True @@ -175,12 +175,10 @@ class Logics(): else: cls.settle_bond(order.taker_bond) cls.cancel_escrow(order) - order.status = Order.Status.PUB order.taker = None order.taker_bond = None order.trade_escrow = None - order.expires_at = order.created_at + timedelta(seconds=Order.t_to_expire[Order.Status.PUB]) - order.save() + cls.publish_order(order) return True elif order.status == Order.Status.WFI: @@ -203,12 +201,10 @@ class Logics(): else: cls.settle_bond(order.taker_bond) cls.return_escrow(order) - order.status = Order.Status.PUB order.taker = None order.taker_bond = None order.trade_escrow = None - order.expires_at = order.created_at + timedelta(seconds=Order.t_to_expire[Order.Status.PUB]) - order.save() + cls.publish_order(order) return True elif order.status == Order.Status.CHA: @@ -218,7 +214,8 @@ class Logics(): cls.open_dispute(order) return True - def kick_taker(order): + @classmethod + def kick_taker(cls, order): ''' The taker did not lock the taker_bond. Now he has to go''' # Add a time out to the taker profile = order.taker.profile @@ -226,11 +223,9 @@ class Logics(): profile.save() # Make order public again - order.status = Order.Status.PUB order.taker = None order.taker_bond = None - order.expires_at = order.created_at + timedelta(seconds=Order.t_to_expire[Order.Status.PUB]) - order.save() + cls.publish_order(order) return True @classmethod @@ -417,14 +412,12 @@ class Logics(): # 4.b) When taker cancel after bond (before escrow) '''The order into cancelled status if maker cancels.''' - elif order.status > Order.Status.TAK and order.status < Order.Status.CHA and order.taker == user: + elif order.status in [Order.Status.WF2, Order.Status.WFE] and order.taker == user: # Settle the maker bond (Maker loses the bond for canceling an ongoing trade) valid = cls.settle_bond(order.taker_bond) if valid: order.taker = None - order.status = Order.Status.PUB - # order.taker_bond = None # TODO fix this, it overrides the information about the settled taker bond. Might make admin tasks hard. - order.save() + cls.publish_order(order) return True, None # 5) When trade collateral has been posted (after escrow) @@ -437,12 +430,10 @@ class Logics(): return False, {'bad_request':'You cannot cancel this order'} def publish_order(order): - if order.status == Order.Status.WFB: - order.status = Order.Status.PUB - # With the bond confirmation the order is extended 'public_order_duration' hours - order.expires_at = order.created_at + timedelta(seconds=Order.t_to_expire[Order.Status.PUB]) - order.save() - return + order.status = Order.Status.PUB + order.expires_at = order.created_at + timedelta(seconds=Order.t_to_expire[Order.Status.PUB]) + order.save() + return @classmethod def is_maker_bond_locked(cls, order): diff --git a/api/views.py b/api/views.py index b89fc61f..2efcded3 100644 --- a/api/views.py +++ b/api/views.py @@ -166,14 +166,14 @@ class OrderView(viewsets.ViewSet): data['escrow_locked'] = False # If both bonds are locked, participants can see the final trade amount in sats. - if order.taker_bond: - if order.maker_bond.status == order.taker_bond.status == LNPayment.Status.LOCKED: - # Seller sees the amount he sends - if data['is_seller']: - data['trade_satoshis'] = order.last_satoshis - # Buyer sees the amount he receives - elif data['is_buyer']: - data['trade_satoshis'] = Logics.buyer_invoice_amount(order, request.user)[1]['invoice_amount'] + # if order.taker_bond: + # if order.maker_bond.status == order.taker_bond.status == LNPayment.Status.LOCKED: + # # Seller sees the amount he sends + # if data['is_seller']: + # data['trade_satoshis'] = order.last_satoshis + # # Buyer sees the amount he receives + # elif data['is_buyer']: + # data['trade_satoshis'] = Logics.buyer_invoice_amount(order, request.user)[1]['invoice_amount'] # 5) If status is 'waiting for maker bond' and user is MAKER, reply with a MAKER hold invoice. if order.status == Order.Status.WFB and data['is_maker']: diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index 8de89617..138e5eb7 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -166,10 +166,10 @@ export default class BookPage extends Component { style: {textAlign:"center"} }} onChange={this.handleCurrencyChange} - > ANY + > 🌍 ANY { Object.entries(this.state.currencies_dict) - .map( ([key, value]) => {value} ) + .map( ([key, value]) => {getFlags(value) + " " + value} ) } diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index 7ca10bda..b415a07b 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -1,5 +1,5 @@ import React, { Component } from "react"; -import { Alert, Paper, CircularProgress, Button , Grid, Typography, List, ListItem, ListItemIcon, ListItemText, ListItemAvatar, Avatar, Divider, Box, LinearProgress} from "@mui/material" +import { 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 TradeBox from "./TradeBox"; import getFlags from './getFlags' @@ -11,6 +11,7 @@ import PriceChangeIcon from '@mui/icons-material/PriceChange'; import PaymentsIcon from '@mui/icons-material/Payments'; import MoneyIcon from '@mui/icons-material/Money'; import ArticleIcon from '@mui/icons-material/Article'; +import ContentCopy from "@mui/icons-material/ContentCopy"; function getCookie(name) { let cookieValue = null; @@ -43,6 +44,7 @@ export default class OrderPage extends Component { currencies_dict: {"1":"USD"}, total_secs_expiry: 300, loading: true, + openCancel: false, }; this.orderId = this.props.match.params.orderId; this.getCurrencyDict(); @@ -144,8 +146,8 @@ export default class OrderPage extends Component { countdownRenderer = ({ total, hours, minutes, seconds, completed }) => { if (completed) { // Render a completed state - this.getOrderDetails(); - return null; + return ( The order has expired); + } else { var col = 'black' var fraction_left = (total/1000) / this.state.total_secs_expiry @@ -218,7 +220,7 @@ export default class OrderPage extends Component { return code } - handleClickCancelOrderButton=()=>{ + handleClickConfirmCancelButton=()=>{ console.log(this.state) const requestOptions = { method: 'POST', @@ -230,6 +232,64 @@ export default class OrderPage extends Component { fetch('/api/order/' + '?order_id=' + this.orderId, requestOptions) .then((response) => response.json()) .then((data) => (console.log(data) & this.getOrderDetails(data.id))); + this.handleClickCloseConfirmCancelDialog(); + } + + handleClickOpenConfirmCancelDialog = () => { + this.setState({openCancel: true}); + }; + handleClickCloseConfirmCancelDialog = () => { + this.setState({openCancel: false}); + }; + + CancelDialog =() =>{ + return( + + + {"Cancel the order?"} + + + + If the order is cancelled now you will lose your bond. + + + + + + + + ) + } + + CancelButton = () => { + + // If maker and Waiting for Bond. Or if taker and Waiting for bond. + // Simply allow to cancel without showing the cancel dialog. + if ((this.state.isMaker & this.state.statusCode == 0) || this.state.isTaker & this.state.statusCode == 3){ + return( + + + + )} + // If the order does not yet have an escrow deposited. Show dialog + // to confirm forfeiting the bond + if (this.state.statusCode < 8){ + return( + + + + + )} + + // TODO If the escrow is Locked, show the collaborative cancel button. + + // If none of the above do not return a cancel button. + return(null) } orderBox=()=>{ @@ -346,8 +406,10 @@ export default class OrderPage extends Component { - {/* Participants cannot see the Back or Take Order buttons */} - {this.state.isParticipant ? "" : + {/* Participants can see the "Cancel" Button, but cannot see the "Back" or "Take Order" buttons */} + {this.state.isParticipant ? + + : <> @@ -358,27 +420,7 @@ export default class OrderPage extends Component { } - {/* Makers can cancel before trade escrow deposited (status <9)*/} - {/* Only free cancel before bond locked (status 0)*/} - {this.state.isMaker & this.state.statusCode < 9 ? - - - - :""} - {this.state.isMaker & this.state.statusCode > 0 & this.state.statusCode < 9 ? - - Cancelling now forfeits the maker bond - - :""} - - {/* Takers can cancel before commiting the bond (status 3)*/} - {this.state.isTaker & this.state.statusCode == 3 ? - - - - :""} - - + ) } diff --git a/frontend/src/components/TradeBox.js b/frontend/src/components/TradeBox.js index e8ed00a8..89f0cd8a 100644 --- a/frontend/src/components/TradeBox.js +++ b/frontend/src/components/TradeBox.js @@ -183,7 +183,7 @@ export default class TradeBox extends Component { return ( - + Deposit {pn(this.props.data.escrowSatoshis)} Sats as trade collateral @@ -569,7 +569,6 @@ handleRatingChange=(e)=>{ ) } - render() { return ( diff --git a/frontend/src/components/UserGenPage.js b/frontend/src/components/UserGenPage.js index 45eb625c..48341242 100644 --- a/frontend/src/components/UserGenPage.js +++ b/frontend/src/components/UserGenPage.js @@ -150,15 +150,15 @@ export default class UserGenPage extends Component { navigator.clipboard.writeText(this.state.token)}> - +