mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-03-15 12:20:21 +01:00
add zbd to settings
update api methods add zbd as funding source to settings and js fix statuses cast str into int for status method fix outbound payment hash issue restore create_invoice remove print stmts
This commit is contained in:
parent
d69946db8a
commit
d20a35eddc
4 changed files with 76 additions and 31 deletions
|
@ -210,6 +210,7 @@ class ZBDFundingSource(LNbitsSettings):
|
|||
zbd_api_endpoint: Optional[str] = Field(default="https://api.zebedee.io/v0/")
|
||||
zbd_api_key: Optional[str] = Field(default=None)
|
||||
|
||||
|
||||
class AlbyFundingSource(LNbitsSettings):
|
||||
alby_api_endpoint: Optional[str] = Field(default="https://api.getalby.com/")
|
||||
alby_access_token: Optional[str] = Field(default=None)
|
||||
|
@ -249,6 +250,7 @@ class FundingSourcesSettings(
|
|||
LndGrpcFundingSource,
|
||||
LnPayFundingSource,
|
||||
AlbyFundingSource,
|
||||
ZBDFundingSource,
|
||||
OpenNodeFundingSource,
|
||||
SparkFundingSource,
|
||||
LnTipsFundingSource,
|
||||
|
@ -403,6 +405,7 @@ class SuperUserSettings(LNbitsSettings):
|
|||
"LnTipsWallet",
|
||||
"LNPayWallet",
|
||||
"AlbyWallet",
|
||||
"ZBDWallet",
|
||||
"LNbitsWallet",
|
||||
"OpenNodeWallet",
|
||||
]
|
||||
|
|
|
@ -110,7 +110,7 @@ Vue.component('lnbits-funding-sources', {
|
|||
'ZBD',
|
||||
{
|
||||
zbd_api_endpoint: 'Endpoint',
|
||||
zbd_access_token: 'Key'
|
||||
zbd_api_key: 'Key'
|
||||
}
|
||||
],
|
||||
[
|
||||
|
|
|
@ -8,7 +8,6 @@ from lnbits.settings import settings
|
|||
from lnbits.wallets.base import Wallet
|
||||
|
||||
from .alby import AlbyWallet
|
||||
from .zbd import ZBDWallet
|
||||
from .cliche import ClicheWallet
|
||||
from .corelightning import CoreLightningWallet
|
||||
|
||||
|
@ -26,6 +25,7 @@ from .lntips import LnTipsWallet
|
|||
from .opennode import OpenNodeWallet
|
||||
from .spark import SparkWallet
|
||||
from .void import VoidWallet
|
||||
from .zbd import ZBDWallet
|
||||
|
||||
|
||||
def set_wallet_class(class_name: Optional[str] = None):
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import asyncio
|
||||
import hashlib
|
||||
from typing import AsyncGenerator, Dict, Optional
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
|
||||
from lnbits.settings import settings
|
||||
from lnbits.wallets.base import PaymentStatus
|
||||
|
||||
from .base import (
|
||||
InvoiceResponse,
|
||||
PaymentResponse,
|
||||
PaymentStatus,
|
||||
StatusResponse,
|
||||
Unsupported,
|
||||
Wallet,
|
||||
)
|
||||
|
||||
|
@ -27,7 +28,7 @@ class ZBDWallet(Wallet):
|
|||
|
||||
self.endpoint = self.normalize_endpoint(settings.zbd_api_endpoint)
|
||||
self.auth = {
|
||||
"Authorization": "Bearer " + settings.zbd_api_key,
|
||||
"apikey": settings.zbd_api_key,
|
||||
"User-Agent": settings.user_agent,
|
||||
}
|
||||
self.client = httpx.AsyncClient(base_url=self.endpoint, headers=self.auth)
|
||||
|
@ -40,16 +41,18 @@ class ZBDWallet(Wallet):
|
|||
|
||||
async def status(self) -> StatusResponse:
|
||||
try:
|
||||
r = await self.client.get("/balance", timeout=10)
|
||||
r = await self.client.get("wallet", timeout=10)
|
||||
except (httpx.ConnectError, httpx.RequestError):
|
||||
return StatusResponse(f"Unable to connect to '{self.endpoint}'", 0)
|
||||
|
||||
if r.is_error:
|
||||
error_message = r.json()["message"]
|
||||
return StatusResponse(error_message, 0)
|
||||
data = r.json()["balance"]
|
||||
# if no error, multiply balance by 1000 for msats representation in lnbits
|
||||
return StatusResponse(None, data * 1000)
|
||||
|
||||
data = int(r.json()["data"]["balance"])
|
||||
# ZBD returns everything as a str not int
|
||||
# balance is returned in msats already in ZBD
|
||||
return StatusResponse(None, data)
|
||||
|
||||
async def create_invoice(
|
||||
self,
|
||||
|
@ -60,16 +63,20 @@ class ZBDWallet(Wallet):
|
|||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
# https://api.zebedee.io/v0/charges
|
||||
data: Dict = {"amount": f"{amount}"}
|
||||
if description_hash:
|
||||
data["description_hash"] = description_hash.hex()
|
||||
elif unhashed_description:
|
||||
data["description_hash"] = hashlib.sha256(unhashed_description).hexdigest()
|
||||
else:
|
||||
data["memo"] = memo or ""
|
||||
if description_hash or unhashed_description:
|
||||
raise Unsupported("description_hash")
|
||||
|
||||
msats_amount = amount * 1000
|
||||
data: Dict = {
|
||||
"amount": f"{msats_amount}",
|
||||
"description": memo,
|
||||
"expiresIn": 3600,
|
||||
"callbackUrl": "",
|
||||
"internalId": "",
|
||||
}
|
||||
|
||||
r = await self.client.post(
|
||||
"/invoices",
|
||||
"charges",
|
||||
json=data,
|
||||
timeout=40,
|
||||
)
|
||||
|
@ -78,16 +85,22 @@ class ZBDWallet(Wallet):
|
|||
error_message = r.json()["message"]
|
||||
return InvoiceResponse(False, None, None, error_message)
|
||||
|
||||
data = r.json()
|
||||
checking_id = data["payment_hash"]
|
||||
payment_request = data["payment_request"]
|
||||
data = r.json()["data"]
|
||||
checking_id = data["id"] # this is a zbd id
|
||||
payment_request = data["invoice"]["request"]
|
||||
return InvoiceResponse(True, checking_id, payment_request, None)
|
||||
|
||||
async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse:
|
||||
# https://api.zebedee.io/v0/payments
|
||||
r = await self.client.post(
|
||||
"/payments/bolt11",
|
||||
json={"invoice": bolt11}, # assume never need amount in body
|
||||
"payments",
|
||||
json={
|
||||
"invoice": bolt11,
|
||||
"description": "",
|
||||
"amount": "",
|
||||
"internalId": "",
|
||||
"callbackUrl": "",
|
||||
},
|
||||
timeout=None,
|
||||
)
|
||||
|
||||
|
@ -96,28 +109,57 @@ class ZBDWallet(Wallet):
|
|||
return PaymentResponse(False, None, None, None, error_message)
|
||||
|
||||
data = r.json()
|
||||
checking_id = data["payment_hash"]
|
||||
fee_msat = -data["fee"]
|
||||
preimage = data["payment_preimage"]
|
||||
|
||||
# get the payment hash from the zbd api
|
||||
decoded_request = await self.client.post(
|
||||
"decode-invoice",
|
||||
json={"invoice": bolt11},
|
||||
timeout=40,
|
||||
)
|
||||
if decoded_request.is_error:
|
||||
error_message = decoded_request.json()["message"]
|
||||
return InvoiceResponse(False, None, None, error_message)
|
||||
|
||||
decoded_data = decoded_request.json()
|
||||
|
||||
checking_id = decoded_data["data"]["paymentHash"]
|
||||
fee_msat = -int(data["data"]["fee"])
|
||||
preimage = data["data"]["preimage"]
|
||||
|
||||
return PaymentResponse(True, checking_id, fee_msat, preimage, None)
|
||||
|
||||
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||
return await self.get_payment_status(checking_id)
|
||||
r = await self.client.get(f"charges/{checking_id}")
|
||||
if r.is_error:
|
||||
return PaymentStatus(None)
|
||||
data = r.json()["data"]
|
||||
|
||||
statuses = {
|
||||
"pending": None,
|
||||
"paid": True,
|
||||
"unpaid": None,
|
||||
"expired": False,
|
||||
"completed": True,
|
||||
}
|
||||
return PaymentStatus(statuses[data.get("status")])
|
||||
|
||||
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||
r = await self.client.get(f"/invoices/{checking_id}")
|
||||
|
||||
r = await self.client.get(f"payments/{checking_id}")
|
||||
if r.is_error:
|
||||
return PaymentStatus(None)
|
||||
|
||||
data = r.json()
|
||||
data = r.json()["data"]
|
||||
|
||||
statuses = {
|
||||
"CREATED": None,
|
||||
"SETTLED": True,
|
||||
"initial": None,
|
||||
"pending": None,
|
||||
"completed": True,
|
||||
"error": None,
|
||||
"expired": False,
|
||||
"failed": False,
|
||||
}
|
||||
return PaymentStatus(statuses[data.get("state")], fee_msat=None, preimage=None)
|
||||
|
||||
return PaymentStatus(statuses[data.get("status")], fee_msat=None, preimage=None)
|
||||
|
||||
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
|
||||
self.queue: asyncio.Queue = asyncio.Queue(0)
|
||||
|
|
Loading…
Add table
Reference in a new issue