mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-31 10:31:35 +00:00
Add needed LNNode routines and LNpayments status. First full trade demonstrated
This commit is contained in:
parent
a3375df6e5
commit
2523e5ef09
@ -26,7 +26,7 @@ class EUserAdmin(UserAdmin):
|
|||||||
class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin):
|
class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin):
|
||||||
list_display = ('id','type','maker_link','taker_link','status','amount','currency','t0_satoshis','is_disputed','is_fiat_sent','created_at','expires_at', 'buyer_invoice_link','maker_bond_link','taker_bond_link','trade_escrow_link')
|
list_display = ('id','type','maker_link','taker_link','status','amount','currency','t0_satoshis','is_disputed','is_fiat_sent','created_at','expires_at', 'buyer_invoice_link','maker_bond_link','taker_bond_link','trade_escrow_link')
|
||||||
list_display_links = ('id','type')
|
list_display_links = ('id','type')
|
||||||
change_links = ('maker','taker','buyer_invoice','maker_bond','taker_invoice','taker_bond','trade_escrow')
|
change_links = ('maker','taker','buyer_invoice','maker_bond','taker_bond','trade_escrow')
|
||||||
list_filter = ('is_disputed','is_fiat_sent','type','currency','status')
|
list_filter = ('is_disputed','is_fiat_sent','type','currency','status')
|
||||||
|
|
||||||
@admin.register(LNPayment)
|
@admin.register(LNPayment)
|
||||||
|
@ -83,6 +83,8 @@ class LNNode():
|
|||||||
'''Checks if hold invoice is locked'''
|
'''Checks if hold invoice is locked'''
|
||||||
request = invoicesrpc.LookupInvoiceMsg(payment_hash=bytes.fromhex(payment_hash))
|
request = invoicesrpc.LookupInvoiceMsg(payment_hash=bytes.fromhex(payment_hash))
|
||||||
response = cls.invoicesstub.LookupInvoiceV2(request, metadata=[('macaroon', MACAROON.hex())])
|
response = cls.invoicesstub.LookupInvoiceV2(request, metadata=[('macaroon', MACAROON.hex())])
|
||||||
|
print('status here')
|
||||||
|
print(response.state)
|
||||||
return response.state == 3 # True if hold invoice is accepted.
|
return response.state == 3 # True if hold invoice is accepted.
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -142,32 +144,38 @@ class LNNode():
|
|||||||
buyer_invoice['description'] = payreq_decoded.description
|
buyer_invoice['description'] = payreq_decoded.description
|
||||||
buyer_invoice['payment_hash'] = payreq_decoded.payment_hash
|
buyer_invoice['payment_hash'] = payreq_decoded.payment_hash
|
||||||
|
|
||||||
|
|
||||||
return buyer_invoice
|
return buyer_invoice
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def pay_invoice(cls, invoice, num_satoshis):
|
def pay_invoice(cls, invoice, num_satoshis):
|
||||||
'''Sends sats to buyer'''
|
'''Sends sats to buyer'''
|
||||||
# Needs router subservice
|
|
||||||
# Maybe best to pass order and change status live.
|
|
||||||
|
|
||||||
fee_limit_sat = max(num_satoshis * 0.0002, 10) # 200 ppm or 10 sats
|
fee_limit_sat = max(num_satoshis * 0.0002, 10) # 200 ppm or 10 sats
|
||||||
|
|
||||||
request = routerrpc.SendPaymentRequest(
|
request = routerrpc.SendPaymentRequest(
|
||||||
payment_request=invoice,
|
payment_request=invoice,
|
||||||
amt_msat=num_satoshis,
|
|
||||||
fee_limit_sat=fee_limit_sat,
|
fee_limit_sat=fee_limit_sat,
|
||||||
timeout_seconds=60)
|
timeout_seconds=60)
|
||||||
|
|
||||||
for response in cls.routerstub.SendPaymentV2(request, metadata=[('macaroon', MACAROON.hex())]):
|
for response in cls.routerstub.SendPaymentV2(request, metadata=[('macaroon', MACAROON.hex())]):
|
||||||
if response.status == True:
|
print(response)
|
||||||
|
print(response.status)
|
||||||
|
print(response.grpc_status)
|
||||||
|
if response.status == 1 : # Status 1 'IN_FLIGHT'
|
||||||
|
pass # LIVE UPDATE THE order.lnpayment.status
|
||||||
|
if response.status == 'FAILED':
|
||||||
|
pass # LIVE UPDATE THE order.lnpayment.status
|
||||||
|
if response.status == 2 : # STATUS 'SUCCEEDED'
|
||||||
return True
|
return True
|
||||||
|
# How to catch the errors like:"grpc_message":"invoice is already paid","grpc_status":6}
|
||||||
|
# These are not in the response only printed to commandline
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def double_check_htlc_is_settled(cls, payment_hash):
|
def double_check_htlc_is_settled(cls, payment_hash):
|
||||||
''' Just as it sounds. Better safe than sorry!'''
|
''' Just as it sounds. Better safe than sorry!'''
|
||||||
request = invoicesrpc.LookupInvoiceMsg(payment_hash=payment_hash)
|
request = invoicesrpc.LookupInvoiceMsg(payment_hash=bytes.fromhex(payment_hash))
|
||||||
response = cls.invoicesstub.LookupInvoiceV2(request, metadata=[('macaroon', MACAROON.hex())])
|
response = cls.invoicesstub.LookupInvoiceV2(request, metadata=[('macaroon', MACAROON.hex())])
|
||||||
|
|
||||||
return response.state == 1 # LND states: 0 OPEN, 1 SETTLED, 3 ACCEPTED, GRPC_ERROR status 5 when cancelled/returned
|
return response.state == 1 # LND states: 0 OPEN, 1 SETTLED, 3 ACCEPTED, GRPC_ERROR status 5 when cancelled/returned
|
||||||
|
@ -166,13 +166,16 @@ class Logics():
|
|||||||
)
|
)
|
||||||
|
|
||||||
# If the order status is 'Waiting for invoice'. Move forward to 'chat'
|
# If the order status is 'Waiting for invoice'. Move forward to 'chat'
|
||||||
if order.status == Order.Status.WFI: order.status = Order.Status.CHA
|
if order.status == Order.Status.WFI:
|
||||||
|
order.status = Order.Status.CHA
|
||||||
|
order.expires_at = timezone.now() + timedelta(hours=FIAT_EXCHANGE_DURATION)
|
||||||
|
|
||||||
# If the order status is 'Waiting for both'. Move forward to 'waiting for escrow'
|
# If the order status is 'Waiting for both'. Move forward to 'waiting for escrow'
|
||||||
if order.status == Order.Status.WF2:
|
if order.status == Order.Status.WF2:
|
||||||
if order.trade_escrow:
|
# If the escrow is lock move to Chat.
|
||||||
if order.trade_escrow.status == LNPayment.Status.LOCKED:
|
if order.trade_escrow.status == LNPayment.Status.LOCKED:
|
||||||
order.status = Order.Status.CHA
|
order.status = Order.Status.CHA
|
||||||
|
order.expires_at = timezone.now() + timedelta(hours=FIAT_EXCHANGE_DURATION)
|
||||||
else:
|
else:
|
||||||
order.status = Order.Status.WFE
|
order.status = Order.Status.WFE
|
||||||
|
|
||||||
@ -312,7 +315,7 @@ class Logics():
|
|||||||
order.last_satoshis = cls.satoshis_now(order)
|
order.last_satoshis = cls.satoshis_now(order)
|
||||||
bond_satoshis = int(order.last_satoshis * BOND_SIZE)
|
bond_satoshis = int(order.last_satoshis * BOND_SIZE)
|
||||||
|
|
||||||
description = f"RoboSats - Publishing '{str(order)}' - This is a maker bond, it will freeze in your wallet. It automatically returns. It will be charged if you cheat or cancel."
|
description = f"RoboSats - Publishing '{str(order)}' - This is a maker bond, it will freeze in your wallet temporarily and automatically return. It will be charged if you cheat or cancel."
|
||||||
|
|
||||||
# Gen hold Invoice
|
# Gen hold Invoice
|
||||||
hold_payment = LNNode.gen_hold_invoice(bond_satoshis, description, BOND_EXPIRY*3600)
|
hold_payment = LNNode.gen_hold_invoice(bond_satoshis, description, BOND_EXPIRY*3600)
|
||||||
@ -368,7 +371,7 @@ class Logics():
|
|||||||
# If there was no taker_bond object yet, generates one
|
# If there was no taker_bond object yet, generates one
|
||||||
order.last_satoshis = cls.satoshis_now(order)
|
order.last_satoshis = cls.satoshis_now(order)
|
||||||
bond_satoshis = int(order.last_satoshis * BOND_SIZE)
|
bond_satoshis = int(order.last_satoshis * BOND_SIZE)
|
||||||
description = f"RoboSats - Taking '{str(order)}' - This is a taker bond, it will freeze in your wallet. It automatically returns. It will be charged if you cheat or cancel."
|
description = f"RoboSats - Taking '{str(order)}' - This is a taker bond, it will freeze in your wallet temporarily and automatically return. It will be charged if you cheat or cancel."
|
||||||
|
|
||||||
# Gen hold Invoice
|
# Gen hold Invoice
|
||||||
hold_payment = LNNode.gen_hold_invoice(bond_satoshis, description, BOND_EXPIRY*3600)
|
hold_payment = LNNode.gen_hold_invoice(bond_satoshis, description, BOND_EXPIRY*3600)
|
||||||
@ -400,7 +403,7 @@ class Logics():
|
|||||||
if order.status == Order.Status.WF2:
|
if order.status == Order.Status.WF2:
|
||||||
order.status = Order.Status.WFI
|
order.status = Order.Status.WFI
|
||||||
# If status is 'Waiting for invoice' move to Chat
|
# If status is 'Waiting for invoice' move to Chat
|
||||||
elif order.status == Order.Status.WFI:
|
elif order.status == Order.Status.WFE:
|
||||||
order.status = Order.Status.CHA
|
order.status = Order.Status.CHA
|
||||||
order.expires_at = timezone.now() + timedelta(hours=FIAT_EXCHANGE_DURATION)
|
order.expires_at = timezone.now() + timedelta(hours=FIAT_EXCHANGE_DURATION)
|
||||||
order.save()
|
order.save()
|
||||||
@ -471,10 +474,16 @@ class Logics():
|
|||||||
order.taker_bond.save()
|
order.taker_bond.save()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def return_bond(bond):
|
||||||
|
'''returns a bond'''
|
||||||
|
if LNNode.cancel_return_hold_invoice(bond.payment_hash):
|
||||||
|
bond.status = LNPayment.Status.RETNED
|
||||||
|
return True
|
||||||
|
|
||||||
def pay_buyer_invoice(order):
|
def pay_buyer_invoice(order):
|
||||||
''' Pay buyer invoice'''
|
''' Pay buyer invoice'''
|
||||||
# TODO ERROR HANDLING
|
# TODO ERROR HANDLING
|
||||||
if LNNode.pay_invoice(order.buyer_invoice.invoice):
|
if LNNode.pay_invoice(order.buyer_invoice.invoice, order.buyer_invoice.num_satoshis):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -498,18 +507,18 @@ class Logics():
|
|||||||
return False, {'bad_request':'You cannot confirm to have received the fiat before it is confirmed to be sent by the buyer.'}
|
return False, {'bad_request':'You cannot confirm to have received the fiat before it is confirmed to be sent by the buyer.'}
|
||||||
|
|
||||||
# Make sure the trade escrow is at least as big as the buyer invoice
|
# Make sure the trade escrow is at least as big as the buyer invoice
|
||||||
if order.trade_escrow.num_satoshis > order.buyer_invoice.num_satoshis:
|
if order.trade_escrow.num_satoshis <= order.buyer_invoice.num_satoshis:
|
||||||
return False, {'bad_request':'Woah, something broke badly. Report in the public channels, or open a Github Issue.'}
|
return False, {'bad_request':'Woah, something broke badly. Report in the public channels, or open a Github Issue.'}
|
||||||
|
|
||||||
# Double check the escrow is settled.
|
# Double check the escrow is settled.
|
||||||
if LNNode.double_check_htlc_is_settled(order.trade_escrow.payment_hash):
|
if LNNode.double_check_htlc_is_settled(order.trade_escrow.payment_hash):
|
||||||
if cls.pay_buyer_invoice(order): ##### !!! KEY LINE - PAYS THE BUYER INVOICE !!!
|
if cls.pay_buyer_invoice(order): ##### !!! KEY LINE - PAYS THE BUYER INVOICE !!!
|
||||||
order.status = Order.Status.PAY
|
order.status = Order.Status.PAY
|
||||||
order.buyer_invoice.status = LNPayment.Status.PAYING
|
order.buyer_invoice.status = LNPayment.Status.SETLED
|
||||||
|
|
||||||
# RETURN THE BONDS
|
# RETURN THE BONDS
|
||||||
LNNode.cancel_return_hold_invoice(order.taker_bond.payment_hash)
|
cls.return_bond(order.taker_bond)
|
||||||
LNNode.cancel_return_hold_invoice(order.maker_bond.payment_hash)
|
cls.return_bond(order.maker_bond)
|
||||||
else:
|
else:
|
||||||
return False, {'bad_request':'You cannot confirm the fiat payment at this stage'}
|
return False, {'bad_request':'You cannot confirm the fiat payment at this stage'}
|
||||||
|
|
||||||
|
@ -34,8 +34,10 @@ class LNPayment(models.Model):
|
|||||||
RETNED = 3, 'Returned'
|
RETNED = 3, 'Returned'
|
||||||
EXPIRE = 4, 'Expired'
|
EXPIRE = 4, 'Expired'
|
||||||
VALIDI = 5, 'Valid'
|
VALIDI = 5, 'Valid'
|
||||||
FLIGHT = 6, 'On flight'
|
FLIGHT = 6, 'In flight'
|
||||||
FAILRO = 7, 'Routing failed'
|
SUCCED = 7, 'Succeeded'
|
||||||
|
FAILRO = 8, 'Routing failed'
|
||||||
|
|
||||||
|
|
||||||
# payment use details
|
# payment use details
|
||||||
type = models.PositiveSmallIntegerField(choices=Types.choices, null=False, default=Types.HOLD)
|
type = models.PositiveSmallIntegerField(choices=Types.choices, null=False, default=Types.HOLD)
|
||||||
@ -44,10 +46,10 @@ class LNPayment(models.Model):
|
|||||||
routing_retries = models.PositiveSmallIntegerField(null=False, default=0)
|
routing_retries = models.PositiveSmallIntegerField(null=False, default=0)
|
||||||
|
|
||||||
# payment info
|
# payment info
|
||||||
invoice = models.CharField(max_length=1000, unique=True, null=True, default=None, blank=True)
|
invoice = models.CharField(max_length=1200, unique=True, null=True, default=None, blank=True) # Some invoices with lots of routing hints might be long
|
||||||
payment_hash = models.CharField(max_length=100, unique=True, null=True, default=None, blank=True)
|
payment_hash = models.CharField(max_length=100, unique=True, null=True, default=None, blank=True)
|
||||||
preimage = models.CharField(max_length=64, unique=True, null=True, default=None, blank=True)
|
preimage = models.CharField(max_length=64, unique=True, null=True, default=None, blank=True)
|
||||||
description = models.CharField(max_length=200, unique=False, null=True, default=None, blank=True)
|
description = models.CharField(max_length=500, unique=False, null=True, default=None, blank=True)
|
||||||
num_satoshis = models.PositiveBigIntegerField(validators=[MinValueValidator(MIN_TRADE*BOND_SIZE), MaxValueValidator(MAX_TRADE*(1+BOND_SIZE+FEE))])
|
num_satoshis = models.PositiveBigIntegerField(validators=[MinValueValidator(MIN_TRADE*BOND_SIZE), MaxValueValidator(MAX_TRADE*(1+BOND_SIZE+FEE))])
|
||||||
created_at = models.DateTimeField()
|
created_at = models.DateTimeField()
|
||||||
expires_at = models.DateTimeField()
|
expires_at = models.DateTimeField()
|
||||||
|
@ -12,6 +12,6 @@ class MakeOrderSerializer(serializers.ModelSerializer):
|
|||||||
fields = ('type','currency','amount','payment_method','is_explicit','premium','satoshis')
|
fields = ('type','currency','amount','payment_method','is_explicit','premium','satoshis')
|
||||||
|
|
||||||
class UpdateOrderSerializer(serializers.Serializer):
|
class UpdateOrderSerializer(serializers.Serializer):
|
||||||
invoice = serializers.CharField(max_length=300, allow_null=True, allow_blank=True, default=None)
|
invoice = serializers.CharField(max_length=2000, allow_null=True, allow_blank=True, default=None)
|
||||||
action = serializers.ChoiceField(choices=('take','update_invoice','dispute','cancel','confirm','rate'), allow_null=False)
|
action = serializers.ChoiceField(choices=('take','update_invoice','dispute','cancel','confirm','rate'), allow_null=False)
|
||||||
rating = serializers.ChoiceField(choices=('1','2','3','4','5'), allow_null=True, allow_blank=True, default=None)
|
rating = serializers.ChoiceField(choices=('1','2','3','4','5'), allow_null=True, allow_blank=True, default=None)
|
@ -137,7 +137,7 @@ class OrderView(viewsets.ViewSet):
|
|||||||
# If both bonds are locked, participants can see the final trade amount in sats.
|
# If both bonds are locked, participants can see the final trade amount in sats.
|
||||||
if order.taker_bond:
|
if order.taker_bond:
|
||||||
if order.maker_bond.status == order.taker_bond.status == LNPayment.Status.LOCKED:
|
if order.maker_bond.status == order.taker_bond.status == LNPayment.Status.LOCKED:
|
||||||
# Seller sees the amount he pays
|
# Seller sees the amount he sends
|
||||||
if data['is_seller']:
|
if data['is_seller']:
|
||||||
data['trade_satoshis'] = order.last_satoshis
|
data['trade_satoshis'] = order.last_satoshis
|
||||||
# Buyer sees the amount he receives
|
# Buyer sees the amount he receives
|
||||||
@ -227,6 +227,7 @@ class OrderView(viewsets.ViewSet):
|
|||||||
|
|
||||||
# 2) If action is 'update invoice'
|
# 2) If action is 'update invoice'
|
||||||
if action == 'update_invoice' and invoice:
|
if action == 'update_invoice' and invoice:
|
||||||
|
print('AAAAAAAAAAAAAAAAAAAAAAAAAAAA')
|
||||||
valid, context = Logics.update_invoice(order,request.user,invoice)
|
valid, context = Logics.update_invoice(order,request.user,invoice)
|
||||||
if not valid: return Response(context, status.HTTP_400_BAD_REQUEST)
|
if not valid: return Response(context, status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
@ -284,6 +284,11 @@ export default class OrderPage extends Component {
|
|||||||
<Button variant='contained' color='secondary' onClick={this.handleClickCancelOrderButton}>Cancel</Button>
|
<Button variant='contained' color='secondary' onClick={this.handleClickCancelOrderButton}>Cancel</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
:""}
|
:""}
|
||||||
|
{this.state.isMaker & this.state.statusCode > 0 & this.state.statusCode < 9 ?
|
||||||
|
<Grid item xs={12} align="center">
|
||||||
|
<Typography color="secondary" variant="subtitle2" component="subtitle2">Cancelling now forfeits the maker bond</Typography>
|
||||||
|
</Grid>
|
||||||
|
:""}
|
||||||
|
|
||||||
{/* Takers can cancel before commiting the bond (status 3)*/}
|
{/* Takers can cancel before commiting the bond (status 3)*/}
|
||||||
{this.state.isTaker & this.state.statusCode == 3 ?
|
{this.state.isTaker & this.state.statusCode == 3 ?
|
||||||
|
@ -70,6 +70,16 @@ export default class TradeBox extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showBondIsLocked=()=>{
|
||||||
|
return (
|
||||||
|
<Grid item xs={12} align="center">
|
||||||
|
<Typography color="primary" component="subtitle1" variant="subtitle1" align="center">
|
||||||
|
🔒 Your {this.props.data.isMaker ? 'maker' : 'taker'} bond is safely locked
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
showEscrowQRInvoice=()=>{
|
showEscrowQRInvoice=()=>{
|
||||||
return (
|
return (
|
||||||
<Grid container spacing={1}>
|
<Grid container spacing={1}>
|
||||||
@ -92,6 +102,7 @@ export default class TradeBox extends Component {
|
|||||||
color = "secondary"
|
color = "secondary"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{this.showBondIsLocked()}
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -113,6 +124,7 @@ export default class TradeBox extends Component {
|
|||||||
Please wait for the taker to confirm his commitment by locking a bond.
|
Please wait for the taker to confirm his commitment by locking a bond.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{this.showBondIsLocked()}
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -138,12 +150,6 @@ export default class TradeBox extends Component {
|
|||||||
return to you (no action needed).</p>
|
return to you (no action needed).</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider/>
|
|
||||||
<ListItem color="info" align="center">
|
|
||||||
<Typography color="primary" component="subtitle1" variant="subtitle1" align="center">
|
|
||||||
🔒 Your maker bond is safely locked
|
|
||||||
</Typography>
|
|
||||||
</ListItem>
|
|
||||||
{/* TODO API sends data for a more confortable wait */}
|
{/* TODO API sends data for a more confortable wait */}
|
||||||
<Divider/>
|
<Divider/>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
@ -159,8 +165,11 @@ export default class TradeBox extends Component {
|
|||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemText primary="33%" secondary="Premium percentile" />
|
<ListItemText primary="33%" secondary="Premium percentile" />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
<Divider/>
|
||||||
|
|
||||||
</List>
|
</List>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{this.showBondIsLocked()}
|
||||||
</Grid>
|
</Grid>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -225,6 +234,7 @@ export default class TradeBox extends Component {
|
|||||||
<Grid item xs={12} align="center">
|
<Grid item xs={12} align="center">
|
||||||
<Button variant='contained' color='primary' onClick={this.handleClickSubmitInvoiceButton}>Submit</Button>
|
<Button variant='contained' color='primary' onClick={this.handleClickSubmitInvoiceButton}>Submit</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{this.showBondIsLocked()}
|
||||||
</Grid>
|
</Grid>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -245,6 +255,7 @@ export default class TradeBox extends Component {
|
|||||||
you will get your bond back automatically.</p>
|
you will get your bond back automatically.</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{this.showBondIsLocked()}
|
||||||
</Grid>
|
</Grid>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -266,6 +277,7 @@ export default class TradeBox extends Component {
|
|||||||
you will get back the trade collateral and your bond automatically.</p>
|
you will get back the trade collateral and your bond automatically.</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{this.showBondIsLocked()}
|
||||||
</Grid>
|
</Grid>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -322,21 +334,17 @@ handleRatingChange=(e)=>{
|
|||||||
// TODO, show alert and ask for double confirmation (Have you check you received the fiat? Confirming fiat received settles the trade.)
|
// TODO, show alert and ask for double confirmation (Have you check you received the fiat? Confirming fiat received settles the trade.)
|
||||||
// Ask for double confirmation.
|
// Ask for double confirmation.
|
||||||
return(
|
return(
|
||||||
<Grid container spacing={1}>
|
|
||||||
<Grid item xs={12} align="center">
|
<Grid item xs={12} align="center">
|
||||||
<Button defaultValue="confirm" variant='contained' color='primary' onClick={this.handleClickConfirmButton}>Confirm {this.props.data.currencyCode} received</Button>
|
<Button defaultValue="confirm" variant='contained' color='primary' onClick={this.handleClickConfirmButton}>Confirm {this.props.data.currencyCode} received</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
showOpenDisputeButton(){
|
showOpenDisputeButton(){
|
||||||
// TODO, show alert about how opening a dispute might involve giving away personal data and might mean losing the bond. Ask for double confirmation.
|
// TODO, show alert about how opening a dispute might involve giving away personal data and might mean losing the bond. Ask for double confirmation.
|
||||||
return(
|
return(
|
||||||
<Grid container spacing={1}>
|
|
||||||
<Grid item xs={12} align="center">
|
<Grid item xs={12} align="center">
|
||||||
<Button defaultValue="dispute" variant='contained' onClick={this.handleClickOpenDisputeButton}>Open Dispute</Button>
|
<Button color="inherit" onClick={this.handleClickOpenDisputeButton}>Open Dispute</Button>
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -368,19 +376,11 @@ handleRatingChange=(e)=>{
|
|||||||
{receivedFiatButton ? this.showFiatReceivedButton() : ""}
|
{receivedFiatButton ? this.showFiatReceivedButton() : ""}
|
||||||
{openDisputeButton ? this.showOpenDisputeButton() : ""}
|
{openDisputeButton ? this.showOpenDisputeButton() : ""}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{this.showBondIsLocked()}
|
||||||
</Grid>
|
</Grid>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// showFiatReceivedButton(){
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// showOpenDisputeButton(){
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
showRateSelect(){
|
showRateSelect(){
|
||||||
return(
|
return(
|
||||||
<Grid container spacing={1}>
|
<Grid container spacing={1}>
|
||||||
|
Loading…
Reference in New Issue
Block a user