text: import json
  import trio  # type: ignore
  import httpx
  from os import getenv
  from http import HTTPStatus
  from typing import Optional, Dict, AsyncGenerator
  from quart import request
  
  from .base import StatusResponse, InvoiceResponse, PaymentResponse, PaymentStatus, Wallet
  
  
  class LNPayWallet(Wallet):
      """https://docs.lnpay.co/"""
  
      def __init__(self):
          endpoint = getenv("LNPAY_API_ENDPOINT", "https://lnpay.co/v1")
          self.endpoint = endpoint[:-1] if endpoint.endswith("/") else endpoint
          self.wallet_key = getenv("LNPAY_WALLET_KEY") or getenv("LNPAY_ADMIN_KEY")
          self.auth = {"X-Api-Key": getenv("LNPAY_API_KEY")}
  
      def status(self) -> StatusResponse:
          url = f"{self.endpoint}/wallet/{self.wallet_key}"
          try:
              r = httpx.get(url, headers=self.auth, timeout=60)
          except (httpx.ConnectError, httpx.RequestError):
              return StatusResponse(f"Unable to connect to '{url}'", 0)
  
          if r.is_error:
              return StatusResponse(r.text[:250], 0)
  
          data = r.json()
          if data["statusType"]["name"] != "active":
              return StatusResponse(
                  f"Wallet {data['user_label']} (data['id']) not active, but {data['statusType']['name']}", 0
              )
  
          return StatusResponse(None, data["balance"] * 1000)
  
      def create_invoice(
          self,
          amount: int,
          memo: Optional[str] = None,
          description_hash: Optional[bytes] = None,
      ) -> InvoiceResponse:
          data: Dict = {"num_satoshis": f"{amount}"}
          if description_hash:
              data["description_hash"] = description_hash.hex()
          else:
              data["memo"] = memo or ""
  
          r = httpx.post(
              f"{self.endpoint}/wallet/{self.wallet_key}/invoice",
              headers=self.auth,
              json=data,
              timeout=60,
          )
          ok, checking_id, payment_request, error_message = (
              r.status_code == 201,
              None,
              None,
              r.text,
          )
  
          if ok:
              data = r.json()
              checking_id, payment_request = data["id"], data["payment_request"]
  
          return InvoiceResponse(ok, checking_id, payment_request, error_message)
  
      def pay_invoice(self, bolt11: str) -> PaymentResponse:
          r = httpx.post(
              f"{self.endpoint}/wallet/{self.wallet_key}/withdraw",
              headers=self.auth,
              json={"payment_request": bolt11},
              timeout=180,
          )
  
          try:
              data = r.json()
          except:
              return PaymentResponse(False, None, 0, None, f"Got invalid JSON: {r.text[:200]}")
  
          if r.is_error:
              return PaymentResponse(False, None, 0, None, data["message"])
  
          checking_id = data["lnTx"]["id"]
          fee_msat = 0
          preimage = data["lnTx"]["payment_preimage"]
          return PaymentResponse(True, checking_id, fee_msat, preimage, None)
  
      def get_invoice_status(self, checking_id: str) -> PaymentStatus:
          return self.get_payment_status(checking_id)
  
      def get_payment_status(self, checking_id: str) -> PaymentStatus:
          r = httpx.get(
              url=f"{self.endpoint}/lntx/{checking_id}?fields=settled",
              headers=self.auth,
          )
  
          if r.is_error:
              return PaymentStatus(None)
  
          statuses = {0: None, 1: True, -1: False}
          return PaymentStatus(statuses[r.json()["settled"]])
  
      async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
          self.send, receive = trio.open_memory_channel(0)
          async for value in receive:
              yield value
  
      async def webhook_listener(self):
          text: str = await request.get_data()
          try:
              data = json.loads(text)
          except json.decoder.JSONDecodeError:
              print(f"got something wrong on lnpay webhook endpoint: {text[:200]}")
              data = None
          if type(data) is not dict or "event" not in data or data["event"].get("name") != "wallet_receive":
              return "", HTTPStatus.NO_CONTENT
  
          lntx_id = data["data"]["wtx"]["lnTx"]["id"]
          async with httpx.AsyncClient() as client:
              r = await client.get(
                  f"{self.endpoint}/lntx/{lntx_id}?fields=settled",
                  headers=self.auth,
              )
              data = r.json()
              if data["settled"]:
                  await self.send.send(lntx_id)
  
          return "", HTTPStatus.NO_CONTENT
  