Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions api/lightning/cln.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,12 +585,19 @@ def watchpayment():
time.sleep(2)

def handle_response():
from api.logics import Logics

if not order.transition_status(
Order.Status.PAY,
from_statuses=[Order.Status.PAY, Order.Status.FAI],
):
return

try:
lnpayment.status = LNPayment.Status.FLIGHT
lnpayment.in_flight = True
lnpayment.save(update_fields=["in_flight", "status"])

order.update_status(Order.Status.PAY)
nodestub = node_pb2_grpc.NodeStub(cls.node_channel)
response = nodestub.Pay(request)

Expand Down Expand Up @@ -649,7 +656,7 @@ def handle_response():
)
lnpayment.preimage = response.payment_preimage.hex()
lnpayment.save(update_fields=["status", "fee", "preimage"])
order.update_status(Order.Status.SUC)
Logics.complete_order(order)
order.expires_at = timezone.now() + timedelta(
seconds=order.t_to_expire(Order.Status.SUC)
)
Expand Down
12 changes: 9 additions & 3 deletions api/lightning/lnd.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,11 +546,17 @@ def follow_send_payment(cls, lnpayment, fee_limit_sat, timeout_seconds):
return

def handle_response(response, was_in_transit=False):
from api.logics import Logics

if not order.transition_status(
Order.Status.PAY,
from_statuses=[Order.Status.PAY, Order.Status.FAI],
):
return

lnpayment.status = LNPayment.Status.FLIGHT
lnpayment.in_flight = True
lnpayment.save(update_fields=["in_flight", "status"])
order.update_status(Order.Status.PAY)
order.save(update_fields=["status"])

if (
response.status == lightning_pb2.Payment.PaymentStatus.UNKNOWN
Expand Down Expand Up @@ -625,7 +631,7 @@ def handle_response(response, was_in_transit=False):
lnpayment.preimage = response.payment_preimage
lnpayment.save(update_fields=["status", "fee", "preimage"])

order.update_status(Order.Status.SUC)
Logics.complete_order(order)
order.expires_at = timezone.now() + timedelta(
seconds=order.t_to_expire(Order.Status.SUC)
)
Expand Down
26 changes: 19 additions & 7 deletions api/logics.py
Original file line number Diff line number Diff line change
Expand Up @@ -967,9 +967,10 @@ def move_state_updated_payout_method(cls, order):
order.update_status(Order.Status.WFE)

# If the order status is 'Failed Routing'. Retry payment.
elif order.status == Order.Status.FAI:
if LNNode.double_check_htlc_is_settled(order.trade_escrow.payment_hash):
order.update_status(Order.Status.PAY)
elif LNNode.double_check_htlc_is_settled(order.trade_escrow.payment_hash):
if order.transition_status(
Order.Status.PAY, from_statuses=[Order.Status.FAI]
):
order.payout.status = LNPayment.Status.FLIGHT
order.payout.routing_attempts = 0
order.payout.save(update_fields=["status", "routing_attempts"])
Expand Down Expand Up @@ -1657,14 +1658,28 @@ def pay_buyer(cls, order):
order.payout_tx.status = OnchainPayment.Status.QUEUE
order.payout_tx.save(update_fields=["status"])

order.update_status(Order.Status.SUC)
cls.complete_order(order)
order.contract_finalization_time = timezone.now()
order.save(update_fields=["contract_finalization_time"])

send_notification.delay(order_id=order.id, message="trade_successful")
order.log("<b>Paying buyer onchain address</b>")
return True

@classmethod
def complete_order(cls, order):
"""
Completes the order after the the sats are successfully paid out
and computes the coordinator revenue.
"""
if not order.transition_status(
Order.Status.SUC, from_statuses=[Order.Status.FSE, Order.Status.PAY, Order.Status.FAI]
):
return

# Computes coordinator trade revenue
cls.compute_proceeds(order)

@classmethod
def confirm_fiat(cls, order, user):
"""If Order is in the CHAT states:
Expand Down Expand Up @@ -1710,9 +1725,6 @@ def confirm_fiat(cls, order, user):
# !!! KEY LINE - PAYS THE BUYER INVOICE !!!
cls.pay_buyer(order)

# Computes coordinator trade revenue
cls.compute_proceeds(order)

return True, None

else:
Expand Down
33 changes: 30 additions & 3 deletions api/models/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,39 @@ def update_status(self, new_status):
old_status = self.status
self.status = new_status
self.save(update_fields=["status"])
self.log(
f"Order state went from {old_status}: <i>{Order.Status(old_status).label}</i> to {new_status}: <i>{Order.Status(new_status).label}</i>"
)

self.log_status_transition(old_status, new_status)

if new_status == Order.Status.FAI:
send_notification.delay(order_id=self.id, message="lightning_failed")

def transition_status(self, new_status, from_statuses):
"""
Atomically transition the order to `new_status` only if its current
database status is one of `from_statuses`.

Returns True if the transition happened, False otherwise.
The in-memory `self.status` is kept in sync on success.
"""
updated = Order.objects.filter(
pk=self.pk,
status__in=from_statuses,
).update(status=new_status)

if updated == 1:
old_status = self.status
self.status = new_status
self.log_status_transition(old_status, new_status)
return True

return False

def log_status_transition(self, old_status, new_status):
if old_status != new_status:
self.log(
f"Order state went from {old_status}: <i>{Order.Status(old_status).label}</i> to {new_status}: <i>{Order.Status(new_status).label}</i>"
)


@receiver(pre_delete, sender=Order)
def delete_lnpayment_at_order_deletion(sender, instance, **kwargs):
Expand Down
Loading