From bed65dd97ba5bcb7cc6d539e77d13d1c90c4e6f4 Mon Sep 17 00:00:00 2001 From: fusion44 Date: Mon, 4 Jul 2022 21:06:11 +0200 Subject: [PATCH] fix(CLN): fix multiple issues with send-payment * CLN PaymentStatus decoding was incorrect * don't set Amount when user passes None as the amount * catch gRPC errors and return appropriate status codes * clarify in docs that implementation behavior is different when attempting to pay an already paid invoice refs #129, refs #131 --- app/models/lightning.py | 8 +++---- app/repositories/ln_impl/cln_grpc.py | 31 ++++++++++++++++++++++++++-- app/routers/lightning.py | 4 +++- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/app/models/lightning.py b/app/models/lightning.py index e74704b..e431207 100644 --- a/app/models/lightning.py +++ b/app/models/lightning.py @@ -695,11 +695,11 @@ class PaymentStatus(str, Enum): @classmethod def from_cln_grpc(cls, id) -> "PaymentStatus": if id == 0: - return PaymentStatus.IN_FLIGHT - elif id == 1: - return PaymentStatus.FAILED - elif id == 2: return PaymentStatus.SUCCEEDED + elif id == 1: + return PaymentStatus.IN_FLIGHT + elif id == 2: + return PaymentStatus.FAILED else: raise NotImplementedError(f"PaymentStatus {id} is not implemented") diff --git a/app/repositories/ln_impl/cln_grpc.py b/app/repositories/ln_impl/cln_grpc.py index bd1e2dc..c7f082f 100644 --- a/app/repositories/ln_impl/cln_grpc.py +++ b/app/repositories/ln_impl/cln_grpc.py @@ -554,7 +554,7 @@ async def send_payment_impl( f"CLN_GRPC: send_payment_impl(pay_req={pay_req}, timeout_seconds={timeout_seconds}, fee_limit_msat={fee_limit_msat}, amount_msat={amount_msat})" ) - amt = lnp.Amount(msat=amount_msat) + amt = lnp.Amount(msat=amount_msat) if amount_msat != None else None fee_limit = lnp.Amount(msat=fee_limit_msat) req = ln.PayRequest( bolt11=pay_req, @@ -562,7 +562,34 @@ async def send_payment_impl( maxfee=fee_limit, retry_for=timeout_seconds, ) - res = await _cln_stub.Pay(req) + + try: + res = await _cln_stub.Pay(req) + except grpc.aio._call.AioRpcError as error: + details = error.details() + + if "Ran out of routes to try after" in details: + attempts = details.split("Ran out of routes to try after ")[1] + attempts = attempts.split(" attempts")[0] + raise HTTPException( + status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Ran out of routes to try after {attempts} attempts.", + ) + + if "msatoshi parameter required" in details: + raise HTTPException( + status.HTTP_400_BAD_REQUEST, + detail="amount must be specified when paying a zero amount invoice", + ) + + if "msatoshi parameter unnecessary" in details: + raise HTTPException( + status.HTTP_400_BAD_REQUEST, + detail="amount must not be specified when paying a non-zero amount invoice", + ) + + raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR, detail=details) + return Payment.from_cln_grpc(res) diff --git a/app/routers/lightning.py b/app/routers/lightning.py index 8349dbb..6460e4c 100644 --- a/app/routers/lightning.py +++ b/app/routers/lightning.py @@ -372,7 +372,9 @@ Possible error messages: * amount must not be specified when paying a non-zero amount invoice """ }, - 409: {"description": "When attempting to pay an already paid invoice."}, + 409: { + "description": "[LND only] When attempting to pay an already paid invoice. CLN will return the payment object of the previously paid invoice. Info: [GitHub](https://github.com/fusion44/blitz_api/issues/131)", + }, 423: responses[423], }, )