mirror of
https://github.com/fusion44/blitz_api.git
synced 2026-08-16 12:20:14 +02:00
parent
43783549d1
commit
ffdfe9fed6
5 changed files with 114 additions and 28 deletions
|
|
@ -48,25 +48,25 @@ class Feature(BaseModel):
|
|||
is_required: bool
|
||||
is_known: bool
|
||||
|
||||
|
||||
def feature_from_grpc(f):
|
||||
return Feature(
|
||||
name=f.name,
|
||||
is_required=f.is_required,
|
||||
is_known=f.is_known,
|
||||
)
|
||||
@classmethod
|
||||
def from_grpc(cls, f):
|
||||
return cls(
|
||||
name=f.name,
|
||||
is_required=f.is_required,
|
||||
is_known=f.is_known,
|
||||
)
|
||||
|
||||
|
||||
class FeaturesEntry(BaseModel):
|
||||
key: int
|
||||
value: Feature
|
||||
|
||||
|
||||
def features_entry_from_grpc(entry_key, feature):
|
||||
return FeaturesEntry(
|
||||
key=entry_key,
|
||||
value=feature_from_grpc(feature),
|
||||
)
|
||||
@classmethod
|
||||
def from_grpc(cls, entry_key, feature):
|
||||
return cls(
|
||||
key=entry_key,
|
||||
value=Feature.from_grpc(feature),
|
||||
)
|
||||
|
||||
|
||||
class AMP(BaseModel):
|
||||
|
|
@ -187,15 +187,15 @@ class RouteHint(BaseModel):
|
|||
# The time-lock delta of the channel.
|
||||
cltv_expiry_delta: int
|
||||
|
||||
|
||||
def route_hint_from_grpc(h) -> RouteHint:
|
||||
return RouteHint(
|
||||
node_id=h.node_id,
|
||||
chan_id=h.chan_id,
|
||||
fee_base_msat=h.fee_base_msat,
|
||||
fee_proportional_millionths=h.fee_proportional_millionths,
|
||||
cltv_expiry_delta=h.cltv_expiry_delta,
|
||||
)
|
||||
@classmethod
|
||||
def from_grpc(cls, h) -> "RouteHint":
|
||||
return cls(
|
||||
node_id=h.node_id,
|
||||
chan_id=h.chan_id,
|
||||
fee_base_msat=h.fee_base_msat,
|
||||
fee_proportional_millionths=h.fee_proportional_millionths,
|
||||
cltv_expiry_delta=h.cltv_expiry_delta,
|
||||
)
|
||||
|
||||
|
||||
class Invoice(BaseModel):
|
||||
|
|
@ -311,7 +311,7 @@ def invoice_from_grpc(i) -> Invoice:
|
|||
def _route_hints(hints):
|
||||
l = []
|
||||
for h in hints:
|
||||
l.append(route_hint_from_grpc(h))
|
||||
l.append(RouteHint.from_grpc((h)))
|
||||
return l
|
||||
|
||||
def _htlcs(htlcs):
|
||||
|
|
@ -323,7 +323,7 @@ def invoice_from_grpc(i) -> Invoice:
|
|||
def _features(features):
|
||||
l = []
|
||||
for k in features:
|
||||
l.append(features_entry_from_grpc(k, features[k]))
|
||||
l.append(FeaturesEntry.from_grpc(k, features[k]))
|
||||
return l
|
||||
|
||||
return Invoice(
|
||||
|
|
@ -833,7 +833,7 @@ def ln_info_from_grpc(i) -> LnInfo:
|
|||
|
||||
_features = []
|
||||
for f in i.features:
|
||||
_features.append(features_entry_from_grpc(f, i.features[f]))
|
||||
_features.append(FeaturesEntry.from_grpc(f, i.features[f]))
|
||||
|
||||
_uris = [u for u in i.uris]
|
||||
|
||||
|
|
@ -935,3 +935,37 @@ class WalletBalance(BaseModel):
|
|||
channel_pending_open_local_balance=channel.pending_open_local_balance.msat,
|
||||
channel_pending_open_remote_balance=channel.pending_open_remote_balance.msat,
|
||||
)
|
||||
|
||||
|
||||
class PaymentRequest(BaseModel):
|
||||
destination: str
|
||||
payment_hash: str
|
||||
num_satoshis: int
|
||||
timestamp: int
|
||||
expiry: int
|
||||
description: str
|
||||
description_hash: str
|
||||
fallback_addr: Optional[str]
|
||||
cltv_expiry: int
|
||||
route_hints: List[RouteHint] = Query([])
|
||||
payment_addr: str = Query(..., description="The payment address in hex format")
|
||||
num_msat: int
|
||||
features: List[FeaturesEntry] = Query([])
|
||||
|
||||
@classmethod
|
||||
def from_grpc(cls, r):
|
||||
return cls(
|
||||
destination=r.destination,
|
||||
payment_hash=r.payment_hash,
|
||||
num_satoshis=r.num_satoshis,
|
||||
timestamp=r.timestamp,
|
||||
expiry=r.expiry,
|
||||
description=r.description,
|
||||
description_hash=r.description_hash,
|
||||
fallback_addr=r.fallback_addr,
|
||||
cltv_expiry=r.cltv_expiry,
|
||||
route_hints=[RouteHint.from_grpc(rh) for rh in r.route_hints],
|
||||
payment_addr=r.payment_addr.hex(),
|
||||
num_msat=r.num_msat,
|
||||
features=[FeaturesEntry.from_grpc(k, r.features[k]) for k in r.features],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
import asyncio
|
||||
|
||||
from app.models.lightning import Invoice, LightningStatus, LnInfo, Payment
|
||||
from app.models.lightning import (
|
||||
Invoice,
|
||||
LightningStatus,
|
||||
LnInfo,
|
||||
Payment,
|
||||
PaymentRequest,
|
||||
)
|
||||
from app.utils import SSE, lightning_config, send_sse_message
|
||||
from decouple import config
|
||||
|
||||
if lightning_config.ln_node == "lnd":
|
||||
from app.repositories.ln_impl.lnd import (
|
||||
add_invoice_impl,
|
||||
decode_pay_request_impl,
|
||||
get_implementation_name,
|
||||
get_ln_info_impl,
|
||||
get_wallet_balance_impl,
|
||||
|
|
@ -16,6 +23,7 @@ if lightning_config.ln_node == "lnd":
|
|||
else:
|
||||
from app.repositories.ln_impl.clightning import (
|
||||
add_invoice_impl,
|
||||
decode_pay_request_impl,
|
||||
get_implementation_name,
|
||||
get_ln_info_impl,
|
||||
get_wallet_balance_impl,
|
||||
|
|
@ -44,6 +52,10 @@ async def add_invoice(
|
|||
return await add_invoice_impl(memo, value_msat, expiry, is_keysend)
|
||||
|
||||
|
||||
async def decode_pay_request(pay_req: str) -> PaymentRequest:
|
||||
return await decode_pay_request_impl(pay_req)
|
||||
|
||||
|
||||
async def send_payment(
|
||||
pay_req: str, timeout_seconds: int, fee_limit_msat: int
|
||||
) -> Payment:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from app.models.lightning import Invoice, LnInfo, Payment
|
||||
from app.models.lightning import Invoice, LnInfo, Payment, PaymentRequest
|
||||
|
||||
|
||||
def get_implementation_name() -> str:
|
||||
|
|
@ -15,6 +15,10 @@ async def add_invoice_impl(
|
|||
raise NotImplementedError("c-lightning not yet implemented")
|
||||
|
||||
|
||||
async def decode_pay_request_impl(pay_req: str) -> PaymentRequest:
|
||||
raise NotImplementedError("c-lightning not yet implemented")
|
||||
|
||||
|
||||
async def send_payment_impl(
|
||||
pay_req: str, timeout_seconds: int, fee_limit_msat: int
|
||||
) -> Payment:
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from app.models.lightning import (
|
|||
InvoiceState,
|
||||
LnInfo,
|
||||
Payment,
|
||||
PaymentRequest,
|
||||
WalletBalance,
|
||||
invoice_from_grpc,
|
||||
ln_info_from_grpc,
|
||||
|
|
@ -62,6 +63,25 @@ async def add_invoice_impl(
|
|||
return invoice
|
||||
|
||||
|
||||
async def decode_pay_request_impl(pay_req: str) -> PaymentRequest:
|
||||
try:
|
||||
req = ln.PayReqString(pay_req=pay_req)
|
||||
res = await lncfg.lnd_stub.DecodePayReq(req)
|
||||
return PaymentRequest.from_grpc(res)
|
||||
except grpc.aio._call.AioRpcError as error:
|
||||
if (
|
||||
error.details() != None
|
||||
and error.details().find("checksum failed.") > -1
|
||||
):
|
||||
raise HTTPException(
|
||||
status.HTTP_400_BAD_REQUEST, detail="Invalid payment request string"
|
||||
)
|
||||
else:
|
||||
raise HTTPException(
|
||||
status.HTTP_500_INTERNAL_SERVER_ERROR, detail=error.details()
|
||||
)
|
||||
|
||||
|
||||
async def send_payment_impl(
|
||||
pay_req: str, timeout_seconds: int, fee_limit_msat: int
|
||||
) -> Payment:
|
||||
|
|
|
|||
|
|
@ -4,17 +4,19 @@ from app.models.lightning import (
|
|||
LightningStatus,
|
||||
LnInfo,
|
||||
Payment,
|
||||
PaymentRequest,
|
||||
WalletBalance,
|
||||
)
|
||||
from app.repositories.lightning import (
|
||||
add_invoice,
|
||||
decode_pay_request,
|
||||
get_ln_info,
|
||||
get_ln_status,
|
||||
get_wallet_balance,
|
||||
send_payment,
|
||||
)
|
||||
from app.routers.lightning_docs import send_payment_desc
|
||||
from fastapi import APIRouter, HTTPException, status
|
||||
from fastapi import APIRouter, HTTPException, Query, status
|
||||
from fastapi.params import Depends
|
||||
|
||||
router = APIRouter(prefix="/lightning", tags=["Lightning"])
|
||||
|
|
@ -107,3 +109,17 @@ async def get_info():
|
|||
raise HTTPException(r.status_code, detail=r.detail)
|
||||
except NotImplementedError as r:
|
||||
raise HTTPException(status.HTTP_501_NOT_IMPLEMENTED, detail=r.args[0])
|
||||
|
||||
|
||||
@router.get(
|
||||
"/decode-pay-req",
|
||||
name="lightning.decode-pay-req",
|
||||
summary="DecodePayReq takes an encoded payment request string and attempts to decode it, returning a full description of the conditions encoded within the payment request.",
|
||||
response_model=PaymentRequest,
|
||||
response_description="A fully decoded payment request or a HTTP status 400 if the payment request cannot be decoded.",
|
||||
dependencies=[Depends(JWTBearer())],
|
||||
)
|
||||
async def get_decode_pay_request(
|
||||
pay_req: str = Query(..., description="The payment request string to be decoded")
|
||||
):
|
||||
return await decode_pay_request(pay_req)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue