make all methods from all wallets async.
This commit is contained in:
parent
42bd5ea989
commit
d4d069fc77
15 changed files with 219 additions and 187 deletions
|
|
@ -55,7 +55,7 @@ def create_app(config_object="lnbits.settings") -> QuartTrio:
|
||||||
def check_funding_source(app: QuartTrio) -> None:
|
def check_funding_source(app: QuartTrio) -> None:
|
||||||
@app.before_serving
|
@app.before_serving
|
||||||
async def check_wallet_status():
|
async def check_wallet_status():
|
||||||
error_message, balance = WALLET.status()
|
error_message, balance = await WALLET.status()
|
||||||
if error_message:
|
if error_message:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
f" × The backend for {WALLET.__class__.__name__} isn't working properly: '{error_message}'",
|
f" × The backend for {WALLET.__class__.__name__} isn't working properly: '{error_message}'",
|
||||||
|
|
|
||||||
|
|
@ -141,9 +141,9 @@ class Payment(NamedTuple):
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.is_out:
|
if self.is_out:
|
||||||
pending = WALLET.get_payment_status(self.checking_id)
|
pending = await WALLET.get_payment_status(self.checking_id)
|
||||||
else:
|
else:
|
||||||
pending = WALLET.get_invoice_status(self.checking_id)
|
pending = await WALLET.get_invoice_status(self.checking_id)
|
||||||
|
|
||||||
await self.set_pending(pending.pending)
|
await self.set_pending(pending.pending)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ async def create_invoice(
|
||||||
invoice_memo = None if description_hash else memo
|
invoice_memo = None if description_hash else memo
|
||||||
storeable_memo = memo
|
storeable_memo = memo
|
||||||
|
|
||||||
ok, checking_id, payment_request, error_message = WALLET.create_invoice(
|
ok, checking_id, payment_request, error_message = await WALLET.create_invoice(
|
||||||
amount=amount, memo=invoice_memo, description_hash=description_hash
|
amount=amount, memo=invoice_memo, description_hash=description_hash
|
||||||
)
|
)
|
||||||
if not ok:
|
if not ok:
|
||||||
|
|
@ -139,7 +139,7 @@ async def pay_invoice(
|
||||||
await internal_invoice_paid.send(internal_checking_id)
|
await internal_invoice_paid.send(internal_checking_id)
|
||||||
else:
|
else:
|
||||||
# actually pay the external invoice
|
# actually pay the external invoice
|
||||||
payment: PaymentResponse = WALLET.pay_invoice(payment_request)
|
payment: PaymentResponse = await WALLET.pay_invoice(payment_request)
|
||||||
if payment.ok and payment.checking_id:
|
if payment.ok and payment.checking_id:
|
||||||
await create_payment(
|
await create_payment(
|
||||||
checking_id=payment.checking_id,
|
checking_id=payment.checking_id,
|
||||||
|
|
@ -255,4 +255,4 @@ async def check_invoice_status(wallet_id: str, payment_hash: str) -> PaymentStat
|
||||||
if not payment:
|
if not payment:
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
|
|
||||||
return WALLET.get_invoice_status(payment.checking_id)
|
return await WALLET.get_invoice_status(payment.checking_id)
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,7 @@ def get_diagonalleys_orders(wallet_ids: Union[str, List[str]]) -> List[Orders]:
|
||||||
f"SELECT * FROM orders WHERE wallet IN ({q})", (*wallet_ids,)
|
f"SELECT * FROM orders WHERE wallet IN ({q})", (*wallet_ids,)
|
||||||
)
|
)
|
||||||
for r in rows:
|
for r in rows:
|
||||||
PAID = WALLET.get_invoice_status(r["invoiceid"]).paid
|
PAID = (await WALLET.get_invoice_status(r["invoiceid"])).paid
|
||||||
if PAID:
|
if PAID:
|
||||||
with open_ext_db("diagonalley") as db:
|
with open_ext_db("diagonalley") as db:
|
||||||
db.execute(
|
db.execute(
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ async def lndhub_gettxs():
|
||||||
exclude_uncheckable=True,
|
exclude_uncheckable=True,
|
||||||
):
|
):
|
||||||
await payment.set_pending(
|
await payment.set_pending(
|
||||||
WALLET.get_payment_status(payment.checking_id).pending
|
(await WALLET.get_payment_status(payment.checking_id)).pending
|
||||||
)
|
)
|
||||||
|
|
||||||
limit = int(request.args.get("limit", 200))
|
limit = int(request.args.get("limit", 200))
|
||||||
|
|
@ -174,7 +174,7 @@ async def lndhub_getuserinvoices():
|
||||||
exclude_uncheckable=True,
|
exclude_uncheckable=True,
|
||||||
):
|
):
|
||||||
await invoice.set_pending(
|
await invoice.set_pending(
|
||||||
WALLET.get_invoice_status(invoice.checking_id).pending
|
(await WALLET.get_invoice_status(invoice.checking_id)).pending
|
||||||
)
|
)
|
||||||
|
|
||||||
limit = int(request.args.get("limit", 200))
|
limit = int(request.args.get("limit", 200))
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import NamedTuple, Optional, AsyncGenerator
|
from typing import NamedTuple, Optional, AsyncGenerator, Coroutine
|
||||||
|
|
||||||
|
|
||||||
class StatusResponse(NamedTuple):
|
class StatusResponse(NamedTuple):
|
||||||
|
|
@ -15,7 +15,9 @@ class InvoiceResponse(NamedTuple):
|
||||||
|
|
||||||
|
|
||||||
class PaymentResponse(NamedTuple):
|
class PaymentResponse(NamedTuple):
|
||||||
ok: bool
|
ok: Optional[
|
||||||
|
bool
|
||||||
|
] = None # when ok is None it means we don't know if this succeeded
|
||||||
checking_id: Optional[str] = None # payment_hash, rcp_id
|
checking_id: Optional[str] = None # payment_hash, rcp_id
|
||||||
fee_msat: int = 0
|
fee_msat: int = 0
|
||||||
preimage: Optional[str] = None
|
preimage: Optional[str] = None
|
||||||
|
|
@ -32,7 +34,7 @@ class PaymentStatus(NamedTuple):
|
||||||
|
|
||||||
class Wallet(ABC):
|
class Wallet(ABC):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def status(self) -> StatusResponse:
|
def status(self) -> Coroutine[None, None, StatusResponse]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
|
@ -41,19 +43,23 @@ class Wallet(ABC):
|
||||||
amount: int,
|
amount: int,
|
||||||
memo: Optional[str] = None,
|
memo: Optional[str] = None,
|
||||||
description_hash: Optional[bytes] = None,
|
description_hash: Optional[bytes] = None,
|
||||||
) -> InvoiceResponse:
|
) -> Coroutine[None, None, InvoiceResponse]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
def pay_invoice(self, bolt11: str) -> Coroutine[None, None, PaymentResponse]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
def get_invoice_status(
|
||||||
|
self, checking_id: str
|
||||||
|
) -> Coroutine[None, None, PaymentStatus]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
def get_payment_status(
|
||||||
|
self, checking_id: str
|
||||||
|
) -> Coroutine[None, None, PaymentStatus]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ class CLightningWallet(Wallet):
|
||||||
self.last_pay_index = inv["pay_index"]
|
self.last_pay_index = inv["pay_index"]
|
||||||
break
|
break
|
||||||
|
|
||||||
def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
try:
|
try:
|
||||||
funds = self.ln.listfunds()
|
funds = self.ln.listfunds()
|
||||||
return StatusResponse(
|
return StatusResponse(
|
||||||
|
|
@ -60,7 +60,7 @@ class CLightningWallet(Wallet):
|
||||||
error_message = f"lightningd '{exc.method}' failed with '{exc.error}'."
|
error_message = f"lightningd '{exc.method}' failed with '{exc.error}'."
|
||||||
return StatusResponse(error_message, 0)
|
return StatusResponse(error_message, 0)
|
||||||
|
|
||||||
def create_invoice(
|
async def create_invoice(
|
||||||
self,
|
self,
|
||||||
amount: int,
|
amount: int,
|
||||||
memo: Optional[str] = None,
|
memo: Optional[str] = None,
|
||||||
|
|
@ -84,7 +84,7 @@ class CLightningWallet(Wallet):
|
||||||
error_message = f"lightningd '{exc.method}' failed with '{exc.error}'."
|
error_message = f"lightningd '{exc.method}' failed with '{exc.error}'."
|
||||||
return InvoiceResponse(False, label, None, error_message)
|
return InvoiceResponse(False, label, None, error_message)
|
||||||
|
|
||||||
def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
async def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
||||||
try:
|
try:
|
||||||
r = self.ln.pay(bolt11)
|
r = self.ln.pay(bolt11)
|
||||||
except RpcError as exc:
|
except RpcError as exc:
|
||||||
|
|
@ -94,7 +94,7 @@ class CLightningWallet(Wallet):
|
||||||
preimage = r["payment_preimage"]
|
preimage = r["payment_preimage"]
|
||||||
return PaymentResponse(True, r["payment_hash"], fee_msat, preimage, None)
|
return PaymentResponse(True, r["payment_hash"], fee_msat, preimage, None)
|
||||||
|
|
||||||
def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||||
r = self.ln.listinvoices(checking_id)
|
r = self.ln.listinvoices(checking_id)
|
||||||
if not r["invoices"]:
|
if not r["invoices"]:
|
||||||
return PaymentStatus(False)
|
return PaymentStatus(False)
|
||||||
|
|
@ -102,7 +102,7 @@ class CLightningWallet(Wallet):
|
||||||
return PaymentStatus(r["invoices"][0]["status"] == "paid")
|
return PaymentStatus(r["invoices"][0]["status"] == "paid")
|
||||||
raise KeyError("supplied an invalid checking_id")
|
raise KeyError("supplied an invalid checking_id")
|
||||||
|
|
||||||
def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||||
r = self.ln.call("listpays", {"payment_hash": checking_id})
|
r = self.ln.call("listpays", {"payment_hash": checking_id})
|
||||||
if not r["pays"]:
|
if not r["pays"]:
|
||||||
return PaymentStatus(False)
|
return PaymentStatus(False)
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,10 @@ class LNbitsWallet(Wallet):
|
||||||
)
|
)
|
||||||
self.key = {"X-Api-Key": key}
|
self.key = {"X-Api-Key": key}
|
||||||
|
|
||||||
def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
r = httpx.get(url=f"{self.endpoint}/api/v1/wallet", headers=self.key)
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.get(url=f"{self.endpoint}/api/v1/wallet", headers=self.key)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = r.json()
|
data = r.json()
|
||||||
except:
|
except:
|
||||||
|
|
@ -39,7 +41,7 @@ class LNbitsWallet(Wallet):
|
||||||
|
|
||||||
return StatusResponse(None, data["balance"])
|
return StatusResponse(None, data["balance"])
|
||||||
|
|
||||||
def create_invoice(
|
async def create_invoice(
|
||||||
self,
|
self,
|
||||||
amount: int,
|
amount: int,
|
||||||
memo: Optional[str] = None,
|
memo: Optional[str] = None,
|
||||||
|
|
@ -51,7 +53,8 @@ class LNbitsWallet(Wallet):
|
||||||
else:
|
else:
|
||||||
data["memo"] = memo or ""
|
data["memo"] = memo or ""
|
||||||
|
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.post(
|
||||||
url=f"{self.endpoint}/api/v1/payments",
|
url=f"{self.endpoint}/api/v1/payments",
|
||||||
headers=self.key,
|
headers=self.key,
|
||||||
json=data,
|
json=data,
|
||||||
|
|
@ -71,8 +74,9 @@ class LNbitsWallet(Wallet):
|
||||||
|
|
||||||
return InvoiceResponse(ok, checking_id, payment_request, error_message)
|
return InvoiceResponse(ok, checking_id, payment_request, error_message)
|
||||||
|
|
||||||
def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
async def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.post(
|
||||||
url=f"{self.endpoint}/api/v1/payments",
|
url=f"{self.endpoint}/api/v1/payments",
|
||||||
headers=self.key,
|
headers=self.key,
|
||||||
json={"out": True, "bolt11": bolt11},
|
json={"out": True, "bolt11": bolt11},
|
||||||
|
|
@ -87,8 +91,9 @@ class LNbitsWallet(Wallet):
|
||||||
|
|
||||||
return PaymentResponse(ok, checking_id, fee_msat, error_message)
|
return PaymentResponse(ok, checking_id, fee_msat, error_message)
|
||||||
|
|
||||||
def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||||
r = httpx.get(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.get(
|
||||||
url=f"{self.endpoint}/api/v1/payments/{checking_id}", headers=self.key
|
url=f"{self.endpoint}/api/v1/payments/{checking_id}", headers=self.key
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -97,8 +102,9 @@ class LNbitsWallet(Wallet):
|
||||||
|
|
||||||
return PaymentStatus(r.json()["paid"])
|
return PaymentStatus(r.json()["paid"])
|
||||||
|
|
||||||
def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||||
r = httpx.get(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.get(
|
||||||
url=f"{self.endpoint}/api/v1/payments/{checking_id}", headers=self.key
|
url=f"{self.endpoint}/api/v1/payments/{checking_id}", headers=self.key
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ class LndWallet(Wallet):
|
||||||
macaroon_filepath=self.macaroon_path,
|
macaroon_filepath=self.macaroon_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
try:
|
try:
|
||||||
resp = self.rpc._ln_stub.ChannelBalance(ln.ChannelBalanceRequest())
|
resp = self.rpc._ln_stub.ChannelBalance(ln.ChannelBalanceRequest())
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|
@ -120,7 +120,7 @@ class LndWallet(Wallet):
|
||||||
|
|
||||||
return StatusResponse(None, resp.balance * 1000)
|
return StatusResponse(None, resp.balance * 1000)
|
||||||
|
|
||||||
def create_invoice(
|
async def create_invoice(
|
||||||
self,
|
self,
|
||||||
amount: int,
|
amount: int,
|
||||||
memo: Optional[str] = None,
|
memo: Optional[str] = None,
|
||||||
|
|
@ -144,7 +144,7 @@ class LndWallet(Wallet):
|
||||||
payment_request = str(resp.payment_request)
|
payment_request = str(resp.payment_request)
|
||||||
return InvoiceResponse(True, checking_id, payment_request, None)
|
return InvoiceResponse(True, checking_id, payment_request, None)
|
||||||
|
|
||||||
def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
async def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
||||||
resp = self.rpc.send_payment(payment_request=bolt11)
|
resp = self.rpc.send_payment(payment_request=bolt11)
|
||||||
|
|
||||||
if resp.payment_error:
|
if resp.payment_error:
|
||||||
|
|
@ -156,7 +156,7 @@ class LndWallet(Wallet):
|
||||||
preimage = resp.payment_preimage.hex()
|
preimage = resp.payment_preimage.hex()
|
||||||
return PaymentResponse(True, checking_id, fee_msat, preimage, None)
|
return PaymentResponse(True, checking_id, fee_msat, preimage, None)
|
||||||
|
|
||||||
def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||||
try:
|
try:
|
||||||
r_hash = parse_checking_id(checking_id)
|
r_hash = parse_checking_id(checking_id)
|
||||||
if len(r_hash) != 32:
|
if len(r_hash) != 32:
|
||||||
|
|
@ -172,7 +172,7 @@ class LndWallet(Wallet):
|
||||||
|
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
|
|
||||||
def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||||
return PaymentStatus(True)
|
return PaymentStatus(True)
|
||||||
|
|
||||||
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
|
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,12 @@ class LndRestWallet(Wallet):
|
||||||
self.auth = {"Grpc-Metadata-macaroon": macaroon}
|
self.auth = {"Grpc-Metadata-macaroon": macaroon}
|
||||||
self.cert = getenv("LND_REST_CERT")
|
self.cert = getenv("LND_REST_CERT")
|
||||||
|
|
||||||
def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
try:
|
try:
|
||||||
r = httpx.get(
|
async with httpx.AsyncClient(verify=self.cert) as client:
|
||||||
|
r = await client.get(
|
||||||
f"{self.endpoint}/v1/balance/channels",
|
f"{self.endpoint}/v1/balance/channels",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
verify=self.cert,
|
|
||||||
)
|
)
|
||||||
except (httpx.ConnectError, httpx.RequestError):
|
except (httpx.ConnectError, httpx.RequestError):
|
||||||
return StatusResponse(f"Unable to connect to {self.endpoint}.", 0)
|
return StatusResponse(f"Unable to connect to {self.endpoint}.", 0)
|
||||||
|
|
@ -54,7 +54,7 @@ class LndRestWallet(Wallet):
|
||||||
|
|
||||||
return StatusResponse(None, int(data["balance"]) * 1000)
|
return StatusResponse(None, int(data["balance"]) * 1000)
|
||||||
|
|
||||||
def create_invoice(
|
async def create_invoice(
|
||||||
self,
|
self,
|
||||||
amount: int,
|
amount: int,
|
||||||
memo: Optional[str] = None,
|
memo: Optional[str] = None,
|
||||||
|
|
@ -71,10 +71,10 @@ class LndRestWallet(Wallet):
|
||||||
else:
|
else:
|
||||||
data["memo"] = memo or ""
|
data["memo"] = memo or ""
|
||||||
|
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient(verify=self.cert) as client:
|
||||||
|
r = await client.post(
|
||||||
url=f"{self.endpoint}/v1/invoices",
|
url=f"{self.endpoint}/v1/invoices",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
verify=self.cert,
|
|
||||||
json=data,
|
json=data,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -93,11 +93,11 @@ class LndRestWallet(Wallet):
|
||||||
|
|
||||||
return InvoiceResponse(True, checking_id, payment_request, None)
|
return InvoiceResponse(True, checking_id, payment_request, None)
|
||||||
|
|
||||||
def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
async def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient(verify=self.cert) as client:
|
||||||
|
r = await client.post(
|
||||||
url=f"{self.endpoint}/v1/channels/transactions",
|
url=f"{self.endpoint}/v1/channels/transactions",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
verify=self.cert,
|
|
||||||
json={"payment_request": bolt11},
|
json={"payment_request": bolt11},
|
||||||
timeout=180,
|
timeout=180,
|
||||||
)
|
)
|
||||||
|
|
@ -116,12 +116,13 @@ class LndRestWallet(Wallet):
|
||||||
preimage = base64.b64decode(data["payment_preimage"]).hex()
|
preimage = base64.b64decode(data["payment_preimage"]).hex()
|
||||||
return PaymentResponse(True, checking_id, 0, preimage, None)
|
return PaymentResponse(True, checking_id, 0, preimage, None)
|
||||||
|
|
||||||
def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||||
checking_id = checking_id.replace("_", "/")
|
checking_id = checking_id.replace("_", "/")
|
||||||
r = httpx.get(
|
|
||||||
|
async with httpx.AsyncClient(verify=self.cert) as client:
|
||||||
|
r = await client.get(
|
||||||
url=f"{self.endpoint}/v1/invoice/{checking_id}",
|
url=f"{self.endpoint}/v1/invoice/{checking_id}",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
verify=self.cert,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if r.is_error or not r.json().get("settled"):
|
if r.is_error or not r.json().get("settled"):
|
||||||
|
|
@ -131,11 +132,11 @@ class LndRestWallet(Wallet):
|
||||||
|
|
||||||
return PaymentStatus(True)
|
return PaymentStatus(True)
|
||||||
|
|
||||||
def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||||
r = httpx.get(
|
async with httpx.AsyncClient(verify=self.cert) as client:
|
||||||
|
r = await client.get(
|
||||||
url=f"{self.endpoint}/v1/payments",
|
url=f"{self.endpoint}/v1/payments",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
verify=self.cert,
|
|
||||||
params={"max_payments": "20", "reversed": True},
|
params={"max_payments": "20", "reversed": True},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,11 @@ class LNPayWallet(Wallet):
|
||||||
self.wallet_key = getenv("LNPAY_WALLET_KEY") or getenv("LNPAY_ADMIN_KEY")
|
self.wallet_key = getenv("LNPAY_WALLET_KEY") or getenv("LNPAY_ADMIN_KEY")
|
||||||
self.auth = {"X-Api-Key": getenv("LNPAY_API_KEY")}
|
self.auth = {"X-Api-Key": getenv("LNPAY_API_KEY")}
|
||||||
|
|
||||||
def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
url = f"{self.endpoint}/wallet/{self.wallet_key}"
|
url = f"{self.endpoint}/wallet/{self.wallet_key}"
|
||||||
try:
|
try:
|
||||||
r = httpx.get(url, headers=self.auth, timeout=60)
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.get(url, headers=self.auth, timeout=60)
|
||||||
except (httpx.ConnectError, httpx.RequestError):
|
except (httpx.ConnectError, httpx.RequestError):
|
||||||
return StatusResponse(f"Unable to connect to '{url}'", 0)
|
return StatusResponse(f"Unable to connect to '{url}'", 0)
|
||||||
|
|
||||||
|
|
@ -43,7 +44,7 @@ class LNPayWallet(Wallet):
|
||||||
|
|
||||||
return StatusResponse(None, data["balance"] * 1000)
|
return StatusResponse(None, data["balance"] * 1000)
|
||||||
|
|
||||||
def create_invoice(
|
async def create_invoice(
|
||||||
self,
|
self,
|
||||||
amount: int,
|
amount: int,
|
||||||
memo: Optional[str] = None,
|
memo: Optional[str] = None,
|
||||||
|
|
@ -55,7 +56,8 @@ class LNPayWallet(Wallet):
|
||||||
else:
|
else:
|
||||||
data["memo"] = memo or ""
|
data["memo"] = memo or ""
|
||||||
|
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.post(
|
||||||
f"{self.endpoint}/wallet/{self.wallet_key}/invoice",
|
f"{self.endpoint}/wallet/{self.wallet_key}/invoice",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
json=data,
|
json=data,
|
||||||
|
|
@ -74,8 +76,9 @@ class LNPayWallet(Wallet):
|
||||||
|
|
||||||
return InvoiceResponse(ok, checking_id, payment_request, error_message)
|
return InvoiceResponse(ok, checking_id, payment_request, error_message)
|
||||||
|
|
||||||
def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
async def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.post(
|
||||||
f"{self.endpoint}/wallet/{self.wallet_key}/withdraw",
|
f"{self.endpoint}/wallet/{self.wallet_key}/withdraw",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
json={"payment_request": bolt11},
|
json={"payment_request": bolt11},
|
||||||
|
|
@ -97,11 +100,12 @@ class LNPayWallet(Wallet):
|
||||||
preimage = data["lnTx"]["payment_preimage"]
|
preimage = data["lnTx"]["payment_preimage"]
|
||||||
return PaymentResponse(True, checking_id, fee_msat, preimage, None)
|
return PaymentResponse(True, checking_id, fee_msat, preimage, None)
|
||||||
|
|
||||||
def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||||
return self.get_payment_status(checking_id)
|
return await self.get_payment_status(checking_id)
|
||||||
|
|
||||||
def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||||
r = httpx.get(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.get(
|
||||||
url=f"{self.endpoint}/lntx/{checking_id}?fields=settled",
|
url=f"{self.endpoint}/lntx/{checking_id}?fields=settled",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,9 @@ class LntxbotWallet(Wallet):
|
||||||
)
|
)
|
||||||
self.auth = {"Authorization": f"Basic {key}"}
|
self.auth = {"Authorization": f"Basic {key}"}
|
||||||
|
|
||||||
def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
r = httpx.get(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.get(
|
||||||
f"{self.endpoint}/balance",
|
f"{self.endpoint}/balance",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
timeout=40,
|
timeout=40,
|
||||||
|
|
@ -45,7 +46,7 @@ class LntxbotWallet(Wallet):
|
||||||
|
|
||||||
return StatusResponse(None, data["BTC"]["AvailableBalance"] * 1000)
|
return StatusResponse(None, data["BTC"]["AvailableBalance"] * 1000)
|
||||||
|
|
||||||
def create_invoice(
|
async def create_invoice(
|
||||||
self,
|
self,
|
||||||
amount: int,
|
amount: int,
|
||||||
memo: Optional[str] = None,
|
memo: Optional[str] = None,
|
||||||
|
|
@ -57,7 +58,8 @@ class LntxbotWallet(Wallet):
|
||||||
else:
|
else:
|
||||||
data["memo"] = memo or ""
|
data["memo"] = memo or ""
|
||||||
|
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.post(
|
||||||
f"{self.endpoint}/addinvoice",
|
f"{self.endpoint}/addinvoice",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
json=data,
|
json=data,
|
||||||
|
|
@ -77,8 +79,9 @@ class LntxbotWallet(Wallet):
|
||||||
data = r.json()
|
data = r.json()
|
||||||
return InvoiceResponse(True, data["payment_hash"], data["pay_req"], None)
|
return InvoiceResponse(True, data["payment_hash"], data["pay_req"], None)
|
||||||
|
|
||||||
def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
async def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.post(
|
||||||
f"{self.endpoint}/payinvoice",
|
f"{self.endpoint}/payinvoice",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
json={"invoice": bolt11},
|
json={"invoice": bolt11},
|
||||||
|
|
@ -101,8 +104,9 @@ class LntxbotWallet(Wallet):
|
||||||
preimage = data["payment_preimage"]
|
preimage = data["payment_preimage"]
|
||||||
return PaymentResponse(True, checking_id, fee_msat, preimage, None)
|
return PaymentResponse(True, checking_id, fee_msat, preimage, None)
|
||||||
|
|
||||||
def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.post(
|
||||||
f"{self.endpoint}/invoicestatus/{checking_id}?wait=false",
|
f"{self.endpoint}/invoicestatus/{checking_id}?wait=false",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
)
|
)
|
||||||
|
|
@ -116,8 +120,9 @@ class LntxbotWallet(Wallet):
|
||||||
|
|
||||||
return PaymentStatus(True)
|
return PaymentStatus(True)
|
||||||
|
|
||||||
def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.post(
|
||||||
url=f"{self.endpoint}/paymentstatus/{checking_id}",
|
url=f"{self.endpoint}/paymentstatus/{checking_id}",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import json
|
|
||||||
import trio # type: ignore
|
import trio # type: ignore
|
||||||
import hmac
|
import hmac
|
||||||
import httpx
|
import httpx
|
||||||
|
|
@ -31,9 +30,10 @@ class OpenNodeWallet(Wallet):
|
||||||
)
|
)
|
||||||
self.auth = {"Authorization": key}
|
self.auth = {"Authorization": key}
|
||||||
|
|
||||||
def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
try:
|
try:
|
||||||
r = httpx.get(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.get(
|
||||||
f"{self.endpoint}/v1/account/balance",
|
f"{self.endpoint}/v1/account/balance",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
timeout=40,
|
timeout=40,
|
||||||
|
|
@ -47,7 +47,7 @@ class OpenNodeWallet(Wallet):
|
||||||
|
|
||||||
return StatusResponse(None, data["balance"]["BTC"] / 100_000_000_000)
|
return StatusResponse(None, data["balance"]["BTC"] / 100_000_000_000)
|
||||||
|
|
||||||
def create_invoice(
|
async def create_invoice(
|
||||||
self,
|
self,
|
||||||
amount: int,
|
amount: int,
|
||||||
memo: Optional[str] = None,
|
memo: Optional[str] = None,
|
||||||
|
|
@ -56,7 +56,8 @@ class OpenNodeWallet(Wallet):
|
||||||
if description_hash:
|
if description_hash:
|
||||||
raise Unsupported("description_hash")
|
raise Unsupported("description_hash")
|
||||||
|
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.post(
|
||||||
f"{self.endpoint}/v1/charges",
|
f"{self.endpoint}/v1/charges",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
json={
|
json={
|
||||||
|
|
@ -76,8 +77,9 @@ class OpenNodeWallet(Wallet):
|
||||||
payment_request = data["lightning_invoice"]["payreq"]
|
payment_request = data["lightning_invoice"]["payreq"]
|
||||||
return InvoiceResponse(True, checking_id, payment_request, None)
|
return InvoiceResponse(True, checking_id, payment_request, None)
|
||||||
|
|
||||||
def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
async def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.post(
|
||||||
f"{self.endpoint}/v2/withdrawals",
|
f"{self.endpoint}/v2/withdrawals",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
json={"type": "ln", "address": bolt11},
|
json={"type": "ln", "address": bolt11},
|
||||||
|
|
@ -93,16 +95,22 @@ class OpenNodeWallet(Wallet):
|
||||||
fee_msat = data["fee"] * 1000
|
fee_msat = data["fee"] * 1000
|
||||||
return PaymentResponse(True, checking_id, fee_msat, None, None)
|
return PaymentResponse(True, checking_id, fee_msat, None, None)
|
||||||
|
|
||||||
def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||||
r = httpx.get(f"{self.endpoint}/v1/charge/{checking_id}", headers=self.auth)
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.get(
|
||||||
|
f"{self.endpoint}/v1/charge/{checking_id}", headers=self.auth
|
||||||
|
)
|
||||||
if r.is_error:
|
if r.is_error:
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
|
|
||||||
statuses = {"processing": None, "paid": True, "unpaid": False}
|
statuses = {"processing": None, "paid": True, "unpaid": False}
|
||||||
return PaymentStatus(statuses[r.json()["data"]["status"]])
|
return PaymentStatus(statuses[r.json()["data"]["status"]])
|
||||||
|
|
||||||
def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||||
r = httpx.get(f"{self.endpoint}/v1/withdrawal/{checking_id}", headers=self.auth)
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.get(
|
||||||
|
f"{self.endpoint}/v1/withdrawal/{checking_id}", headers=self.auth
|
||||||
|
)
|
||||||
|
|
||||||
if r.is_error:
|
if r.is_error:
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class SparkWallet(Wallet):
|
||||||
self.token = getenv("SPARK_TOKEN")
|
self.token = getenv("SPARK_TOKEN")
|
||||||
|
|
||||||
def __getattr__(self, key):
|
def __getattr__(self, key):
|
||||||
def call(*args, **kwargs):
|
async def call(*args, **kwargs):
|
||||||
if args and kwargs:
|
if args and kwargs:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
f"must supply either named arguments or a list of arguments, not both: {args} {kwargs}"
|
f"must supply either named arguments or a list of arguments, not both: {args} {kwargs}"
|
||||||
|
|
@ -40,12 +40,14 @@ class SparkWallet(Wallet):
|
||||||
else:
|
else:
|
||||||
params = {}
|
params = {}
|
||||||
|
|
||||||
r = httpx.post(
|
async with httpx.AsyncClient() as client:
|
||||||
|
r = await client.post(
|
||||||
self.url + "/rpc",
|
self.url + "/rpc",
|
||||||
headers={"X-Access": self.token},
|
headers={"X-Access": self.token},
|
||||||
json={"method": key, "params": params},
|
json={"method": key, "params": params},
|
||||||
timeout=40,
|
timeout=40,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = r.json()
|
data = r.json()
|
||||||
except:
|
except:
|
||||||
|
|
@ -61,9 +63,9 @@ class SparkWallet(Wallet):
|
||||||
|
|
||||||
return call
|
return call
|
||||||
|
|
||||||
def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
try:
|
try:
|
||||||
funds = self.listfunds()
|
funds = await self.listfunds()
|
||||||
except (httpx.ConnectError, httpx.RequestError):
|
except (httpx.ConnectError, httpx.RequestError):
|
||||||
return StatusResponse("Couldn't connect to Spark server", 0)
|
return StatusResponse("Couldn't connect to Spark server", 0)
|
||||||
except (SparkError, UnknownError) as e:
|
except (SparkError, UnknownError) as e:
|
||||||
|
|
@ -74,7 +76,7 @@ class SparkWallet(Wallet):
|
||||||
sum([ch["channel_sat"] * 1000 for ch in funds["channels"]]),
|
sum([ch["channel_sat"] * 1000 for ch in funds["channels"]]),
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_invoice(
|
async def create_invoice(
|
||||||
self,
|
self,
|
||||||
amount: int,
|
amount: int,
|
||||||
memo: Optional[str] = None,
|
memo: Optional[str] = None,
|
||||||
|
|
@ -85,13 +87,13 @@ class SparkWallet(Wallet):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if description_hash:
|
if description_hash:
|
||||||
r = self.invoicewithdescriptionhash(
|
r = await self.invoicewithdescriptionhash(
|
||||||
msatoshi=amount * 1000,
|
msatoshi=amount * 1000,
|
||||||
label=label,
|
label=label,
|
||||||
description_hash=description_hash.hex(),
|
description_hash=description_hash.hex(),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
r = self.invoice(
|
r = await self.invoice(
|
||||||
msatoshi=amount * 1000,
|
msatoshi=amount * 1000,
|
||||||
label=label,
|
label=label,
|
||||||
description=memo or "",
|
description=memo or "",
|
||||||
|
|
@ -103,9 +105,9 @@ class SparkWallet(Wallet):
|
||||||
|
|
||||||
return InvoiceResponse(ok, checking_id, payment_request, error_message)
|
return InvoiceResponse(ok, checking_id, payment_request, error_message)
|
||||||
|
|
||||||
def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
async def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
||||||
try:
|
try:
|
||||||
r = self.pay(bolt11)
|
r = await self.pay(bolt11)
|
||||||
except (SparkError, UnknownError) as exc:
|
except (SparkError, UnknownError) as exc:
|
||||||
return PaymentResponse(False, None, 0, None, str(exc))
|
return PaymentResponse(False, None, 0, None, str(exc))
|
||||||
|
|
||||||
|
|
@ -113,15 +115,15 @@ class SparkWallet(Wallet):
|
||||||
preimage = r["payment_preimage"]
|
preimage = r["payment_preimage"]
|
||||||
return PaymentResponse(True, r["payment_hash"], fee_msat, preimage, None)
|
return PaymentResponse(True, r["payment_hash"], fee_msat, preimage, None)
|
||||||
|
|
||||||
def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||||
r = self.listinvoices(label=checking_id)
|
r = await self.listinvoices(label=checking_id)
|
||||||
if not r or not r.get("invoices"):
|
if not r or not r.get("invoices"):
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
if r["invoices"][0]["status"] == "unpaid":
|
if r["invoices"][0]["status"] == "unpaid":
|
||||||
return PaymentStatus(False)
|
return PaymentStatus(False)
|
||||||
return PaymentStatus(True)
|
return PaymentStatus(True)
|
||||||
|
|
||||||
def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||||
# check if it's 32 bytes hex
|
# check if it's 32 bytes hex
|
||||||
if len(checking_id) != 64:
|
if len(checking_id) != 64:
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
|
|
@ -131,7 +133,7 @@ class SparkWallet(Wallet):
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
|
|
||||||
# ask sparko
|
# ask sparko
|
||||||
r = self.listpays(payment_hash=checking_id)
|
r = await self.listpays(payment_hash=checking_id)
|
||||||
if not r["pays"]:
|
if not r["pays"]:
|
||||||
return PaymentStatus(False)
|
return PaymentStatus(False)
|
||||||
if r["pays"][0]["payment_hash"] == checking_id:
|
if r["pays"][0]["payment_hash"] == checking_id:
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ from .base import (
|
||||||
|
|
||||||
|
|
||||||
class VoidWallet(Wallet):
|
class VoidWallet(Wallet):
|
||||||
def create_invoice(
|
async def create_invoice(
|
||||||
self,
|
self,
|
||||||
amount: int,
|
amount: int,
|
||||||
memo: Optional[str] = None,
|
memo: Optional[str] = None,
|
||||||
|
|
@ -19,19 +19,19 @@ class VoidWallet(Wallet):
|
||||||
) -> InvoiceResponse:
|
) -> InvoiceResponse:
|
||||||
raise Unsupported("")
|
raise Unsupported("")
|
||||||
|
|
||||||
def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
return StatusResponse(
|
return StatusResponse(
|
||||||
"This backend does nothing, it is here just as a placeholder, you must configure an actual backend before being able to do anything useful with LNbits.",
|
"This backend does nothing, it is here just as a placeholder, you must configure an actual backend before being able to do anything useful with LNbits.",
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|
||||||
def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
async def pay_invoice(self, bolt11: str) -> PaymentResponse:
|
||||||
raise Unsupported("")
|
raise Unsupported("")
|
||||||
|
|
||||||
def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||||
raise Unsupported("")
|
raise Unsupported("")
|
||||||
|
|
||||||
def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||||
raise Unsupported("")
|
raise Unsupported("")
|
||||||
|
|
||||||
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
|
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue