Nutshell cleanup wishlist (#332)

* fix keys

* fix tests

* backwards compatible api upgrade

* upgrade seems to work

* fix tests

* add deprecated api functions

* add more tests of backwards compat

* add test serialization for nut00

* remove a redundant test

* move mint and melt to new api

* mypy works

* CI: mypy --check-untyped-defs

* add deprecated router

* add hints and remove logs

* fix tests

* cleanup

* use new mint and melt endpoints

* tests passing?

* fix mypy

* make format

* make format

* make format

* commit

* errors gone

* save

* adjust the API

* store quotes in db

* make mypy happy

* add fakewallet settings

* remove LIGHTNING=True and pass quote id for melt

* format

* tests passing

* add CoreLightningRestWallet

* add macaroon loader

* add correct config

* preimage -> proof

* move wallet.status() to cli.helpers.print_status()

* remove statuses from tests

* remove

* make format

* Use httpx in deprecated wallet

* fix cln interface

* create invoice before quote

* internal transactions and deprecated api testing

* fix tests

* add deprecated API tests

* fastapi type hints break things

* fix duplicate wallet error

* make format

* update poetry in CI to 1.7.1

* precommit restore

* remove bolt11

* oops

* default poetry

* store fee reserve for melt quotes and refactor melt()

* works?

* make format

* test

* finally

* fix deprecated models

* rename v1 endpoints to bolt11

* raise restore and check to v1, bump version to 0.15.0

* add version byte to keyset id

* remove redundant fields in json

* checks

* generate bip32 keyset wip

* migrate old keysets

* load duplicate keys

* duplicate old keysets

* revert router changes

* add deprecated /check and /restore endpoints

* try except invalidate

* parse unit from derivation path, adjust keyset id calculation with bytes

* remove keyest id from functions again and rely on self.keyset_id

* mosts tests work

* mint loads multiple derivation paths

* make format

* properly print units

* fix tests

* wallet works with multiple units

* add strike wallet and choose backend dynamically

* fix mypy

* add get_payment_quote to lightning backends

* make format

* fix startup

* fix lnbitswallet

* fix tests

* LightningWallet -> LightningBackend

* remove comments

* make format

* remove msat conversion

* add Amount type

* fix regtest

* use melt_quote as argument for pay_invoice

* test old api

* fees in sats

* fix deprecated fees

* fixes

* print balance correctly

* internally index keyset response by int

* add pydantic validation to input models

* add timestamps to mint db

* store timestamps for invoices, promises, proofs_used

* fix wallet migration

* rotate keys correctly for testing

* remove print

* update latest keyset

* fix tests

* fix test

* make format

* make format with correct black version

* remove nsat and cheese

* test against deprecated mint

* fix tests?

* actually use env var

* mint run with env vars

* moar test

* cleanup

* simplify tests, load all keys

* try out testing with internal invoices

* fix internal melt test

* fix test

* deprecated checkfees expects appropriate fees

* adjust comment

* drop lightning table

* split migration for testing for now, remove it later

* remove unused lightning table

* skip_private_key -> skip_db_read

* throw error on migration error

* reorder

* fix migrations

* fix lnbits fee return value negative

* fix typo

* comments

* add type

* make format

* split must use correct amount

* fix tests

* test deprecated api with internal/external melts

* do not split if not necessary

* refactor

* fix test

* make format with new black

* cleanup and add comments

* add quote state check endpoints

* fix deprecated wallet response

* split -> swap endpoint

* make format

* add expiry to quotes, get quote endpoints, and adjust to nut review comments

* allow overpayment of melt

* add lightning wallet tests

* commiting to save

* fix tests a bit

* make format

* remove comments

* get mint info

* check_spendable default False, and return payment quote checking id

* make format

* bump version in pyproject

* update to /v1/checkstate

* make format

* fix mint api checks

* return witness on /v1/checkstate

* no failfast

* try fail-fast: false in ci.yaml

* fix db lookup

* clean up literals
This commit is contained in:
callebtc
2024-01-08 00:57:15 +01:00
committed by GitHub
parent 375b27833a
commit a518274f7e
64 changed files with 5362 additions and 2046 deletions

View File

@@ -4,23 +4,30 @@ import random
from typing import AsyncGenerator, Dict, Optional
import httpx
from bolt11 import Bolt11Exception
from bolt11.decode import decode
from bolt11 import (
Bolt11Exception,
decode,
)
from loguru import logger
from ..core.base import Amount, MeltQuote, Unit
from ..core.helpers import fee_reserve
from ..core.settings import settings
from .base import (
InvoiceResponse,
LightningBackend,
PaymentQuoteResponse,
PaymentResponse,
PaymentStatus,
StatusResponse,
Unsupported,
Wallet,
)
from .macaroon import load_macaroon
class CoreLightningRestWallet(Wallet):
class CoreLightningRestWallet(LightningBackend):
units = set([Unit.sat, Unit.msat])
def __init__(self):
macaroon = settings.mint_corelightning_rest_macaroon
assert macaroon, "missing cln-rest macaroon"
@@ -72,26 +79,27 @@ class CoreLightningRestWallet(Wallet):
error_message=(
f"Failed to connect to {self.url}, got: '{error_message}...'"
),
balance_msat=0,
balance=0,
)
data = r.json()
if len(data) == 0:
return StatusResponse(error_message="no data", balance_msat=0)
return StatusResponse(error_message="no data", balance=0)
balance_msat = int(data.get("localBalance") * 1000)
return StatusResponse(error_message=None, balance_msat=balance_msat)
return StatusResponse(error_message=None, balance=balance_msat)
async def create_invoice(
self,
amount: int,
amount: Amount,
memo: Optional[str] = None,
description_hash: Optional[bytes] = None,
unhashed_description: Optional[bytes] = None,
**kwargs,
) -> InvoiceResponse:
self.assert_unit_supported(amount.unit)
label = f"lbl{random.random()}"
data: Dict = {
"amount": amount * 1000,
"amount": amount.to(Unit.msat, round="up").amount,
"description": memo,
"label": label,
}
@@ -139,14 +147,16 @@ class CoreLightningRestWallet(Wallet):
error_message=None,
)
async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse:
async def pay_invoice(
self, quote: MeltQuote, fee_limit_msat: int
) -> PaymentResponse:
try:
invoice = decode(bolt11)
invoice = decode(quote.request)
except Bolt11Exception as exc:
return PaymentResponse(
ok=False,
checking_id=None,
fee_msat=None,
fee=None,
preimage=None,
error_message=str(exc),
)
@@ -156,7 +166,7 @@ class CoreLightningRestWallet(Wallet):
return PaymentResponse(
ok=False,
checking_id=None,
fee_msat=None,
fee=None,
preimage=None,
error_message=error_message,
)
@@ -164,7 +174,7 @@ class CoreLightningRestWallet(Wallet):
r = await self.client.post(
f"{self.url}/v1/pay",
data={
"invoice": bolt11,
"invoice": quote.request,
"maxfeepercent": f"{fee_limit_percent:.11}",
"exemptfee": 0, # so fee_limit_percent is applied even on payments
# with fee < 5000 millisatoshi (which is default value of exemptfee)
@@ -181,7 +191,7 @@ class CoreLightningRestWallet(Wallet):
return PaymentResponse(
ok=False,
checking_id=None,
fee_msat=None,
fee=None,
preimage=None,
error_message=error_message,
)
@@ -192,7 +202,7 @@ class CoreLightningRestWallet(Wallet):
return PaymentResponse(
ok=False,
checking_id=None,
fee_msat=None,
fee=None,
preimage=None,
error_message="payment failed",
)
@@ -204,7 +214,7 @@ class CoreLightningRestWallet(Wallet):
return PaymentResponse(
ok=self.statuses.get(data["status"]),
checking_id=checking_id,
fee_msat=fee_msat,
fee=Amount(unit=Unit.msat, amount=fee_msat) if fee_msat else None,
preimage=preimage,
error_message=None,
)
@@ -249,7 +259,7 @@ class CoreLightningRestWallet(Wallet):
return PaymentStatus(
paid=self.statuses.get(pay["status"]),
fee_msat=fee_msat,
fee=Amount(unit=Unit.msat, amount=fee_msat) if fee_msat else None,
preimage=preimage,
)
except Exception as e:
@@ -274,7 +284,6 @@ class CoreLightningRestWallet(Wallet):
except Exception:
continue
logger.trace(f"paid invoice: {inv}")
yield inv["label"]
# NOTE: use payment_hash when corelightning-rest returns it
# when using waitAnyInvoice
# payment_hash = inv["payment_hash"]
@@ -299,3 +308,14 @@ class CoreLightningRestWallet(Wallet):
"reconnecting..."
)
await asyncio.sleep(0.02)
async def get_payment_quote(self, bolt11: str) -> PaymentQuoteResponse:
invoice_obj = decode(bolt11)
assert invoice_obj.amount_msat, "invoice has no amount."
amount_msat = int(invoice_obj.amount_msat)
fees_msat = fee_reserve(amount_msat)
fees = Amount(unit=Unit.msat, amount=fees_msat)
amount = Amount(unit=Unit.msat, amount=amount_msat)
return PaymentQuoteResponse(
checking_id=invoice_obj.payment_hash, fee=fees, amount=amount
)