Wallet: store quotes (#657)

* wallet_quotes_wip

* fix quote in db

* fix subscription test

* clean up api

* fix api tests

* fix balance check
This commit is contained in:
callebtc
2024-11-01 13:27:27 +01:00
committed by GitHub
parent 21418a114a
commit 92627399a5
31 changed files with 981 additions and 865 deletions

View File

@@ -1,6 +1,7 @@
import base64
import json
import math
import time
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from enum import Enum
@@ -260,20 +261,7 @@ class BlindedSignature(BaseModel):
)
# ------- LIGHTNING INVOICE -------
class Invoice(BaseModel):
amount: int
bolt11: str
id: str
out: Union[None, bool] = None
payment_hash: Union[None, str] = None
preimage: Union[str, None] = None
issued: Union[None, bool] = False
paid: Union[None, bool] = False
time_created: Union[None, str, int, float] = ""
time_paid: Union[None, str, int, float] = ""
# ------- Quotes -------
class MeltQuoteState(Enum):
@@ -297,9 +285,10 @@ class MeltQuote(LedgerEvent):
created_time: Union[int, None] = None
paid_time: Union[int, None] = None
fee_paid: int = 0
payment_preimage: str = ""
payment_preimage: Optional[str] = None
expiry: Optional[int] = None
change: Optional[List[BlindedSignature]] = None
mint: Optional[str] = None
@classmethod
def from_row(cls, row: Row):
@@ -314,6 +303,8 @@ class MeltQuote(LedgerEvent):
paid_time = int(row["paid_time"].timestamp()) if row["paid_time"] else None
expiry = int(row["expiry"].timestamp()) if row["expiry"] else None
payment_preimage = row.get("payment_preimage") or row.get("proof") # type: ignore
# parse change from row as json
change = None
if row["change"]:
@@ -327,13 +318,30 @@ class MeltQuote(LedgerEvent):
unit=row["unit"],
amount=row["amount"],
fee_reserve=row["fee_reserve"],
state=MeltQuoteState[row["state"]],
state=MeltQuoteState(row["state"]),
created_time=created_time,
paid_time=paid_time,
fee_paid=row["fee_paid"],
change=change,
expiry=expiry,
payment_preimage=row["proof"],
payment_preimage=payment_preimage,
)
@classmethod
def from_resp_wallet(
cls, melt_quote_resp, mint: str, amount: int, unit: str, request: str
):
return cls(
quote=melt_quote_resp.quote,
method="bolt11",
request=request,
checking_id="",
unit=unit,
amount=amount,
fee_reserve=melt_quote_resp.fee_reserve,
state=MeltQuoteState(melt_quote_resp.state),
mint=mint,
change=melt_quote_resp.change,
)
@property
@@ -397,6 +405,7 @@ class MintQuote(LedgerEvent):
created_time: Union[int, None] = None
paid_time: Union[int, None] = None
expiry: Optional[int] = None
mint: Optional[str] = None
@classmethod
def from_row(cls, row: Row):
@@ -417,11 +426,26 @@ class MintQuote(LedgerEvent):
checking_id=row["checking_id"],
unit=row["unit"],
amount=row["amount"],
state=MintQuoteState[row["state"]],
state=MintQuoteState(row["state"]),
created_time=created_time,
paid_time=paid_time,
)
@classmethod
def from_resp_wallet(cls, mint_quote_resp, mint: str, amount: int, unit: str):
return cls(
quote=mint_quote_resp.quote,
method="bolt11",
request=mint_quote_resp.request,
checking_id="",
unit=unit,
amount=amount,
state=MintQuoteState(mint_quote_resp.state),
mint=mint,
expiry=mint_quote_resp.expiry,
created_time=int(time.time()),
)
@property
def identifier(self) -> str:
"""Implementation of the abstract method from LedgerEventManager"""

View File

@@ -65,6 +65,7 @@ class Compat:
def table_with_schema(self, table: str):
return f"{self.references_schema if self.schema else ''}{table}"
# https://docs.sqlalchemy.org/en/14/core/connections.html#sqlalchemy.engine.CursorResult
class Connection(Compat):
def __init__(self, conn: AsyncSession, txn, typ, name, schema):
@@ -82,7 +83,9 @@ class Connection(Compat):
async def fetchall(self, query: str, values: dict = {}):
result = await self.conn.execute(self.rewrite_query(query), values)
return [r._mapping for r in result.all()] # will return [] if result list is empty
return [
r._mapping for r in result.all()
] # will return [] if result list is empty
async def fetchone(self, query: str, values: dict = {}):
result = await self.conn.execute(self.rewrite_query(query), values)
@@ -140,7 +143,7 @@ class Database(Compat):
self.engine = create_async_engine(database_uri, **kwargs)
self.async_session = sessionmaker(
self.engine,
self.engine, # type: ignore
expire_on_commit=False,
class_=AsyncSession, # type: ignore
)

View File

@@ -304,7 +304,7 @@ class LedgerCrudSqlite(LedgerCrud):
""",
{"b_": str(b_)},
)
return BlindedSignature.from_row(row) if row else None
return BlindedSignature.from_row(row) if row else None # type: ignore
async def get_promises(
self,
@@ -320,7 +320,7 @@ class LedgerCrudSqlite(LedgerCrud):
""",
{f"b_{i}": b_s[i] for i in range(len(b_s))},
)
return [BlindedSignature.from_row(r) for r in rows] if rows else []
return [BlindedSignature.from_row(r) for r in rows] if rows else [] # type: ignore
async def invalidate_proof(
self,
@@ -455,7 +455,7 @@ class LedgerCrudSqlite(LedgerCrud):
"amount": quote.amount,
"paid": quote.paid, # this is deprecated! we need to store it because we have a NOT NULL constraint | we could also remove the column but sqlite doesn't support that (we would have to make a new table)
"issued": quote.issued, # this is deprecated! we need to store it because we have a NOT NULL constraint | we could also remove the column but sqlite doesn't support that (we would have to make a new table)
"state": quote.state.name,
"state": quote.state.value,
"created_time": db.to_timestamp(
db.timestamp_from_seconds(quote.created_time) or ""
),
@@ -497,7 +497,7 @@ class LedgerCrudSqlite(LedgerCrud):
)
if row is None:
return None
return MintQuote.from_row(row) if row else None
return MintQuote.from_row(row) if row else None # type: ignore
async def get_mint_quote_by_request(
self,
@@ -513,7 +513,7 @@ class LedgerCrudSqlite(LedgerCrud):
""",
{"request": request},
)
return MintQuote.from_row(row) if row else None
return MintQuote.from_row(row) if row else None # type: ignore
async def update_mint_quote(
self,
@@ -525,7 +525,7 @@ class LedgerCrudSqlite(LedgerCrud):
await (conn or db).execute(
f"UPDATE {db.table_with_schema('mint_quotes')} SET state = :state, paid_time = :paid_time WHERE quote = :quote",
{
"state": quote.state.name,
"state": quote.state.value,
"paid_time": db.to_timestamp(
db.timestamp_from_seconds(quote.paid_time) or ""
),
@@ -554,7 +554,7 @@ class LedgerCrudSqlite(LedgerCrud):
"unit": quote.unit,
"amount": quote.amount,
"fee_reserve": quote.fee_reserve or 0,
"state": quote.state.name,
"state": quote.state.value,
"paid": quote.paid, # this is deprecated! we need to store it because we have a NOT NULL constraint | we could also remove the column but sqlite doesn't support that (we would have to make a new table)
"created_time": db.to_timestamp(
db.timestamp_from_seconds(quote.created_time) or ""
@@ -631,7 +631,7 @@ class LedgerCrudSqlite(LedgerCrud):
UPDATE {db.table_with_schema('melt_quotes')} SET state = :state, fee_paid = :fee_paid, paid_time = :paid_time, proof = :proof, change = :change, checking_id = :checking_id WHERE quote = :quote
""",
{
"state": quote.state.name,
"state": quote.state.value,
"fee_paid": quote.fee_paid,
"paid_time": db.to_timestamp(
db.timestamp_from_seconds(quote.paid_time) or ""

View File

@@ -1,7 +1,7 @@
import copy
from typing import Dict, List
from ..core.base import MintKeyset, Proof
from ..core.base import MeltQuoteState, MintKeyset, MintQuoteState, Proof
from ..core.crypto.keys import derive_keyset_id, derive_keyset_id_deprecated
from ..core.db import Connection, Database
from ..core.settings import settings
@@ -826,3 +826,15 @@ async def m021_add_change_and_expiry_to_melt_quotes(db: Database):
await conn.execute(
f"ALTER TABLE {db.table_with_schema('melt_quotes')} ADD COLUMN expiry TIMESTAMP"
)
async def m022_quote_set_states_to_values(db: Database):
async with db.connect() as conn:
for melt_quote_states in MeltQuoteState:
await conn.execute(
f"UPDATE {db.table_with_schema('melt_quotes')} SET state = '{melt_quote_states.value}' WHERE state = '{melt_quote_states.name}'"
)
for mint_quote_states in MintQuoteState:
await conn.execute(
f"UPDATE {db.table_with_schema('mint_quotes')} SET state = '{mint_quote_states.value}' WHERE state = '{mint_quote_states.name}'"
)

View File

@@ -2,23 +2,13 @@ from typing import Dict, List, Optional
from pydantic import BaseModel
from ...core.base import Invoice
class PayResponse(BaseModel):
ok: Optional[bool] = None
class InvoiceResponse(BaseModel):
amount: Optional[int] = None
invoice: Optional[Invoice] = None
id: Optional[str] = None
from ...core.base import MeltQuote, MintQuote
class SwapResponse(BaseModel):
outgoing_mint: str
incoming_mint: str
invoice: Invoice
mint_quote: MintQuote
balances: Dict
@@ -56,7 +46,8 @@ class LocksResponse(BaseModel):
class InvoicesResponse(BaseModel):
invoices: List[Invoice]
mint_quotes: List[MintQuote]
melt_quotes: List[MeltQuote]
class WalletsResponse(BaseModel):

View File

@@ -19,7 +19,11 @@ from ...lightning.base import (
)
from ...nostr.client.client import NostrClient
from ...tor.tor import TorProxy
from ...wallet.crud import get_lightning_invoices, get_reserved_proofs
from ...wallet.crud import (
get_bolt11_melt_quotes,
get_bolt11_mint_quotes,
get_reserved_proofs,
)
from ...wallet.helpers import (
deserialize_token_from_string,
init_wallet,
@@ -141,7 +145,7 @@ async def create_invoice(
response_model=PaymentStatus,
)
async def invoice_state(
payment_hash: str = Query(default=None, description="Payment hash of paid invoice"),
payment_request: str = Query(default=None, description="Payment request to check"),
mint: str = Query(
default=None,
description="Mint URL to create an invoice at (None for default mint)",
@@ -150,7 +154,7 @@ async def invoice_state(
global wallet
if mint:
wallet = await mint_wallet(mint)
state = await wallet.get_invoice_status(payment_hash)
state = await wallet.get_invoice_status(payment_request)
return state
@@ -185,11 +189,11 @@ async def swap(
raise Exception("mints for swap have to be different")
# request invoice from incoming mint
invoice = await incoming_wallet.request_mint(amount)
mint_quote = await incoming_wallet.request_mint(amount)
# pay invoice from outgoing mint
await outgoing_wallet.load_proofs(reload=True)
quote = await outgoing_wallet.melt_quote(invoice.bolt11)
quote = await outgoing_wallet.melt_quote(mint_quote.request)
total_amount = quote.amount + quote.fee_reserve
if outgoing_wallet.available_balance < total_amount:
raise Exception("balance too low")
@@ -198,17 +202,17 @@ async def swap(
outgoing_wallet.proofs, total_amount, set_reserved=True
)
await outgoing_wallet.melt(
send_proofs, invoice.bolt11, quote.fee_reserve, quote.quote
send_proofs, mint_quote.request, quote.fee_reserve, quote.quote
)
# mint token in incoming mint
await incoming_wallet.mint(amount, id=invoice.id)
await incoming_wallet.mint(amount, quote_id=mint_quote.quote)
await incoming_wallet.load_proofs(reload=True)
mint_balances = await incoming_wallet.balance_per_minturl()
return SwapResponse(
outgoing_mint=outgoing_mint,
incoming_mint=incoming_mint,
invoice=invoice,
mint_quote=mint_quote,
balances=mint_balances,
)
@@ -386,8 +390,9 @@ async def locks():
"/invoices", name="List all pending invoices", response_model=InvoicesResponse
)
async def invoices():
invoices = await get_lightning_invoices(db=wallet.db)
return InvoicesResponse(invoices=invoices)
mint_quotes = await get_bolt11_mint_quotes(db=wallet.db)
melt_quotes = await get_bolt11_melt_quotes(db=wallet.db)
return InvoicesResponse(mint_quotes=mint_quotes, melt_quotes=melt_quotes)
@router.get(

View File

@@ -15,7 +15,15 @@ import click
from click import Context
from loguru import logger
from ...core.base import Invoice, Method, MintQuoteState, TokenV4, Unit
from ...core.base import (
MeltQuote,
MeltQuoteState,
Method,
MintQuote,
MintQuoteState,
TokenV4,
Unit,
)
from ...core.helpers import sum_proofs
from ...core.json_rpc.base import JSONRPCNotficationParams
from ...core.logging import configure_logger
@@ -24,8 +32,9 @@ from ...core.settings import settings
from ...nostr.client.client import NostrClient
from ...tor.tor import TorProxy
from ...wallet.crud import (
get_lightning_invoice,
get_lightning_invoices,
get_bolt11_melt_quotes,
get_bolt11_mint_quote,
get_bolt11_mint_quotes,
get_reserved_proofs,
get_seed_and_mnemonic,
)
@@ -302,7 +311,7 @@ async def invoice(
)
paid = False
invoice_nonlocal: Union[None, Invoice] = None
invoice_nonlocal: Union[None, MintQuote] = None
subscription_nonlocal: Union[None, SubscriptionManager] = None
def mint_invoice_callback(msg: JSONRPCNotficationParams):
@@ -318,20 +327,24 @@ async def invoice(
if paid:
return
try:
quote = PostMintQuoteResponse.parse_obj(msg.payload)
ws_quote_resp = PostMintQuoteResponse.parse_obj(msg.payload)
except Exception:
return
logger.debug(f"Received callback for quote: {quote}")
logger.debug(
f"Received callback for quote: {ws_quote_resp.quote}: state {ws_quote_resp.state}"
)
# we need to sleep to give the callback map some time to be populated
time.sleep(0.1)
if (
(quote.paid or quote.state == MintQuoteState.paid.value)
and quote.request == invoice.bolt11
(ws_quote_resp.state == MintQuoteState.paid.value)
and ws_quote_resp.request == mint_quote.request
and msg.subId in subscription.callback_map.keys()
):
try:
asyncio.run(
wallet.mint(int(amount), split=optional_split, id=invoice.id)
wallet.mint(
int(amount), split=optional_split, quote_id=mint_quote.quote
)
)
# set paid so we won't react to any more callbacks
paid = True
@@ -348,21 +361,21 @@ async def invoice(
Method["bolt11"], wallet.unit
)
if mint_supports_websockets and not no_check:
invoice, subscription = await wallet.request_mint_with_callback(
mint_quote, subscription = await wallet.request_mint_with_callback(
amount, callback=mint_invoice_callback, memo=memo
)
invoice_nonlocal, subscription_nonlocal = invoice, subscription
invoice_nonlocal, subscription_nonlocal = mint_quote, subscription
else:
invoice = await wallet.request_mint(amount, memo=memo)
if invoice.bolt11:
mint_quote = await wallet.request_mint(amount, memo=memo)
if mint_quote.request:
print("")
print(f"Pay invoice to mint {wallet.unit.str(amount)}:")
print("")
print(f"Invoice: {invoice.bolt11}")
print(f"Invoice: {mint_quote.request}")
print("")
print(
"You can use this command to check the invoice: cashu invoice"
f" {amount} --id {invoice.id}"
f" {amount} --id {mint_quote.quote}"
)
if no_check:
return
@@ -381,9 +394,11 @@ async def invoice(
while time.time() < check_until and not paid:
await asyncio.sleep(5)
try:
mint_quote_resp = await wallet.get_mint_quote(invoice.id)
mint_quote_resp = await wallet.get_mint_quote(mint_quote.quote)
if mint_quote_resp.state == MintQuoteState.paid.value:
await wallet.mint(amount, split=optional_split, id=invoice.id)
await wallet.mint(
amount, split=optional_split, quote_id=mint_quote.quote
)
paid = True
else:
print(".", end="", flush=True)
@@ -403,7 +418,7 @@ async def invoice(
# user paid invoice before and wants to check the quote id
elif amount and id:
await wallet.mint(amount, split=optional_split, id=id)
await wallet.mint(amount, split=optional_split, quote_id=id)
# close open subscriptions so we can exit
try:
@@ -422,10 +437,10 @@ async def invoice(
@coro
async def swap(ctx: Context):
print("Select the mint to swap from:")
outgoing_wallet = await get_mint_wallet(ctx, force_select=True)
outgoing_wallet: Wallet = await get_mint_wallet(ctx, force_select=True)
print("Select the mint to swap to:")
incoming_wallet = await get_mint_wallet(ctx, force_select=True)
incoming_wallet: Wallet = await get_mint_wallet(ctx, force_select=True)
await incoming_wallet.load_mint()
await outgoing_wallet.load_mint()
@@ -437,22 +452,25 @@ async def swap(ctx: Context):
assert amount > 0, "amount is not positive"
# request invoice from incoming mint
invoice = await incoming_wallet.request_mint(amount)
mint_quote = await incoming_wallet.request_mint(amount)
# pay invoice from outgoing mint
quote = await outgoing_wallet.melt_quote(invoice.bolt11)
total_amount = quote.amount + quote.fee_reserve
melt_quote_resp = await outgoing_wallet.melt_quote(mint_quote.request)
total_amount = melt_quote_resp.amount + melt_quote_resp.fee_reserve
if outgoing_wallet.available_balance < total_amount:
raise Exception("balance too low")
send_proofs, fees = await outgoing_wallet.select_to_send(
outgoing_wallet.proofs, total_amount, set_reserved=True
)
await outgoing_wallet.melt(
send_proofs, invoice.bolt11, quote.fee_reserve, quote.quote
send_proofs,
mint_quote.request,
melt_quote_resp.fee_reserve,
melt_quote_resp.quote,
)
# mint token in incoming mint
await incoming_wallet.mint(amount, id=invoice.id)
await incoming_wallet.mint(amount, quote_id=mint_quote.quote)
await incoming_wallet.load_proofs(reload=True)
await print_mint_balances(incoming_wallet, show_mints=True)
@@ -875,67 +893,85 @@ async def invoices(ctx, paid: bool, unpaid: bool, pending: bool, mint: bool):
if mint:
await wallet.load_mint()
paid_arg = None
melt_state: MeltQuoteState | None = None
mint_state: MintQuoteState | None = None
if unpaid:
paid_arg = False
melt_state = MeltQuoteState.unpaid
mint_state = MintQuoteState.unpaid
elif paid:
paid_arg = True
melt_state = MeltQuoteState.paid
mint_state = MintQuoteState.paid
invoices = await get_lightning_invoices(
melt_quotes = await get_bolt11_melt_quotes(
db=wallet.db,
paid=paid_arg,
pending=pending or None,
state=melt_state,
)
if len(invoices) == 0:
mint_quotes = await get_bolt11_mint_quotes(
db=wallet.db,
state=mint_state,
)
if len(melt_quotes) == 0 and len(mint_quotes) == 0:
print("No invoices found.")
return
async def _try_to_mint_pending_invoice(amount: int, id: str) -> Optional[Invoice]:
async def _try_to_mint_pending_invoice(amount: int, id: str) -> Optional[MintQuote]:
try:
await wallet.mint(amount, id)
return await get_lightning_invoice(db=wallet.db, id=id)
proofs = await wallet.mint(amount, id)
print(f"Received {wallet.unit.str(sum_proofs(proofs))}")
return await get_bolt11_mint_quote(db=wallet.db, quote=id)
except Exception as e:
logger.error(f"Could not mint pending invoice [{id}]: {e}")
logger.error(f"Could not mint pending invoice: {e}")
return None
def _print_invoice_info(invoice: Invoice):
def _print_quote_info(
quote: MintQuote | MeltQuote | None, counter: int | None = None
):
print("\n--------------------------\n")
print(f"Amount: {abs(invoice.amount)}")
print(f"ID: {invoice.id}")
print(f"Paid: {invoice.paid}")
print(f"Incoming: {invoice.amount > 0}")
if counter:
print(f"#{counter}", end=" ")
if isinstance(quote, MintQuote):
print("Mint quote (incoming invoice)")
elif isinstance(quote, MeltQuote):
print("Melt quote (outgoing invoice)")
else:
return
print(f"Amount: {abs(quote.amount)}")
print(f"Mint: {quote.mint}")
print(f"ID: {quote.quote}")
print(f"State: {quote.state}")
if invoice.preimage:
print(f"Preimage: {invoice.preimage}")
if invoice.time_created:
if isinstance(quote, MeltQuote):
if quote.payment_preimage:
print(f"Preimage: {quote.payment_preimage}")
if quote.created_time:
d = datetime.fromtimestamp(
int(float(invoice.time_created)), timezone.utc
int(float(quote.created_time)), timezone.utc
).strftime("%Y-%m-%d %H:%M:%S")
print(f"Created at: {d}")
if invoice.time_paid:
if quote.paid_time:
d = datetime.fromtimestamp(
(int(float(invoice.time_paid))), timezone.utc
(int(float(quote.paid_time))), timezone.utc
).strftime("%Y-%m-%d %H:%M:%S")
print(f"Paid at: {d}")
print(f"\nPayment request: {invoice.bolt11}")
print(f"\nPayment request: {quote.request}")
invoices_printed_count = 0
for invoice in invoices:
is_pending_invoice = invoice.out is False and invoice.paid is False
if is_pending_invoice and mint:
# Tries to mint pending invoice
updated_invoice = await _try_to_mint_pending_invoice(
invoice.amount, invoice.id
)
# If the mint ran successfully and we are querying for pending or unpaid invoices, do not print it
if pending or unpaid:
continue
# Otherwise, print the invoice with updated values
if updated_invoice:
invoice = updated_invoice
for melt_quote in melt_quotes:
_print_quote_info(melt_quote, invoices_printed_count + 1)
invoices_printed_count += 1
_print_invoice_info(invoice)
for mint_quote in mint_quotes:
if mint_quote.state == MintQuoteState.unpaid and mint:
# Tries to mint pending invoice
mint_quote_pay = await _try_to_mint_pending_invoice(
mint_quote.amount, mint_quote.quote
)
# If minting was successful, we don't need to print this invoice
if mint_quote_pay:
continue
_print_quote_info(mint_quote, invoices_printed_count + 1)
invoices_printed_count += 1
if invoices_printed_count == 0:

View File

@@ -2,7 +2,14 @@ import json
import time
from typing import Any, Dict, List, Optional, Tuple
from ..core.base import Invoice, Proof, WalletKeyset
from ..core.base import (
MeltQuote,
MeltQuoteState,
MintQuote,
MintQuoteState,
Proof,
WalletKeyset,
)
from ..core.db import Connection, Database
@@ -217,7 +224,7 @@ async def get_keysets(
""",
values,
)
return [WalletKeyset.from_row(r) for r in rows]
return [WalletKeyset.from_row(r) for r in rows] # type: ignore
async def update_keyset(
@@ -238,83 +245,78 @@ async def update_keyset(
)
async def store_lightning_invoice(
async def store_bolt11_mint_quote(
db: Database,
invoice: Invoice,
quote: MintQuote,
conn: Optional[Connection] = None,
) -> None:
await (conn or db).execute(
"""
INSERT INTO invoices
(amount, bolt11, id, payment_hash, preimage, paid, time_created, time_paid, out)
VALUES (:amount, :bolt11, :id, :payment_hash, :preimage, :paid, :time_created, :time_paid, :out)
INSERT INTO bolt11_mint_quotes
(quote, mint, method, request, checking_id, unit, amount, state, created_time, paid_time, expiry)
VALUES (:quote, :mint, :method, :request, :checking_id, :unit, :amount, :state, :created_time, :paid_time, :expiry)
""",
{
"amount": invoice.amount,
"bolt11": invoice.bolt11,
"id": invoice.id,
"payment_hash": invoice.payment_hash,
"preimage": invoice.preimage,
"paid": invoice.paid,
"time_created": invoice.time_created,
"time_paid": invoice.time_paid,
"out": invoice.out,
"quote": quote.quote,
"mint": quote.mint,
"method": quote.method,
"request": quote.request,
"checking_id": quote.checking_id,
"unit": quote.unit,
"amount": quote.amount,
"state": quote.state.value,
"created_time": quote.created_time,
"paid_time": quote.paid_time,
"expiry": quote.expiry,
},
)
async def get_lightning_invoice(
*,
async def get_bolt11_mint_quote(
db: Database,
id: str = "",
payment_hash: str = "",
out: Optional[bool] = None,
quote: str | None = None,
request: str | None = None,
conn: Optional[Connection] = None,
) -> Optional[Invoice]:
) -> Optional[MintQuote]:
if not quote and not request:
raise ValueError("quote or request must be provided")
clauses = []
values: Dict[str, Any] = {}
if id:
clauses.append("id = :id")
values["id"] = id
if payment_hash:
clauses.append("payment_hash = :payment_hash")
values["payment_hash"] = payment_hash
if out is not None:
clauses.append("out = :out")
values["out"] = out
if quote:
clauses.append("quote = :quote")
values["quote"] = quote
if request:
clauses.append("request = :request")
values["request"] = request
where = ""
if clauses:
where = f"WHERE {' AND '.join(clauses)}"
query = f"""
SELECT * from invoices
{where}
"""
row = await (conn or db).fetchone(
query,
f"""
SELECT * from bolt11_mint_quotes
{where}
""",
values,
)
return Invoice(**row) if row else None
return MintQuote.from_row(row) if row else None # type: ignore
async def get_lightning_invoices(
async def get_bolt11_mint_quotes(
db: Database,
paid: Optional[bool] = None,
pending: Optional[bool] = None,
mint: Optional[str] = None,
state: Optional[MintQuoteState] = None,
conn: Optional[Connection] = None,
) -> List[Invoice]:
) -> List[MintQuote]:
clauses = []
values: Dict[str, Any] = {}
if paid is not None and not pending:
clauses.append("paid = :paid")
values["paid"] = paid
if pending:
clauses.append("paid = :paid")
values["paid"] = False
clauses.append("out = :out")
values["out"] = False
if mint:
clauses.append("mint = :mint")
values["mint"] = mint
if state:
clauses.append("state = :state")
values["state"] = state.value
where = ""
if clauses:
@@ -322,37 +324,149 @@ async def get_lightning_invoices(
rows = await (conn or db).fetchall(
f"""
SELECT * from invoices
SELECT * from bolt11_mint_quotes
{where}
""",
values,
)
return [Invoice(**r) for r in rows]
return [MintQuote.from_row(r) for r in rows] # type: ignore
async def update_lightning_invoice(
async def update_bolt11_mint_quote(
db: Database,
id: str,
paid: bool,
time_paid: Optional[int] = None,
preimage: Optional[str] = None,
quote: str,
state: MintQuoteState,
paid_time: int,
conn: Optional[Connection] = None,
) -> None:
await (conn or db).execute(
"""
UPDATE bolt11_mint_quotes
SET state = :state, paid_time = :paid_time
WHERE quote = :quote
""",
{
"state": state.value,
"paid_time": paid_time,
"quote": quote,
},
)
async def store_bolt11_melt_quote(
db: Database,
quote: MeltQuote,
conn: Optional[Connection] = None,
) -> None:
await (conn or db).execute(
"""
INSERT INTO bolt11_melt_quotes
(quote, mint, method, request, checking_id, unit, amount, fee_reserve, state, created_time, paid_time, fee_paid, payment_preimage, expiry, change)
VALUES (:quote, :mint, :method, :request, :checking_id, :unit, :amount, :fee_reserve, :state, :created_time, :paid_time, :fee_paid, :payment_preimage, :expiry, :change)
""",
{
"quote": quote.quote,
"mint": quote.mint,
"method": quote.method,
"request": quote.request,
"checking_id": quote.checking_id,
"unit": quote.unit,
"amount": quote.amount,
"fee_reserve": quote.fee_reserve,
"state": quote.state.value,
"created_time": quote.created_time,
"paid_time": quote.paid_time,
"fee_paid": quote.fee_paid,
"payment_preimage": quote.payment_preimage,
"expiry": quote.expiry,
"change": (
json.dumps([c.dict() for c in quote.change]) if quote.change else ""
),
},
)
async def get_bolt11_melt_quote(
db: Database,
quote: Optional[str] = None,
request: Optional[str] = None,
conn: Optional[Connection] = None,
) -> Optional[MeltQuote]:
if not quote and not request:
raise ValueError("quote or request must be provided")
clauses = []
values: Dict[str, Any] = {}
clauses.append("paid = :paid")
values["paid"] = paid
if quote:
clauses.append("quote = :quote")
values["quote"] = quote
if request:
clauses.append("request = :request")
values["request"] = request
if time_paid:
clauses.append("time_paid = :time_paid")
values["time_paid"] = time_paid
if preimage:
clauses.append("preimage = :preimage")
values["preimage"] = preimage
where = ""
if clauses:
where = f"WHERE {' AND '.join(clauses)}"
row = await (conn or db).fetchone(
f"""
SELECT * from bolt11_melt_quotes
{where}
""",
values,
)
return MeltQuote.from_row(row) if row else None # type: ignore
async def get_bolt11_melt_quotes(
db: Database,
mint: Optional[str] = None,
state: Optional[MeltQuoteState] = None,
conn: Optional[Connection] = None,
) -> List[MeltQuote]:
clauses = []
values: Dict[str, Any] = {}
if mint:
clauses.append("mint = :mint")
values["mint"] = mint
if state:
clauses.append("state = :state")
values["state"] = state.value
where = ""
if clauses:
where = f"WHERE {' AND '.join(clauses)}"
rows = await (conn or db).fetchall(
f"""
SELECT * from bolt11_melt_quotes
{where}
""",
values,
)
return [MeltQuote.from_row(r) for r in rows] # type: ignore
async def update_bolt11_melt_quote(
db: Database,
quote: str,
state: MeltQuoteState,
paid_time: int,
fee_paid: int,
payment_preimage: str,
conn: Optional[Connection] = None,
) -> None:
await (conn or db).execute(
f"UPDATE invoices SET {', '.join(clauses)} WHERE id = :id",
{**values, "id": id},
"""
UPDATE bolt11_melt_quotes
SET state = :state, paid_time = :paid_time, fee_paid = :fee_paid, payment_preimage = :payment_preimage
WHERE quote = :quote
""",
{
"state": state.value,
"paid_time": paid_time,
"fee_paid": fee_paid,
"payment_preimage": payment_preimage,
"quote": quote,
},
)
@@ -423,7 +537,7 @@ async def get_nostr_last_check_timestamp(
""",
{"type": "dm"},
)
return row[0] if row else None
return row[0] if row else None # type: ignore
async def get_seed_and_mnemonic(

View File

@@ -12,7 +12,11 @@ from ...lightning.base import (
PaymentStatus,
StatusResponse,
)
from ...wallet.crud import get_lightning_invoice, get_proofs
from ...wallet.crud import (
get_bolt11_melt_quote,
get_bolt11_mint_quote,
get_proofs,
)
from ..wallet import Wallet
@@ -47,21 +51,22 @@ class LightningWallet(Wallet):
Returns:
str: invoice
"""
invoice = await self.request_mint(amount, memo)
mint_quote = await self.request_mint(amount, memo)
return InvoiceResponse(
ok=True, payment_request=invoice.bolt11, checking_id=invoice.payment_hash
ok=True,
payment_request=mint_quote.request,
)
async def pay_invoice(self, pr: str) -> PaymentResponse:
async def pay_invoice(self, request: str) -> PaymentResponse:
"""Pay lightning invoice
Args:
pr (str): bolt11 payment request
request (str): bolt11 payment request
Returns:
PaymentResponse: containing details of the operation
"""
quote = await self.melt_quote(pr)
quote = await self.melt_quote(request)
total_amount = quote.amount + quote.fee_reserve
assert total_amount > 0, "amount is not positive"
if self.available_balance < total_amount:
@@ -69,13 +74,13 @@ class LightningWallet(Wallet):
return PaymentResponse(result=PaymentResult.FAILED)
_, send_proofs = await self.swap_to_send(self.proofs, total_amount)
try:
resp = await self.melt(send_proofs, pr, quote.fee_reserve, quote.quote)
resp = await self.melt(send_proofs, request, quote.fee_reserve, quote.quote)
if resp.change:
fees_paid_sat = quote.fee_reserve - sum_promises(resp.change)
else:
fees_paid_sat = quote.fee_reserve
invoice_obj = bolt11.decode(pr)
invoice_obj = bolt11.decode(request)
return PaymentResponse(
result=PaymentResult.SETTLED,
checking_id=invoice_obj.payment_hash,
@@ -86,55 +91,49 @@ class LightningWallet(Wallet):
print("Exception:", e)
return PaymentResponse(result=PaymentResult.FAILED, error_message=str(e))
async def get_invoice_status(self, payment_hash: str) -> PaymentStatus:
async def get_invoice_status(self, request: str) -> PaymentStatus:
"""Get lightning invoice status (incoming)
Args:
invoice (str): lightning invoice
request (str): lightning invoice request
Returns:
str: status
"""
invoice = await get_lightning_invoice(
db=self.db, payment_hash=payment_hash, out=False
)
if not invoice:
mint_quote = await get_bolt11_mint_quote(db=self.db, request=request)
if not mint_quote:
return PaymentStatus(result=PaymentResult.UNKNOWN)
if invoice.paid:
if mint_quote.paid:
return PaymentStatus(result=PaymentResult.SETTLED)
try:
# to check the invoice state, we try minting tokens
await self.mint(invoice.amount, id=invoice.id)
await self.mint(mint_quote.amount, quote_id=mint_quote.quote)
return PaymentStatus(result=PaymentResult.SETTLED)
except Exception as e:
print(e)
return PaymentStatus(result=PaymentResult.FAILED)
async def get_payment_status(self, payment_hash: str) -> PaymentStatus:
async def get_payment_status(self, request: str) -> PaymentStatus:
"""Get lightning payment status (outgoing)
Args:
payment_hash (str): lightning invoice payment_hash
request (str): lightning invoice request
Returns:
str: status
"""
# NOTE: consider adding this in wallet.py and update invoice state to paid in DB
melt_quote = await get_bolt11_melt_quote(db=self.db, request=request)
invoice = await get_lightning_invoice(
db=self.db, payment_hash=payment_hash, out=True
)
if not invoice:
if not melt_quote:
return PaymentStatus(
result=PaymentResult.FAILED
) # "invoice not found (in db)"
if invoice.paid:
if melt_quote.paid:
return PaymentStatus(
result=PaymentResult.SETTLED, preimage=invoice.preimage
result=PaymentResult.SETTLED, preimage=melt_quote.payment_preimage
) # "paid (in db)"
proofs = await get_proofs(db=self.db, melt_id=invoice.id)
proofs = await get_proofs(db=self.db, melt_id=melt_quote.quote)
if not proofs:
return PaymentStatus(
result=PaymentResult.FAILED

View File

@@ -245,79 +245,44 @@ async def m012_add_fee_to_keysets(db: Database):
await conn.execute("UPDATE keysets SET input_fee_ppk = 0")
# # async def m020_add_state_to_mint_and_melt_quotes(db: Database):
# # async with db.connect() as conn:
# # await conn.execute(
# # f"ALTER TABLE {db.table_with_schema('mint_quotes')} ADD COLUMN state TEXT"
# # )
# # await conn.execute(
# # f"ALTER TABLE {db.table_with_schema('melt_quotes')} ADD COLUMN state TEXT"
# # )
async def m013_add_mint_and_melt_quote_tables(db: Database):
async with db.connect() as conn:
await conn.execute(
"""
CREATE TABLE IF NOT EXISTS bolt11_mint_quotes (
quote TEXT PRIMARY KEY,
mint TEXT NOT NULL,
method TEXT NOT NULL,
request TEXT NOT NULL,
checking_id TEXT NOT NULL,
unit TEXT NOT NULL,
amount INTEGER NOT NULL,
state TEXT NOT NULL,
created_time INTEGER,
paid_time INTEGER,
expiry INTEGER
);
"""
)
# # # get all melt and mint quotes and figure out the state to set using the `paid` column
# # # and the `paid` and `issued` column respectively
# # # mint quotes:
# # async with db.connect() as conn:
# # rows = await conn.fetchall(
# # f"SELECT * FROM {db.table_with_schema('mint_quotes')}"
# # )
# # for row in rows:
# # if row["issued"]:
# # state = "issued"
# # elif row["paid"]:
# # state = "paid"
# # else:
# # state = "unpaid"
# # await conn.execute(
# # f"UPDATE {db.table_with_schema('mint_quotes')} SET state = '{state}' WHERE quote = '{row['quote']}'"
# # )
# # # melt quotes:
# # async with db.connect() as conn:
# # rows = await conn.fetchall(
# # f"SELECT * FROM {db.table_with_schema('melt_quotes')}"
# # )
# # for row in rows:
# # if row["paid"]:
# # state = "paid"
# # else:
# # state = "unpaid"
# # await conn.execute(
# # f"UPDATE {db.table_with_schema('melt_quotes')} SET state = '{state}' WHERE quote = '{row['quote']}'"
# # )
# # add the equivalent of the above migration for the wallet here. do not use table_with_schema. use the tables and columns
# # as they are defined in the wallet db
# async def m020_add_state_to_mint_and_melt_quotes(db: Database):
# async with db.connect() as conn:
# await conn.execute("ALTER TABLE mint_quotes ADD COLUMN state TEXT")
# await conn.execute("ALTER TABLE melt_quotes ADD COLUMN state TEXT")
# # get all melt and mint quotes and figure out the state to set using the `paid` column
# # and the `paid` and `issued` column respectively
# # mint quotes:
# async with db.connect() as conn:
# rows = await conn.fetchall("SELECT * FROM mint_quotes")
# for row in rows:
# if row["issued"]:
# state = "issued"
# elif row["paid"]:
# state = "paid"
# else:
# state = "unpaid"
# await conn.execute(
# f"UPDATE mint_quotes SET state = '{state}' WHERE quote = '{row['quote']}'"
# )
# # melt quotes:
# async with db.connect() as conn:
# rows = await conn.fetchall("SELECT * FROM melt_quotes")
# for row in rows:
# if row["paid"]:
# state = "paid"
# else:
# state = "unpaid"
# await conn.execute(
# f"UPDATE melt_quotes SET state = '{state}' WHERE quote = '{row['quote']}'"
# )
await conn.execute(
"""
CREATE TABLE IF NOT EXISTS bolt11_melt_quotes (
quote TEXT PRIMARY KEY,
mint TEXT NOT NULL,
method TEXT NOT NULL,
request TEXT NOT NULL,
checking_id TEXT NOT NULL,
unit TEXT NOT NULL,
amount INTEGER NOT NULL,
fee_reserve INTEGER NOT NULL,
state TEXT NOT NULL,
created_time INTEGER,
paid_time INTEGER,
fee_paid INTEGER,
payment_preimage TEXT,
expiry INTEGER,
change TEXT
);
"""
)

View File

@@ -9,6 +9,8 @@ from httpx import Response
from loguru import logger
from pydantic import ValidationError
from cashu.wallet.crud import get_bolt11_melt_quote
from ..core.base import (
BlindedMessage,
BlindedSignature,
@@ -45,9 +47,6 @@ from ..core.models import (
)
from ..core.settings import settings
from ..tor.tor import TorProxy
from .crud import (
get_lightning_invoice,
)
from .wallet_deprecated import LedgerAPIDeprecated
@@ -476,10 +475,10 @@ class LedgerAPI(LedgerAPIDeprecated):
# BEGIN backwards compatibility < 0.15.0
# assume the mint has not upgraded yet if we get a 404
if resp.status_code == 404:
invoice = await get_lightning_invoice(id=quote, db=self.db)
assert invoice, f"no invoice found for id {quote}"
melt_quote = await get_bolt11_melt_quote(quote=quote, db=self.db)
assert melt_quote, f"no melt_quote found for id {quote}"
ret: PostMeltResponse_deprecated = await self.melt_deprecated(
proofs=proofs, outputs=outputs, invoice=invoice.bolt11
proofs=proofs, outputs=outputs, invoice=melt_quote.request
)
elif isinstance(e, ValidationError):
# BEGIN backwards compatibility < 0.16.0

View File

@@ -4,7 +4,6 @@ import threading
import time
from typing import Callable, Dict, List, Optional, Tuple, Union
import bolt11
from bip32 import BIP32
from loguru import logger
@@ -12,8 +11,10 @@ from ..core.base import (
BlindedMessage,
BlindedSignature,
DLEQWallet,
Invoice,
MeltQuote,
MeltQuoteState,
MintQuote,
MintQuoteState,
Proof,
Unit,
WalletKeyset,
@@ -26,6 +27,7 @@ from ..core.errors import KeysetNotFoundError
from ..core.helpers import (
amount_summary,
calculate_number_of_blank_outputs,
sum_promises,
sum_proofs,
)
from ..core.json_rpc.base import JSONRPCSubscriptionKinds
@@ -45,11 +47,13 @@ from .crud import (
invalidate_proof,
secret_used,
set_secret_derivation,
store_bolt11_melt_quote,
store_bolt11_mint_quote,
store_keyset,
store_lightning_invoice,
store_proof,
update_bolt11_melt_quote,
update_bolt11_mint_quote,
update_keyset,
update_lightning_invoice,
update_proof,
)
from .htlc import WalletHTLC
@@ -312,7 +316,9 @@ class Wallet(
self.keyset_id = chosen_keyset.id
logger.debug(f"Activated keyset {self.keyset_id}")
logger.debug(
f"Activated keyset {self.keyset_id} ({self.keysets[self.keyset_id].unit}) fee: {self.keysets[self.keyset_id].input_fee_ppk}"
)
async def load_mint(self, keyset_id: str = "", force_old_keysets=False) -> None:
"""
@@ -381,8 +387,8 @@ class Wallet(
async def request_mint_with_callback(
self, amount: int, callback: Callable, memo: Optional[str] = None
) -> Tuple[Invoice, SubscriptionManager]:
"""Request a Lightning invoice for minting tokens.
) -> Tuple[MintQuote, SubscriptionManager]:
"""Request a quote invoice for minting tokens.
Args:
amount (int): Amount for Lightning invoice in satoshis
@@ -390,7 +396,7 @@ class Wallet(
memo (Optional[str], optional): Memo for the Lightning invoice. Defaults
Returns:
Invoice: Lightning invoice
MintQuote: Mint Quote
"""
mint_qoute = await super().mint_quote(amount, self.unit, memo)
subscriptions = SubscriptionManager(self.url)
@@ -402,21 +408,13 @@ class Wallet(
filters=[mint_qoute.quote],
callback=callback,
)
# return the invoice
decoded_invoice = bolt11.decode(mint_qoute.request)
invoice = Invoice(
amount=amount,
bolt11=mint_qoute.request,
payment_hash=decoded_invoice.payment_hash,
id=mint_qoute.quote,
out=False,
time_created=int(time.time()),
)
await store_lightning_invoice(db=self.db, invoice=invoice)
return invoice, subscriptions
quote = MintQuote.from_resp_wallet(mint_qoute, self.url, amount, self.unit.name)
await store_bolt11_mint_quote(db=self.db, quote=quote)
async def request_mint(self, amount: int, memo: Optional[str] = None) -> Invoice:
"""Request a Lightning invoice for minting tokens.
return quote, subscriptions
async def request_mint(self, amount: int, memo: Optional[str] = None) -> MintQuote:
"""Request a quote invoice for minting tokens.
Args:
amount (int): Amount for Lightning invoice in satoshis
@@ -424,20 +422,14 @@ class Wallet(
memo (Optional[str], optional): Memo for the Lightning invoice. Defaults to None.
Returns:
PostMintQuoteResponse: Mint Quote Response
MintQuote: Mint Quote
"""
mint_quote_response = await super().mint_quote(amount, self.unit, memo)
decoded_invoice = bolt11.decode(mint_quote_response.request)
invoice = Invoice(
amount=amount,
bolt11=mint_quote_response.request,
payment_hash=decoded_invoice.payment_hash,
id=mint_quote_response.quote,
out=False,
time_created=int(time.time()),
quote = MintQuote.from_resp_wallet(
mint_quote_response, self.url, amount, self.unit.name
)
await store_lightning_invoice(db=self.db, invoice=invoice)
return invoice
await store_bolt11_mint_quote(db=self.db, quote=quote)
return quote
def split_wallet_state(self, amount: int) -> List[int]:
"""This function produces an amount split for outputs based on the current state of the wallet.
@@ -484,33 +476,10 @@ class Wallet(
return amounts
async def mint_quote(self, amount: int, memo: Optional[str] = None) -> Invoice:
"""Request a Lightning invoice for minting tokens.
Args:
amount (int): Amount for Lightning invoice in satoshis
memo (Optional[str], optional): Memo for the Lightning invoice. Defaults to None.
Returns:
Invoice: Lightning invoice for minting tokens
"""
mint_quote_response = await super().mint_quote(amount, self.unit)
decoded_invoice = bolt11.decode(mint_quote_response.request)
invoice = Invoice(
amount=amount,
bolt11=mint_quote_response.request,
payment_hash=decoded_invoice.payment_hash,
id=mint_quote_response.quote,
out=False,
time_created=int(time.time()),
)
await store_lightning_invoice(db=self.db, invoice=invoice)
return invoice
async def mint(
self,
amount: int,
id: str,
quote_id: str,
split: Optional[List[int]] = None,
) -> List[Proof]:
"""Mint tokens of a specific amount after an invoice has been paid.
@@ -553,7 +522,7 @@ class Wallet(
outputs, rs = self._construct_outputs(amounts, secrets, rs)
# will raise exception if mint is unsuccessful
promises = await super().mint(outputs, id)
promises = await super().mint(outputs, quote_id)
promises_keyset_id = promises[0].id
await bump_secret_derivation(
@@ -561,15 +530,17 @@ class Wallet(
)
proofs = await self._construct_proofs(promises, secrets, rs, derivation_paths)
if id:
await update_lightning_invoice(
db=self.db, id=id, paid=True, time_paid=int(time.time())
await update_bolt11_mint_quote(
db=self.db,
quote=quote_id,
state=MintQuoteState.paid,
paid_time=int(time.time()),
)
# store the mint_id in proofs
async with self.db.connect() as conn:
for p in proofs:
p.mint_id = id
await update_proof(p, mint_id=id, conn=conn)
p.mint_id = quote_id
await update_proof(p, mint_id=quote_id, conn=conn)
return proofs
async def redeem(
@@ -725,11 +696,19 @@ class Wallet(
"""
if amount and not self.mint_info.supports_mpp("bolt11", self.unit):
raise Exception("Mint does not support MPP, cannot specify amount.")
melt_quote = await super().melt_quote(invoice, self.unit, amount)
melt_quote_resp = await super().melt_quote(invoice, self.unit, amount)
logger.debug(
f"Mint wants {self.unit.str(melt_quote.fee_reserve)} as fee reserve."
f"Mint wants {self.unit.str(melt_quote_resp.fee_reserve)} as fee reserve."
)
return melt_quote
melt_quote = MeltQuote.from_resp_wallet(
melt_quote_resp,
self.url,
amount=melt_quote_resp.amount,
unit=self.unit.name,
request=invoice,
)
await store_bolt11_melt_quote(db=self.db, quote=melt_quote)
return melt_quote_resp
async def melt(
self, proofs: List[Proof], invoice: str, fee_reserve_sat: int, quote_id: str
@@ -744,6 +723,7 @@ class Wallet(
"""
# Make sure we're operating on an independent copy of proofs
proofs = copy.copy(proofs)
amount = sum_proofs(proofs)
# Generate a number of blank outputs for any overpaid fees. As described in
# NUT-08, the mint will imprint these outputs with a value depending on the
@@ -764,59 +744,56 @@ class Wallet(
p.melt_id = quote_id
await update_proof(p, melt_id=quote_id, conn=conn)
# we store the invoice object in the database to later be able to check the invoice state
decoded_invoice = bolt11.decode(invoice)
invoice_obj = Invoice(
amount=-sum_proofs(proofs),
bolt11=invoice,
payment_hash=decoded_invoice.payment_hash,
# preimage=status.preimage,
paid=False,
time_paid=int(time.time()),
id=quote_id, # store the same ID in the invoice
out=True, # outgoing invoice
melt_quote_resp = await super().melt(quote_id, proofs, change_outputs)
melt_quote = MeltQuote.from_resp_wallet(
melt_quote_resp,
self.url,
amount=amount,
unit=self.unit.name,
request=invoice,
)
# store invoice in db as not paid yet
await store_lightning_invoice(db=self.db, invoice=invoice_obj)
status = await super().melt(quote_id, proofs, change_outputs)
# if payment fails
if MeltQuoteState(status.state) == MeltQuoteState.unpaid:
if melt_quote.state == MeltQuoteState.unpaid:
# remove the melt_id in proofs and set reserved to False
for p in proofs:
p.melt_id = None
p.reserved = False
await update_proof(p, melt_id="", db=self.db)
raise Exception("could not pay invoice.")
elif MeltQuoteState(status.state) == MeltQuoteState.pending:
elif melt_quote.state == MeltQuoteState.pending:
# payment is still pending
return status
logger.debug("Payment is still pending.")
return melt_quote_resp
# invoice was paid successfully
await self.invalidate(proofs)
# update paid status in db
logger.trace(f"Settings invoice {quote_id} to paid.")
await update_lightning_invoice(
logger.trace(f"Quote: {melt_quote_resp}")
fee_paid = melt_quote.amount + melt_quote.fee_paid
if melt_quote.change:
fee_paid -= sum_promises(melt_quote.change)
await update_bolt11_melt_quote(
db=self.db,
id=quote_id,
paid=True,
time_paid=int(time.time()),
preimage=status.payment_preimage,
quote=quote_id,
state=MeltQuoteState.paid,
paid_time=int(time.time()),
payment_preimage=melt_quote.payment_preimage or "",
fee_paid=fee_paid,
)
# handle change and produce proofs
if status.change:
if melt_quote.change:
change_proofs = await self._construct_proofs(
status.change,
change_secrets[: len(status.change)],
change_rs[: len(status.change)],
change_derivation_paths[: len(status.change)],
melt_quote.change,
change_secrets[: len(melt_quote.change)],
change_rs[: len(melt_quote.change)],
change_derivation_paths[: len(melt_quote.change)],
)
logger.debug(f"Received change: {self.unit.str(sum_proofs(change_proofs))}")
return status
return melt_quote_resp
async def check_proof_state(self, proofs) -> PostCheckStateResponse:
return await super().check_proof_state(proofs)

View File

@@ -63,7 +63,7 @@ async def test_db_tables(ledger: Ledger):
"SELECT table_name FROM information_schema.tables WHERE table_schema ="
" 'public';"
)
tables_all: List[Tuple[str]] = tables_res.all()
tables_all: List[Tuple[str]] = tables_res.all() # type: ignore
tables = [t[0] for t in tables_all]
tables_expected = [
"dbversions",
@@ -117,7 +117,7 @@ async def test_db_get_connection(ledger: Ledger):
# @pytest.mark.asyncio
# async def test_db_get_connection_locked(wallet: Wallet, ledger: Ledger):
# invoice = await wallet.request_mint(64)
# mint_quote = await wallet.request_mint(64)
# async def get_connection():
# """This code makes sure that only the error of the second connection is raised (which we check in the assert_err)"""
@@ -129,7 +129,7 @@ async def test_db_get_connection(ledger: Ledger):
# ) as conn2:
# # write something with conn1, we never reach this point if the lock works
# await conn2.execute(
# f"INSERT INTO mint_quotes (quote, amount) VALUES ('{invoice.id}', 100);"
# f"INSERT INTO mint_quotes (quote, amount) VALUES ('{mint_quote.quote}', 100);"
# )
# except Exception as exc:
# # this is expected to raise
@@ -149,28 +149,28 @@ async def test_db_get_connection_lock_row(wallet: Wallet, ledger: Ledger):
if ledger.db.type == db.SQLITE:
pytest.skip("SQLite does not support row locking")
invoice = await wallet.request_mint(64)
mint_quote = await wallet.request_mint(64)
async def get_connection():
"""This code makes sure that only the error of the second connection is raised (which we check in the assert_err)"""
try:
async with ledger.db.get_connection(
lock_table="mint_quotes",
lock_select_statement=f"quote='{invoice.id}'",
lock_select_statement=f"quote='{mint_quote.quote}'",
lock_timeout=0.1,
) as conn1:
await conn1.execute(
f"UPDATE mint_quotes SET amount=100 WHERE quote='{invoice.id}';"
f"UPDATE mint_quotes SET amount=100 WHERE quote='{mint_quote.quote}';"
)
try:
async with ledger.db.get_connection(
lock_table="mint_quotes",
lock_select_statement=f"quote='{invoice.id}'",
lock_select_statement=f"quote='{mint_quote.quote}'",
lock_timeout=0.1,
) as conn2:
# write something with conn1, we never reach this point if the lock works
await conn2.execute(
f"UPDATE mint_quotes SET amount=101 WHERE quote='{invoice.id}';"
f"UPDATE mint_quotes SET amount=101 WHERE quote='{mint_quote.quote}';"
)
except Exception as exc:
# this is expected to raise
@@ -189,9 +189,9 @@ async def test_db_verify_spent_proofs_and_set_pending_race_condition(
wallet: Wallet, ledger: Ledger
):
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
await assert_err_multiple(
@@ -211,9 +211,9 @@ async def test_db_verify_spent_proofs_and_set_pending_delayed_no_race_condition(
wallet: Wallet, ledger: Ledger
):
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
async def delayed_verify_spent_proofs_and_set_pending():
@@ -234,9 +234,9 @@ async def test_db_verify_spent_proofs_and_set_pending_no_race_condition_differen
wallet: Wallet, ledger: Ledger
):
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id, split=[32, 32])
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote, split=[32, 32])
assert wallet.balance == 64
assert len(wallet.proofs) == 2
@@ -251,26 +251,26 @@ async def test_db_get_connection_lock_different_row(wallet: Wallet, ledger: Ledg
if ledger.db.type == db.SQLITE:
pytest.skip("SQLite does not support row locking")
# this should work since we lock two different rows
invoice = await wallet.request_mint(64)
invoice2 = await wallet.request_mint(64)
mint_quote = await wallet.request_mint(64)
mint_quote_2 = await wallet.request_mint(64)
async def get_connection2():
"""This code makes sure that only the error of the second connection is raised (which we check in the assert_err)"""
try:
async with ledger.db.get_connection(
lock_table="mint_quotes",
lock_select_statement=f"quote='{invoice.id}'",
lock_select_statement=f"quote='{mint_quote.quote}'",
lock_timeout=0.1,
):
try:
async with ledger.db.get_connection(
lock_table="mint_quotes",
lock_select_statement=f"quote='{invoice2.id}'",
lock_select_statement=f"quote='{mint_quote_2.quote}'",
lock_timeout=0.1,
) as conn2:
# write something with conn1, this time we should reach this block with postgres
quote = await ledger.crud.get_mint_quote(
quote_id=invoice2.id, db=ledger.db, conn=conn2
quote_id=mint_quote_2.quote, db=ledger.db, conn=conn2
)
assert quote is not None
quote.amount = 100
@@ -294,10 +294,10 @@ async def test_db_get_connection_lock_different_row(wallet: Wallet, ledger: Ledg
@pytest.mark.asyncio
async def test_db_lock_table(wallet: Wallet, ledger: Ledger):
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, id=invoice.id)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
async with ledger.db.connect(lock_table="proofs_pending", lock_timeout=0.1) as conn:

View File

@@ -159,9 +159,9 @@ async def test_api_keyset_keys_old_keyset_id(ledger: Ledger):
reason="settings.debug_mint_only_deprecated is set",
)
async def test_split(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
secrets, rs, derivation_paths = await wallet.generate_n_secrets(2)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
@@ -240,15 +240,14 @@ async def test_mint_quote(ledger: Ledger):
reason="settings.debug_mint_only_deprecated is set",
)
async def test_mint(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
quote_id = invoice.id
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
outputs_payload = [o.dict() for o in outputs]
response = httpx.post(
f"{BASE_URL}/v1/mint/bolt11",
json={"quote": quote_id, "outputs": outputs_payload},
json={"quote": mint_quote.quote, "outputs": outputs_payload},
timeout=None,
)
assert response.status_code == 200, f"{response.url} {response.status_code}"
@@ -273,8 +272,8 @@ async def test_mint(ledger: Ledger, wallet: Wallet):
)
async def test_melt_quote_internal(ledger: Ledger, wallet: Wallet):
# internal invoice
invoice = await wallet.request_mint(64)
request = invoice.bolt11
mint_quote = await wallet.request_mint(64)
request = mint_quote.request
response = httpx.post(
f"{BASE_URL}/v1/melt/quote/bolt11",
json={"unit": "sat", "request": request},
@@ -358,14 +357,14 @@ async def test_melt_quote_external(ledger: Ledger, wallet: Wallet):
)
async def test_melt_internal(ledger: Ledger, wallet: Wallet):
# internal invoice
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
# create invoice to melt to
invoice = await wallet.request_mint(64)
invoice_payment_request = invoice.bolt11
mint_quote = await wallet.request_mint(64)
invoice_payment_request = mint_quote.request
quote = await wallet.melt_quote(invoice_payment_request)
assert quote.amount == 64
@@ -389,7 +388,7 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet):
)
assert response.status_code == 200, f"{response.url} {response.status_code}"
result = response.json()
assert result.get("payment_preimage") is not None
assert result.get("payment_preimage") is None
assert result["paid"] is True
# deserialize the response
@@ -397,7 +396,7 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet):
assert resp_quote.quote == quote.quote
# internal invoice, no preimage, no change
assert resp_quote.payment_preimage == ""
assert resp_quote.payment_preimage is None
assert resp_quote.change == []
assert resp_quote.state == MeltQuoteState.paid.value
@@ -417,9 +416,9 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet):
)
async def test_melt_external(ledger: Ledger, wallet: Wallet):
# internal invoice
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
invoice_dict = get_real_invoice(62)
@@ -493,9 +492,9 @@ async def test_api_check_state(ledger: Ledger):
reason="settings.debug_mint_only_deprecated is set",
)
async def test_api_restore(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
secret_counter = await bump_secret_derivation(
db=wallet.db, keyset_id=wallet.keyset_id, by=0, skip=True

View File

@@ -67,9 +67,9 @@ async def test_api_keyset_keys(ledger: Ledger):
@pytest.mark.asyncio
async def test_split(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(20000, 20001)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
@@ -88,9 +88,9 @@ async def test_split(ledger: Ledger, wallet: Wallet):
@pytest.mark.asyncio
async def test_split_deprecated_with_amount(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(80000, 80001)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
@@ -124,16 +124,15 @@ async def test_api_mint_validation(ledger):
@pytest.mark.asyncio
async def test_mint(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
quote_id = invoice.id
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
outputs_payload = [o.dict() for o in outputs]
response = httpx.post(
f"{BASE_URL}/mint",
json={"outputs": outputs_payload},
params={"hash": quote_id},
params={"hash": mint_quote.quote},
timeout=None,
)
assert response.status_code == 200, f"{response.url} {response.status_code}"
@@ -150,15 +149,15 @@ async def test_mint(ledger: Ledger, wallet: Wallet):
@pytest.mark.asyncio
async def test_melt_internal(ledger: Ledger, wallet: Wallet):
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
# create invoice to melt to
invoice = await wallet.request_mint(64)
mint_quote = await wallet.request_mint(64)
invoice_payment_request = invoice.bolt11
invoice_payment_request = mint_quote.request
quote = await wallet.melt_quote(invoice_payment_request)
assert quote.amount == 64
@@ -182,7 +181,7 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet):
)
assert response.status_code == 200, f"{response.url} {response.status_code}"
result = response.json()
assert result.get("preimage") is not None
assert result.get("preimage") is None
assert result["paid"] is True
@@ -190,14 +189,14 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet):
async def test_melt_internal_no_change_outputs(ledger: Ledger, wallet: Wallet):
# Clients without NUT-08 will not send change outputs
# internal invoice
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
# create invoice to melt to
invoice = await wallet.request_mint(64)
invoice_payment_request = invoice.bolt11
mint_quote = await wallet.request_mint(64)
invoice_payment_request = mint_quote.request
quote = await wallet.melt_quote(invoice_payment_request)
assert quote.amount == 64
assert quote.fee_reserve == 0
@@ -218,7 +217,7 @@ async def test_melt_internal_no_change_outputs(ledger: Ledger, wallet: Wallet):
)
assert response.status_code == 200, f"{response.url} {response.status_code}"
result = response.json()
assert result.get("preimage") is not None
assert result.get("preimage") is None
assert result["paid"] is True
@@ -229,9 +228,9 @@ async def test_melt_internal_no_change_outputs(ledger: Ledger, wallet: Wallet):
)
async def test_melt_external(ledger: Ledger, wallet: Wallet):
# internal invoice
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
# create invoice to melt to
@@ -271,11 +270,11 @@ async def test_melt_external(ledger: Ledger, wallet: Wallet):
@pytest.mark.asyncio
async def test_checkfees(ledger: Ledger, wallet: Wallet):
# internal invoice
invoice = await wallet.request_mint(64)
mint_quote = await wallet.request_mint(64)
response = httpx.post(
f"{BASE_URL}/checkfees",
json={
"pr": invoice.bolt11,
"pr": mint_quote.request,
},
timeout=None,
)
@@ -323,9 +322,9 @@ async def test_api_check_state(ledger: Ledger):
@pytest.mark.asyncio
async def test_api_restore(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
secret_counter = await bump_secret_derivation(
db=wallet.db, keyset_id=wallet.keyset_id, by=0, skip=True

View File

@@ -37,9 +37,9 @@ async def wallet(ledger: Ledger):
@pytest.mark.asyncio
@pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS")
async def test_mint_proofs_pending(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
proofs = wallet.proofs.copy()
proofs_states_before_split = await wallet.check_proof_state(proofs)
@@ -61,26 +61,21 @@ async def test_mint_proofs_pending(wallet: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_mint_quote(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128)
assert invoice is not None
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
mint_quote = await wallet.request_mint(128)
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
assert quote is not None
assert quote.quote == invoice.id
assert quote.amount == 128
assert quote.unit == "sat"
assert not quote.paid
assert quote.checking_id == invoice.payment_hash
# assert quote.paid_time is None
assert quote.created_time
@pytest.mark.asyncio
async def test_mint_quote_state_transitions(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128)
assert invoice is not None
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
mint_quote = await wallet.request_mint(128)
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
assert quote is not None
assert quote.quote == invoice.id
assert quote.unpaid
# set pending again
@@ -129,11 +124,9 @@ async def test_mint_quote_state_transitions(wallet: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_get_mint_quote_by_request(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128)
assert invoice is not None
quote = await ledger.crud.get_mint_quote(request=invoice.bolt11, db=ledger.db)
mint_quote = await wallet.request_mint(128)
quote = await ledger.crud.get_mint_quote(request=mint_quote.request, db=ledger.db)
assert quote is not None
assert quote.quote == invoice.id
assert quote.amount == 128
assert quote.unit == "sat"
assert not quote.paid
@@ -143,10 +136,9 @@ async def test_get_mint_quote_by_request(wallet: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_melt_quote(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128)
assert invoice is not None
mint_quote = await wallet.request_mint(128)
melt_quote = await ledger.melt_quote(
PostMeltQuoteRequest(request=invoice.bolt11, unit="sat")
PostMeltQuoteRequest(request=mint_quote.request, unit="sat")
)
quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db)
assert quote is not None
@@ -154,17 +146,15 @@ async def test_melt_quote(wallet: Wallet, ledger: Ledger):
assert quote.amount == 128
assert quote.unit == "sat"
assert not quote.paid
assert quote.checking_id == invoice.payment_hash
# assert quote.paid_time is None
assert quote.created_time
@pytest.mark.asyncio
async def test_melt_quote_set_pending(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128)
assert invoice is not None
mint_quote = await wallet.request_mint(128)
melt_quote = await ledger.melt_quote(
PostMeltQuoteRequest(request=invoice.bolt11, unit="sat")
PostMeltQuoteRequest(request=mint_quote.request, unit="sat")
)
assert melt_quote is not None
assert melt_quote.state == MeltQuoteState.unpaid.value
@@ -187,10 +177,9 @@ async def test_melt_quote_set_pending(wallet: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_melt_quote_state_transitions(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128)
assert invoice is not None
mint_quote = await wallet.request_mint(128)
melt_quote = await ledger.melt_quote(
PostMeltQuoteRequest(request=invoice.bolt11, unit="sat")
PostMeltQuoteRequest(request=mint_quote.request, unit="sat")
)
quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db)
assert quote is not None
@@ -218,33 +207,36 @@ async def test_melt_quote_state_transitions(wallet: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_mint_quote_set_pending(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128)
assert invoice is not None
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
assert quote is not None
assert quote.unpaid
mint_quote = await wallet.request_mint(128)
mint_quote = await ledger.crud.get_mint_quote(
quote_id=mint_quote.quote, db=ledger.db
)
assert mint_quote is not None
assert mint_quote.unpaid
# pay_if_regtest pays on regtest, get_mint_quote pays on FakeWallet
await pay_if_regtest(invoice.bolt11)
_ = await ledger.get_mint_quote(invoice.id)
await pay_if_regtest(mint_quote.request)
_ = await ledger.get_mint_quote(mint_quote.quote)
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
assert quote is not None
assert quote.paid
previous_state = MintQuoteState.paid
await ledger.db_write._set_mint_quote_pending(quote.quote)
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
assert quote is not None
assert quote.pending
# try to mint while pending
await assert_err(wallet.mint(128, id=invoice.id), "Mint quote already pending.")
await assert_err(
wallet.mint(128, quote_id=mint_quote.quote), "Mint quote already pending."
)
# set unpending
await ledger.db_write._unset_mint_quote_pending(quote.quote, previous_state)
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
assert quote is not None
assert quote.state == previous_state
assert quote.paid
@@ -253,20 +245,19 @@ async def test_mint_quote_set_pending(wallet: Wallet, ledger: Ledger):
# quote.state = MintQuoteState.paid
# await ledger.crud.update_mint_quote(quote=quote, db=ledger.db)
await wallet.mint(quote.amount, id=quote.quote)
await wallet.mint(quote.amount, quote_id=quote.quote)
# check if quote is issued
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
assert quote is not None
assert quote.issued
@pytest.mark.asyncio
async def test_db_events_add_client(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128)
assert invoice is not None
mint_quote = await wallet.request_mint(128)
melt_quote = await ledger.melt_quote(
PostMeltQuoteRequest(request=invoice.bolt11, unit="sat")
PostMeltQuoteRequest(request=mint_quote.request, unit="sat")
)
assert melt_quote is not None
assert melt_quote.state == MeltQuoteState.unpaid.value

View File

@@ -48,9 +48,9 @@ def set_ledger_keyset_fees(
@pytest.mark.asyncio
async def test_get_fees_for_proofs(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, split=[1] * 64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, split=[1] * 64, quote_id=mint_quote.quote)
# two proofs
@@ -105,9 +105,9 @@ async def test_wallet_selection_with_fee(wallet1: Wallet, ledger: Ledger):
for keyset in wallet1.keysets.values():
assert keyset.input_fee_ppk == 100
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
assert sum_proofs(send_proofs) == 10
@@ -123,9 +123,11 @@ async def test_wallet_selection_with_fee(wallet1: Wallet, ledger: Ledger):
async def test_wallet_swap_to_send_with_fee(wallet1: Wallet, ledger: Ledger):
# set fees to 100 ppk
set_ledger_keyset_fees(100, ledger, wallet1)
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id, split=[32, 32]) # make sure we need to swap
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(
64, quote_id=mint_quote.quote, split=[32, 32]
) # make sure we need to swap
# quirk: this should call a `/v1/swap` with the mint but the mint will
# throw an error since the fees are only changed in the `ledger` instance, not in the uvicorn API server
@@ -142,9 +144,9 @@ async def test_wallet_swap_to_send_with_fee(wallet1: Wallet, ledger: Ledger):
async def test_split_with_fees(wallet1: Wallet, ledger: Ledger):
# set fees to 100 ppk
set_ledger_keyset_fees(100, ledger)
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
fees = ledger.get_fees_for_proofs(send_proofs)
@@ -160,9 +162,9 @@ async def test_split_with_fees(wallet1: Wallet, ledger: Ledger):
async def test_split_with_high_fees(wallet1: Wallet, ledger: Ledger):
# set fees to 100 ppk
set_ledger_keyset_fees(1234, ledger)
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
fees = ledger.get_fees_for_proofs(send_proofs)
@@ -178,9 +180,9 @@ async def test_split_with_high_fees(wallet1: Wallet, ledger: Ledger):
async def test_split_not_enough_fees(wallet1: Wallet, ledger: Ledger):
# set fees to 100 ppk
set_ledger_keyset_fees(100, ledger)
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
fees = ledger.get_fees_for_proofs(send_proofs)
@@ -200,14 +202,14 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
set_ledger_keyset_fees(100, ledger, wallet1)
# mint twice so we have enough to pay the second invoice back
invoice = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(128, id=invoice.id)
mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(128, quote_id=mint_quote.quote)
assert wallet1.balance == 128
# create a mint quote so that we can melt to it internally
invoice_to_pay = await wallet1.request_mint(64)
invoice_payment_request = invoice_to_pay.bolt11
invoice_payment_request = invoice_to_pay.request
melt_quote = await ledger.melt_quote(
PostMeltQuoteRequest(request=invoice_payment_request, unit="sat")
@@ -247,9 +249,9 @@ async def test_melt_external_with_fees(wallet1: Wallet, ledger: Ledger):
set_ledger_keyset_fees(100, ledger, wallet1)
# mint twice so we have enough to pay the second invoice back
invoice = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(128, id=invoice.id)
mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(128, quote_id=mint_quote.quote)
assert wallet1.balance == 128
invoice_dict = get_real_invoice(64)

View File

@@ -261,9 +261,9 @@ async def test_startup_fakewallet_pending_quote_unknown(ledger: Ledger):
@pytest.mark.skipif(is_fake, reason="only regtest")
async def test_startup_regtest_pending_quote_pending(wallet: Wallet, ledger: Ledger):
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
# create hodl invoice
@@ -305,9 +305,9 @@ async def test_startup_regtest_pending_quote_pending(wallet: Wallet, ledger: Led
@pytest.mark.skipif(is_fake, reason="only regtest")
async def test_startup_regtest_pending_quote_success(wallet: Wallet, ledger: Ledger):
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
# create hodl invoice
@@ -353,9 +353,9 @@ async def test_startup_regtest_pending_quote_success(wallet: Wallet, ledger: Led
async def test_startup_regtest_pending_quote_failure(wallet: Wallet, ledger: Ledger):
"""Simulate a failure to pay the hodl invoice by canceling it."""
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
# create hodl invoice
@@ -407,9 +407,9 @@ async def test_startup_regtest_pending_quote_unknown(wallet: Wallet, ledger: Led
points to an unknown payment."""
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
# create hodl invoice

View File

@@ -185,9 +185,9 @@ async def test_fakewallet_pending_quote_get_melt_quote_unknown(ledger: Ledger):
@pytest.mark.asyncio
@pytest.mark.skipif(is_regtest, reason="only fake wallet")
async def test_melt_lightning_pay_invoice_settled(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
await wallet.mint(64, quote_id=mint_quote.quote)
# invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
quote_id = (
@@ -205,9 +205,9 @@ async def test_melt_lightning_pay_invoice_settled(ledger: Ledger, wallet: Wallet
@pytest.mark.asyncio
@pytest.mark.skipif(is_regtest, reason="only fake wallet")
async def test_melt_lightning_pay_invoice_failed_failed(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
await wallet.mint(64, quote_id=mint_quote.quote)
# invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
quote_id = (
@@ -254,9 +254,9 @@ async def test_melt_lightning_pay_invoice_failed_failed(ledger: Ledger, wallet:
async def test_melt_lightning_pay_invoice_failed_settled(
ledger: Ledger, wallet: Wallet
):
invoice = await wallet.request_mint(64)
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
await wallet.mint(64, quote_id=mint_quote.quote)
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
quote_id = (
await ledger.melt_quote(
@@ -278,9 +278,9 @@ async def test_melt_lightning_pay_invoice_failed_settled(
async def test_melt_lightning_pay_invoice_failed_pending(
ledger: Ledger, wallet: Wallet
):
invoice = await wallet.request_mint(64)
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
await wallet.mint(64, quote_id=mint_quote.quote)
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
quote_id = (
await ledger.melt_quote(
@@ -303,9 +303,9 @@ async def test_melt_lightning_pay_invoice_exception_exception(
ledger: Ledger, wallet: Wallet
):
"""Simulates the case where pay_invoice and get_payment_status raise an exception (due to network issues for example)."""
invoice = await wallet.request_mint(64)
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
await wallet.mint(64, quote_id=mint_quote.quote)
# invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
quote_id = (
@@ -338,8 +338,8 @@ async def test_melt_lightning_pay_invoice_exception_exception(
async def test_mint_melt_different_units(ledger: Ledger, wallet: Wallet):
"""Mint and melt different units."""
# load the wallet
invoice = await wallet.request_mint(64)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await wallet.mint(64, quote_id=mint_quote.quote)
amount = 32

View File

@@ -38,14 +38,14 @@ async def wallet1(ledger: Ledger):
@pytest.mark.skipif(is_regtest, reason="only works with FakeWallet")
async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
# mint twice so we have enough to pay the second invoice back
invoice = await wallet1.request_mint(128)
await ledger.get_mint_quote(invoice.id)
await wallet1.mint(128, id=invoice.id)
mint_quote = await wallet1.request_mint(128)
await ledger.get_mint_quote(mint_quote.quote)
await wallet1.mint(128, quote_id=mint_quote.quote)
assert wallet1.balance == 128
# create a mint quote so that we can melt to it internally
invoice_to_pay = await wallet1.request_mint(64)
invoice_payment_request = invoice_to_pay.bolt11
mint_quote_to_pay = await wallet1.request_mint(64)
invoice_payment_request = mint_quote_to_pay.request
melt_quote = await ledger.melt_quote(
PostMeltQuoteRequest(request=invoice_payment_request, unit="sat")
@@ -79,9 +79,9 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
@pytest.mark.skipif(is_fake, reason="only works with Regtest")
async def test_melt_external(wallet1: Wallet, ledger: Ledger):
# mint twice so we have enough to pay the second invoice back
invoice = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(128, id=invoice.id)
mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(128, quote_id=mint_quote.quote)
assert wallet1.balance == 128
invoice_dict = get_real_invoice(64)
@@ -119,14 +119,14 @@ async def test_melt_external(wallet1: Wallet, ledger: Ledger):
@pytest.mark.asyncio
@pytest.mark.skipif(is_regtest, reason="only works with FakeWallet")
async def test_mint_internal(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128)
await ledger.get_mint_quote(invoice.id)
mint_quote = await ledger.get_mint_quote(invoice.id)
mint_quote = await wallet1.request_mint(128)
await ledger.get_mint_quote(mint_quote.quote)
mint_quote = await ledger.get_mint_quote(mint_quote.quote)
assert mint_quote.paid, "mint quote should be paid"
if not settings.debug_mint_only_deprecated:
mint_quote_resp = await wallet1.get_mint_quote(invoice.id)
mint_quote_resp = await wallet1.get_mint_quote(mint_quote.quote)
assert (
mint_quote_resp.state == MeltQuoteState.paid.value
), "mint quote should be paid"
@@ -136,14 +136,14 @@ async def test_mint_internal(wallet1: Wallet, ledger: Ledger):
len(output_amounts)
)
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
await ledger.mint(outputs=outputs, quote_id=invoice.id)
await ledger.mint(outputs=outputs, quote_id=mint_quote.quote)
await assert_err(
ledger.mint(outputs=outputs, quote_id=invoice.id),
ledger.mint(outputs=outputs, quote_id=mint_quote.quote),
"outputs have already been signed before.",
)
mint_quote_after_payment = await ledger.get_mint_quote(invoice.id)
mint_quote_after_payment = await ledger.get_mint_quote(mint_quote.quote)
assert mint_quote_after_payment.issued, "mint quote should be issued"
assert mint_quote_after_payment.issued
@@ -164,7 +164,7 @@ async def test_mint_external(wallet1: Wallet, ledger: Ledger):
assert not mint_quote_resp.paid, "mint quote should not be paid"
await assert_err(
wallet1.mint(128, id=quote.quote),
wallet1.mint(128, quote_id=quote.quote),
"quote not paid",
)
@@ -187,9 +187,9 @@ async def test_mint_external(wallet1: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_split(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10)
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(len(send_proofs))
@@ -204,9 +204,9 @@ async def test_split(wallet1: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10, set_reserved=False)
await assert_err(
ledger.swap(proofs=send_proofs, outputs=[]),
@@ -216,9 +216,9 @@ async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
keep_proofs, send_proofs = await wallet1.swap_to_send(
wallet1.proofs, 10, set_reserved=False
@@ -245,9 +245,9 @@ async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledge
@pytest.mark.asyncio
async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(128, id=invoice.id)
mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(128, quote_id=mint_quote.quote)
inputs = wallet1.proofs
@@ -269,9 +269,9 @@ async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledge
@pytest.mark.asyncio
async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(128, split=[64, 64], id=invoice.id)
mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(128, split=[64, 64], quote_id=mint_quote.quote)
inputs1 = wallet1.proofs[:1]
inputs2 = wallet1.proofs[1:]
@@ -304,30 +304,30 @@ async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_mint_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11)
mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(mint_quote.request)
output_amounts = [128]
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
len(output_amounts)
)
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
await ledger.mint(outputs=outputs, quote_id=invoice.id)
await ledger.mint(outputs=outputs, quote_id=mint_quote.quote)
# now try to mint with the same outputs again
invoice2 = await wallet1.request_mint(128)
await pay_if_regtest(invoice2.bolt11)
mint_quote_2 = await wallet1.request_mint(128)
await pay_if_regtest(mint_quote_2.request)
await assert_err(
ledger.mint(outputs=outputs, quote_id=invoice2.id),
ledger.mint(outputs=outputs, quote_id=mint_quote_2.quote),
"outputs have already been signed before.",
)
@pytest.mark.asyncio
async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(130)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(130, id=invoice.id)
mint_quote = await wallet1.request_mint(130)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(130, quote_id=mint_quote.quote)
output_amounts = [128]
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
@@ -336,9 +336,9 @@ async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
# we use the outputs once for minting
invoice2 = await wallet1.request_mint(128)
await pay_if_regtest(invoice2.bolt11)
await ledger.mint(outputs=outputs, quote_id=invoice2.id)
mint_quote_2 = await wallet1.request_mint(128)
await pay_if_regtest(mint_quote_2.request)
await ledger.mint(outputs=outputs, quote_id=mint_quote_2.quote)
# use the same outputs for melting
mint_quote = await ledger.mint_quote(PostMintQuoteRequest(unit="sat", amount=128))
@@ -353,9 +353,9 @@ async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_melt_with_less_inputs_than_invoice(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(32)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(32, id=invoice.id)
mint_quote = await wallet1.request_mint(32)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(32, quote_id=mint_quote.quote)
# outputs for fee return
output_amounts = [1, 1, 1, 1]
@@ -382,9 +382,9 @@ async def test_melt_with_less_inputs_than_invoice(wallet1: Wallet, ledger: Ledge
@pytest.mark.asyncio
async def test_melt_with_more_inputs_than_invoice(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(130)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(130, split=[64, 64, 2], id=invoice.id)
mint_quote = await wallet1.request_mint(130)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(130, split=[64, 64, 2], quote_id=mint_quote.quote)
# outputs for fee return
output_amounts = [1, 1, 1, 1]
@@ -414,9 +414,9 @@ async def test_melt_with_more_inputs_than_invoice(wallet1: Wallet, ledger: Ledge
@pytest.mark.asyncio
async def test_check_proof_state(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10)
@@ -427,13 +427,13 @@ async def test_check_proof_state(wallet1: Wallet, ledger: Ledger):
# TODO: test keeps running forever, needs to be fixed
# @pytest.mark.asyncio
# async def test_websocket_quote_updates(wallet1: Wallet, ledger: Ledger):
# invoice = await wallet1.request_mint(64)
# mint_quote = await wallet1.request_mint(64)
# ws = websocket.create_connection(
# f"ws://localhost:{SERVER_PORT}/v1/quote/{invoice.id}"
# )
# await asyncio.sleep(0.1)
# await pay_if_regtest(invoice.bolt11)
# await wallet1.mint(64, id=invoice.id)
# await pay_if_regtest(mint_quote.request)
# await wallet1.mint(64, quote_id=mint_quote.quote)
# await asyncio.sleep(0.1)
# data = str(ws.recv())
# ws.close()

View File

@@ -274,9 +274,9 @@ async def test_lightning_pay_invoice_pending_failure(ledger: Ledger):
@pytest.mark.skipif(is_fake, reason="only regtest")
async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
# create hodl invoice

View File

@@ -8,7 +8,12 @@ from cashu.core.base import MintQuoteState, Proof
from cashu.core.errors import CashuError, KeysetNotFoundError
from cashu.core.helpers import sum_proofs
from cashu.core.settings import settings
from cashu.wallet.crud import get_keysets, get_lightning_invoice, get_proofs
from cashu.wallet.crud import (
get_bolt11_melt_quote,
get_bolt11_mint_quote,
get_keysets,
get_proofs,
)
from cashu.wallet.wallet import Wallet
from cashu.wallet.wallet import Wallet as Wallet1
from cashu.wallet.wallet import Wallet as Wallet2
@@ -160,44 +165,41 @@ async def test_get_keysets(wallet1: Wallet):
@pytest.mark.asyncio
async def test_request_mint(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
assert invoice.payment_hash
mint_quote = await wallet1.request_mint(64)
assert mint_quote.request
@pytest.mark.asyncio
async def test_mint(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
if not settings.debug_mint_only_deprecated:
quote_resp = await wallet1.get_mint_quote(invoice.id)
assert quote_resp.request == invoice.bolt11
quote_resp = await wallet1.get_mint_quote(mint_quote.quote)
assert quote_resp.request == mint_quote.request
assert quote_resp.state == MintQuoteState.paid.value
expected_proof_amounts = wallet1.split_wallet_state(64)
await wallet1.mint(64, id=invoice.id)
await wallet1.mint(64, quote_id=mint_quote.quote)
assert wallet1.balance == 64
# verify that proofs in proofs_used db have the same mint_id as the invoice in the db
assert invoice.payment_hash
invoice_db = await get_lightning_invoice(
db=wallet1.db, payment_hash=invoice.payment_hash, out=False
)
assert invoice_db
mint_quote = await get_bolt11_mint_quote(db=wallet1.db, quote=mint_quote.quote)
assert mint_quote
proofs_minted = await get_proofs(
db=wallet1.db, mint_id=invoice_db.id, table="proofs"
db=wallet1.db, mint_id=mint_quote.quote, table="proofs"
)
assert len(proofs_minted) == len(expected_proof_amounts)
assert all([p.amount in expected_proof_amounts for p in proofs_minted])
assert all([p.mint_id == invoice.id for p in proofs_minted])
assert all([p.mint_id == mint_quote.quote for p in proofs_minted])
@pytest.mark.asyncio
async def test_mint_amounts(wallet1: Wallet):
"""Mint predefined amounts"""
amts = [1, 1, 1, 2, 2, 4, 16]
invoice = await wallet1.request_mint(sum(amts))
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(amount=sum(amts), split=amts, id=invoice.id)
mint_quote = await wallet1.request_mint(sum(amts))
await pay_if_regtest(mint_quote.request)
await wallet1.mint(amount=sum(amts), split=amts, quote_id=mint_quote.quote)
assert wallet1.balance == 27
assert wallet1.proof_amounts == amts
@@ -207,9 +209,9 @@ async def test_mint_amounts_wrong_sum(wallet1: Wallet):
"""Mint predefined amounts"""
amts = [1, 1, 1, 2, 2, 4, 16]
invoice = await wallet1.request_mint(sum(amts))
mint_quote = await wallet1.request_mint(sum(amts))
await assert_err(
wallet1.mint(amount=sum(amts) + 1, split=amts, id=invoice.id),
wallet1.mint(amount=sum(amts) + 1, split=amts, quote_id=mint_quote.quote),
"split must sum to amount",
)
@@ -218,18 +220,18 @@ async def test_mint_amounts_wrong_sum(wallet1: Wallet):
async def test_mint_amounts_wrong_order(wallet1: Wallet):
"""Mint amount that is not part in 2^n"""
amts = [1, 2, 3]
invoice = await wallet1.request_mint(sum(amts))
mint_quote = await wallet1.request_mint(sum(amts))
await assert_err(
wallet1.mint(amount=sum(amts), split=[1, 2, 3], id=invoice.id),
wallet1.mint(amount=sum(amts), split=[1, 2, 3], quote_id=mint_quote.quote),
f"Can only mint amounts with 2^n up to {2**settings.max_order}.",
)
@pytest.mark.asyncio
async def test_split(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
assert wallet1.balance == 64
# the outputs we keep that we expect after the split
expected_proof_amounts = wallet1.split_wallet_state(44)
@@ -247,9 +249,9 @@ async def test_split(wallet1: Wallet):
@pytest.mark.asyncio
async def test_swap_to_send(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
assert wallet1.balance == 64
# this will select 32 sats and them (nothing to keep)
@@ -269,9 +271,9 @@ async def test_swap_to_send(wallet1: Wallet):
@pytest.mark.asyncio
async def test_split_more_than_balance(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
await assert_err(
wallet1.split(wallet1.proofs, 128),
# "Mint Error: inputs do not have same amount as outputs",
@@ -283,22 +285,19 @@ async def test_split_more_than_balance(wallet1: Wallet):
@pytest.mark.asyncio
async def test_melt(wallet1: Wallet):
# mint twice so we have enough to pay the second invoice back
topup_invoice = await wallet1.request_mint(128)
await pay_if_regtest(topup_invoice.bolt11)
await wallet1.mint(128, id=topup_invoice.id)
topup_mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(topup_mint_quote.request)
await wallet1.mint(128, quote_id=topup_mint_quote.quote)
assert wallet1.balance == 128
invoice_payment_request = ""
invoice_payment_hash = ""
if is_regtest:
invoice_dict = get_real_invoice(64)
invoice_payment_hash = str(invoice_dict["r_hash"])
invoice_payment_request = invoice_dict["payment_request"]
if is_fake:
invoice = await wallet1.request_mint(64)
invoice_payment_hash = str(invoice.payment_hash)
invoice_payment_request = invoice.bolt11
mint_quote = await wallet1.request_mint(64)
invoice_payment_request = mint_quote.request
quote = await wallet1.melt_quote(invoice_payment_request)
total_amount = quote.amount + quote.fee_reserve
@@ -334,17 +333,16 @@ async def test_melt(wallet1: Wallet):
assert melt_response.change[0].id == send_proofs[0].id, "Wrong keyset returned"
# verify that proofs in proofs_used db have the same melt_id as the invoice in the db
assert invoice_payment_hash, "No payment hash in invoice"
invoice_db = await get_lightning_invoice(
db=wallet1.db, payment_hash=invoice_payment_hash, out=True
melt_quote_db = await get_bolt11_melt_quote(
db=wallet1.db, request=invoice_payment_request
)
assert invoice_db, "No invoice in db"
assert melt_quote_db, "No invoice in db"
proofs_used = await get_proofs(
db=wallet1.db, melt_id=invoice_db.id, table="proofs_used"
db=wallet1.db, melt_id=melt_quote_db.quote, table="proofs_used"
)
assert len(proofs_used) == len(send_proofs), "Not all proofs used"
assert all([p.melt_id == invoice_db.id for p in proofs_used]), "Wrong melt_id"
assert all([p.melt_id == melt_quote_db.quote for p in proofs_used]), "Wrong melt_id"
# the payment was without fees so we need to remove it from the total amount
assert wallet1.balance == 128 - (total_amount - quote.fee_reserve), "Wrong balance"
@@ -353,9 +351,9 @@ async def test_melt(wallet1: Wallet):
@pytest.mark.asyncio
async def test_swap_to_send_more_than_balance(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
await assert_err(
wallet1.swap_to_send(wallet1.proofs, 128, set_reserved=True),
"balance too low.",
@@ -366,9 +364,9 @@ async def test_swap_to_send_more_than_balance(wallet1: Wallet):
@pytest.mark.asyncio
async def test_double_spend(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
doublespend = await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
doublespend = await wallet1.mint(64, quote_id=mint_quote.quote)
await wallet1.split(wallet1.proofs, 20)
await assert_err(
wallet1.split(doublespend, 20),
@@ -380,9 +378,9 @@ async def test_double_spend(wallet1: Wallet):
@pytest.mark.asyncio
async def test_duplicate_proofs_double_spent(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
doublespend = await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
doublespend = await wallet1.mint(64, quote_id=mint_quote.quote)
await assert_err(
wallet1.split(wallet1.proofs + doublespend, 20),
"Mint Error: duplicate proofs.",
@@ -394,9 +392,9 @@ async def test_duplicate_proofs_double_spent(wallet1: Wallet):
@pytest.mark.asyncio
@pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS")
async def test_split_race_condition(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
# run two splits in parallel
import asyncio
@@ -411,9 +409,9 @@ async def test_split_race_condition(wallet1: Wallet):
@pytest.mark.asyncio
async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
_, spendable_proofs = await wallet1.swap_to_send(
wallet1.proofs, 32, set_reserved=True
)
@@ -430,9 +428,9 @@ async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet):
@pytest.mark.asyncio
async def test_invalidate_all_proofs(wallet1: Wallet):
"""Try to invalidate proofs that have not been spent yet. Should not work!"""
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
await wallet1.invalidate(wallet1.proofs)
assert wallet1.balance == 0
@@ -440,18 +438,18 @@ async def test_invalidate_all_proofs(wallet1: Wallet):
@pytest.mark.asyncio
async def test_invalidate_unspent_proofs_with_checking(wallet1: Wallet):
"""Try to invalidate proofs that have not been spent yet but force no check."""
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
await wallet1.invalidate(wallet1.proofs, check_spendable=True)
assert wallet1.balance == 64
@pytest.mark.asyncio
async def test_split_invalid_amount(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
await assert_err(
wallet1.split(wallet1.proofs, -1),
"amount can't be negative",
@@ -460,9 +458,9 @@ async def test_split_invalid_amount(wallet1: Wallet):
@pytest.mark.asyncio
async def test_token_state(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
assert wallet1.balance == 64
resp = await wallet1.check_proof_state(wallet1.proofs)
assert resp.states[0].state.value == "UNSPENT"

View File

@@ -33,12 +33,14 @@ async def test_invoice(wallet: Wallet):
while state.pending:
print("checking invoice state")
response2 = client.get(
f"/lightning/invoice_state?payment_hash={invoice_response.checking_id}"
f"/lightning/invoice_state?payment_request={invoice_response.payment_request}"
)
state = PaymentStatus.parse_obj(response2.json())
await asyncio.sleep(0.1)
print("state:", state)
print("paid")
await wallet.load_proofs()
assert wallet.available_balance >= 100
@pytest.mark.skipif(is_regtest, reason="regtest")
@@ -175,7 +177,7 @@ async def test_flow(wallet: Wallet):
while state.pending:
print("checking invoice state")
response2 = client.get(
f"/lightning/invoice_state?payment_hash={invoice_response.checking_id}"
f"/lightning/invoice_state?payment_request={invoice_response.payment_request}"
)
state = PaymentStatus.parse_obj(response2.json())
await asyncio.sleep(0.1)

View File

@@ -32,6 +32,10 @@ def get_invoice_from_invoices_command(output: str) -> dict[str, str]:
removed_empty_and_hiphens = [
value for value in splitted if value and not value.startswith("-----")
]
# filter only lines that have ": " in them
removed_empty_and_hiphens = [
value for value in removed_empty_and_hiphens if ": " in value
]
dict_output = {
f"{value.split(': ')[0]}": value.split(": ")[1]
for value in removed_empty_and_hiphens
@@ -41,7 +45,8 @@ def get_invoice_from_invoices_command(output: str) -> dict[str, str]:
async def reset_invoices(wallet: Wallet):
await wallet.db.execute("DELETE FROM invoices")
await wallet.db.execute("DELETE FROM bolt11_melt_quotes")
await wallet.db.execute("DELETE FROM bolt11_mint_quotes")
async def init_wallet():
@@ -204,8 +209,8 @@ def test_invoices_with_minting(cli_prefix):
# arrange
wallet1 = asyncio.run(init_wallet())
asyncio.run(reset_invoices(wallet=wallet1))
invoice = asyncio.run(wallet1.request_mint(64))
asyncio.run(pay_if_regtest(invoice.bolt11))
mint_quote = asyncio.run(wallet1.request_mint(64))
asyncio.run(pay_if_regtest(mint_quote.request))
# act
runner = CliRunner()
result = runner.invoke(
@@ -217,18 +222,14 @@ def test_invoices_with_minting(cli_prefix):
print("INVOICES --mint")
assert result.exception is None
assert result.exit_code == 0
assert "No invoices found." not in result.output
assert "ID" in result.output
assert "Paid" in result.output
assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id
assert get_invoice_from_invoices_command(result.output)["Paid"] == "True"
assert "Received 64 sat" in result.output
def test_invoices_without_minting(cli_prefix):
# arrange
wallet1 = asyncio.run(init_wallet())
asyncio.run(reset_invoices(wallet=wallet1))
invoice = asyncio.run(wallet1.request_mint(64))
mint_quote = asyncio.run(wallet1.request_mint(64))
# act
runner = CliRunner()
@@ -243,9 +244,11 @@ def test_invoices_without_minting(cli_prefix):
assert result.exit_code == 0
assert "No invoices found." not in result.output
assert "ID" in result.output
assert "Paid" in result.output
assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id
assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid)
assert "State" in result.output
assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote
assert get_invoice_from_invoices_command(result.output)["State"] == str(
mint_quote.state
)
@pytest.mark.skipif(not is_fake, reason="only on fakewallet")
@@ -259,11 +262,11 @@ def test_invoices_with_onlypaid_option(cli_prefix):
runner = CliRunner()
result = runner.invoke(
cli,
[*cli_prefix, "invoices", "--only-paid", "--mint"],
[*cli_prefix, "invoices", "--only-paid"],
)
# assert
print("INVOICES --only-paid --mint")
print("INVOICES --only-paid")
assert result.exception is None
assert result.exit_code == 0
assert "No invoices found." in result.output
@@ -314,7 +317,7 @@ def test_invoices_with_onlyunpaid_option_without_minting(cli_prefix):
# arrange
wallet1 = asyncio.run(init_wallet())
asyncio.run(reset_invoices(wallet=wallet1))
invoice = asyncio.run(wallet1.request_mint(64))
mint_quote = asyncio.run(wallet1.request_mint(64))
# act
runner = CliRunner()
@@ -329,9 +332,11 @@ def test_invoices_with_onlyunpaid_option_without_minting(cli_prefix):
assert result.exit_code == 0
assert "No invoices found." not in result.output
assert "ID" in result.output
assert "Paid" in result.output
assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id
assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid)
assert "State" in result.output
assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote
assert get_invoice_from_invoices_command(result.output)["State"] == str(
mint_quote.state
)
def test_invoices_with_both_onlypaid_and_onlyunpaid_options(cli_prefix):
@@ -374,7 +379,7 @@ def test_invoices_with_pending_option_without_minting(cli_prefix):
# arrange
wallet1 = asyncio.run(init_wallet())
asyncio.run(reset_invoices(wallet=wallet1))
invoice = asyncio.run(wallet1.request_mint(64))
mint_quote = asyncio.run(wallet1.request_mint(64))
# act
runner = CliRunner()
@@ -389,9 +394,11 @@ def test_invoices_with_pending_option_without_minting(cli_prefix):
assert result.exit_code == 0
assert "No invoices found." not in result.output
assert "ID" in result.output
assert "Paid" in result.output
assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id
assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid)
assert "State" in result.output
assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote
assert get_invoice_from_invoices_command(result.output)["State"] == str(
mint_quote.state
)
def test_wallets(cli_prefix):

View File

@@ -57,9 +57,9 @@ async def wallet2():
@pytest.mark.asyncio
async def test_create_htlc_secret(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
secret = await wallet1.create_htlc_lock(preimage=preimage)
@@ -68,9 +68,9 @@ async def test_create_htlc_secret(wallet1: Wallet):
@pytest.mark.asyncio
async def test_htlc_split(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
secret = await wallet1.create_htlc_lock(preimage=preimage)
@@ -81,9 +81,9 @@ async def test_htlc_split(wallet1: Wallet, wallet2: Wallet):
@pytest.mark.asyncio
async def test_htlc_redeem_with_preimage(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
secret = await wallet1.create_htlc_lock(preimage=preimage)
@@ -95,9 +95,9 @@ async def test_htlc_redeem_with_preimage(wallet1: Wallet, wallet2: Wallet):
@pytest.mark.asyncio
async def test_htlc_redeem_with_wrong_preimage(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
secret = await wallet1.create_htlc_lock(
@@ -113,9 +113,9 @@ async def test_htlc_redeem_with_wrong_preimage(wallet1: Wallet, wallet2: Wallet)
@pytest.mark.asyncio
async def test_htlc_redeem_with_no_signature(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
@@ -133,9 +133,9 @@ async def test_htlc_redeem_with_no_signature(wallet1: Wallet, wallet2: Wallet):
@pytest.mark.asyncio
async def test_htlc_redeem_with_wrong_signature(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
@@ -157,9 +157,9 @@ async def test_htlc_redeem_with_wrong_signature(wallet1: Wallet, wallet2: Wallet
@pytest.mark.asyncio
async def test_htlc_redeem_with_correct_signature(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
@@ -177,9 +177,9 @@ async def test_htlc_redeem_with_correct_signature(wallet1: Wallet, wallet2: Wall
@pytest.mark.asyncio
async def test_htlc_redeem_with_2_of_1_signatures(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
@@ -201,9 +201,9 @@ async def test_htlc_redeem_with_2_of_1_signatures(wallet1: Wallet, wallet2: Wall
@pytest.mark.asyncio
async def test_htlc_redeem_with_2_of_2_signatures(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
@@ -227,9 +227,9 @@ async def test_htlc_redeem_with_2_of_2_signatures(wallet1: Wallet, wallet2: Wall
async def test_htlc_redeem_with_2_of_2_signatures_with_duplicate_pubkeys(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = pubkey_wallet1
@@ -256,9 +256,9 @@ async def test_htlc_redeem_with_2_of_2_signatures_with_duplicate_pubkeys(
async def test_htlc_redeem_with_3_of_3_signatures_but_only_2_provided(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
@@ -285,9 +285,9 @@ async def test_htlc_redeem_with_3_of_3_signatures_but_only_2_provided(
async def test_htlc_redeem_with_2_of_3_signatures_with_2_valid_and_1_invalid_provided(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
@@ -316,9 +316,9 @@ async def test_htlc_redeem_with_2_of_3_signatures_with_2_valid_and_1_invalid_pro
async def test_htlc_redeem_with_3_of_3_signatures_with_2_valid_and_1_invalid_provided(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
@@ -349,9 +349,9 @@ async def test_htlc_redeem_with_3_of_3_signatures_with_2_valid_and_1_invalid_pro
async def test_htlc_redeem_hashlock_wrong_signature_timelock_correct_signature(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
@@ -383,9 +383,9 @@ async def test_htlc_redeem_hashlock_wrong_signature_timelock_correct_signature(
async def test_htlc_redeem_hashlock_wrong_signature_timelock_wrong_signature(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()

View File

@@ -81,8 +81,7 @@ async def test_check_invoice_internal(wallet: LightningWallet):
# fill wallet
invoice = await wallet.create_invoice(64)
assert invoice.payment_request
assert invoice.checking_id
status = await wallet.get_invoice_status(invoice.checking_id)
status = await wallet.get_invoice_status(invoice.payment_request)
assert status.settled
@@ -92,11 +91,10 @@ async def test_check_invoice_external(wallet: LightningWallet):
# fill wallet
invoice = await wallet.create_invoice(64)
assert invoice.payment_request
assert invoice.checking_id
status = await wallet.get_invoice_status(invoice.checking_id)
status = await wallet.get_invoice_status(invoice.payment_request)
assert not status.settled
await pay_if_regtest(invoice.payment_request)
status = await wallet.get_invoice_status(invoice.checking_id)
status = await wallet.get_invoice_status(invoice.payment_request)
assert status.settled
@@ -106,8 +104,7 @@ async def test_pay_invoice_internal(wallet: LightningWallet):
# fill wallet
invoice = await wallet.create_invoice(64)
assert invoice.payment_request
assert invoice.checking_id
await wallet.get_invoice_status(invoice.checking_id)
await wallet.get_invoice_status(invoice.payment_request)
assert wallet.available_balance >= 64
# pay invoice
@@ -118,8 +115,7 @@ async def test_pay_invoice_internal(wallet: LightningWallet):
assert status.settled
# check payment
assert invoice2.checking_id
status = await wallet.get_payment_status(invoice2.checking_id)
status = await wallet.get_payment_status(invoice2.payment_request)
assert status.settled
@@ -129,9 +125,8 @@ async def test_pay_invoice_external(wallet: LightningWallet):
# fill wallet
invoice = await wallet.create_invoice(64)
assert invoice.payment_request
assert invoice.checking_id
await pay_if_regtest(invoice.payment_request)
status = await wallet.get_invoice_status(invoice.checking_id)
status = await wallet.get_invoice_status(invoice.payment_request)
assert status.settled
assert wallet.available_balance >= 64
@@ -141,7 +136,5 @@ async def test_pay_invoice_external(wallet: LightningWallet):
assert status.settled
# check payment
assert status.checking_id
status = await wallet.get_payment_status(status.checking_id)
# check payment)
assert status.settled

View File

@@ -59,18 +59,18 @@ async def wallet2():
@pytest.mark.asyncio
async def test_create_p2pk_pubkey(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey = await wallet1.create_p2pk_pubkey()
PublicKey(bytes.fromhex(pubkey), raw=True)
@pytest.mark.asyncio
async def test_p2pk(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
# p2pk test
secret_lock = await wallet1.create_p2pk_lock(pubkey_wallet2) # sender side
@@ -92,9 +92,9 @@ async def test_p2pk(wallet1: Wallet, wallet2: Wallet):
@pytest.mark.asyncio
async def test_p2pk_sig_all(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
# p2pk test
secret_lock = await wallet1.create_p2pk_lock(
@@ -108,9 +108,9 @@ async def test_p2pk_sig_all(wallet1: Wallet, wallet2: Wallet):
@pytest.mark.asyncio
async def test_p2pk_receive_with_wrong_private_key(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
# sender side
secret_lock = await wallet1.create_p2pk_lock(pubkey_wallet2) # sender side
@@ -129,9 +129,9 @@ async def test_p2pk_receive_with_wrong_private_key(wallet1: Wallet, wallet2: Wal
async def test_p2pk_short_locktime_receive_with_wrong_private_key(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
# sender side
secret_lock = await wallet1.create_p2pk_lock(
@@ -155,9 +155,9 @@ async def test_p2pk_short_locktime_receive_with_wrong_private_key(
@pytest.mark.asyncio
async def test_p2pk_locktime_with_refund_pubkey(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
# sender side
garbage_pubkey = PrivateKey().pubkey
@@ -184,9 +184,9 @@ async def test_p2pk_locktime_with_refund_pubkey(wallet1: Wallet, wallet2: Wallet
@pytest.mark.asyncio
async def test_p2pk_locktime_with_wrong_refund_pubkey(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
await wallet2.create_p2pk_pubkey() # receiver side
# sender side
garbage_pubkey = PrivateKey().pubkey
@@ -220,9 +220,9 @@ async def test_p2pk_locktime_with_wrong_refund_pubkey(wallet1: Wallet, wallet2:
async def test_p2pk_locktime_with_second_refund_pubkey(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() # receiver side
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
# sender side
@@ -252,9 +252,9 @@ async def test_p2pk_locktime_with_second_refund_pubkey(
@pytest.mark.asyncio
async def test_p2pk_multisig_2_of_2(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
assert pubkey_wallet1 != pubkey_wallet2
@@ -274,9 +274,9 @@ async def test_p2pk_multisig_2_of_2(wallet1: Wallet, wallet2: Wallet):
@pytest.mark.asyncio
async def test_p2pk_multisig_duplicate_signature(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
assert pubkey_wallet1 != pubkey_wallet2
@@ -298,9 +298,9 @@ async def test_p2pk_multisig_duplicate_signature(wallet1: Wallet, wallet2: Walle
@pytest.mark.asyncio
async def test_p2pk_multisig_quorum_not_met_1_of_2(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
assert pubkey_wallet1 != pubkey_wallet2
@@ -319,9 +319,9 @@ async def test_p2pk_multisig_quorum_not_met_1_of_2(wallet1: Wallet, wallet2: Wal
@pytest.mark.asyncio
async def test_p2pk_multisig_quorum_not_met_2_of_3(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
assert pubkey_wallet1 != pubkey_wallet2
@@ -344,9 +344,9 @@ async def test_p2pk_multisig_quorum_not_met_2_of_3(wallet1: Wallet, wallet2: Wal
@pytest.mark.asyncio
async def test_p2pk_multisig_with_duplicate_publickey(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
# p2pk test
secret_lock = await wallet1.create_p2pk_lock(
@@ -362,9 +362,9 @@ async def test_p2pk_multisig_with_duplicate_publickey(wallet1: Wallet, wallet2:
async def test_p2pk_multisig_with_wrong_first_private_key(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, quote_id=mint_quote.quote)
await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
wrong_pubklic_key = PrivateKey().pubkey

View File

@@ -32,9 +32,9 @@ async def wallet():
@pytest.mark.skipif(is_fake, reason="only regtest")
async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
# create hodl invoice
@@ -70,9 +70,9 @@ async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
@pytest.mark.skipif(is_fake, reason="only regtest")
async def test_regtest_failed_quote(wallet: Wallet, ledger: Ledger):
# fill wallet
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
assert wallet.balance == 64
# create hodl invoice

View File

@@ -40,9 +40,9 @@ async def test_regtest_pay_mpp(wallet: Wallet, ledger: Ledger):
assert wallet.mint_info.supports_mpp("bolt11", wallet.unit)
# top up wallet twice so we have enough for two payments
topup_invoice = await wallet.request_mint(128)
await pay_if_regtest(topup_invoice.bolt11)
proofs1 = await wallet.mint(128, id=topup_invoice.id)
topup_mint_quote = await wallet.request_mint(128)
await pay_if_regtest(topup_mint_quote.request)
proofs1 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
assert wallet.balance == 128
# this is the invoice we want to pay in two parts
@@ -95,19 +95,19 @@ async def test_regtest_pay_mpp_incomplete_payment(wallet: Wallet, ledger: Ledger
assert wallet.mint_info.supports_mpp("bolt11", wallet.unit)
# top up wallet twice so we have enough for three payments
topup_invoice = await wallet.request_mint(128)
await pay_if_regtest(topup_invoice.bolt11)
proofs1 = await wallet.mint(128, id=topup_invoice.id)
topup_mint_quote = await wallet.request_mint(128)
await pay_if_regtest(topup_mint_quote.request)
proofs1 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
assert wallet.balance == 128
topup_invoice = await wallet.request_mint(128)
await pay_if_regtest(topup_invoice.bolt11)
proofs2 = await wallet.mint(128, id=topup_invoice.id)
topup_mint_quote = await wallet.request_mint(128)
await pay_if_regtest(topup_mint_quote.request)
proofs2 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
assert wallet.balance == 256
topup_invoice = await wallet.request_mint(128)
await pay_if_regtest(topup_invoice.bolt11)
proofs3 = await wallet.mint(128, id=topup_invoice.id)
topup_mint_quote = await wallet.request_mint(128)
await pay_if_regtest(topup_mint_quote.request)
proofs3 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
assert wallet.balance == 384
# this is the invoice we want to pay in two parts

View File

@@ -156,9 +156,9 @@ async def test_generate_secrets_from_to(wallet3: Wallet):
@pytest.mark.asyncio
async def test_restore_wallet_after_mint(wallet3: Wallet):
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(64, id=invoice.id)
mint_quote = await wallet3.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet3.mint(64, quote_id=mint_quote.quote)
assert wallet3.balance == 64
await reset_wallet_db(wallet3)
await wallet3.load_proofs()
@@ -192,9 +192,9 @@ async def test_restore_wallet_after_swap_to_send(wallet3: Wallet):
)
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(64, id=invoice.id)
mint_quote = await wallet3.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet3.mint(64, quote_id=mint_quote.quote)
assert wallet3.balance == 64
_, spendable_proofs = await wallet3.swap_to_send(
@@ -217,9 +217,9 @@ async def test_restore_wallet_after_send_and_receive(wallet3: Wallet, wallet2: W
"hello rug want adapt talent together lunar method bean expose beef position"
)
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(64, id=invoice.id)
mint_quote = await wallet3.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet3.mint(64, quote_id=mint_quote.quote)
assert wallet3.balance == 64
_, spendable_proofs = await wallet3.swap_to_send(
@@ -260,9 +260,9 @@ async def test_restore_wallet_after_send_and_self_receive(wallet3: Wallet):
)
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(64, id=invoice.id)
mint_quote = await wallet3.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet3.mint(64, quote_id=mint_quote.quote)
assert wallet3.balance == 64
_, spendable_proofs = await wallet3.swap_to_send(
@@ -289,9 +289,9 @@ async def test_restore_wallet_after_send_twice(
wallet3.private_key = PrivateKey()
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(2)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(2, id=invoice.id)
mint_quote = await wallet3.request_mint(2)
await pay_if_regtest(mint_quote.request)
await wallet3.mint(2, quote_id=mint_quote.quote)
box.add(wallet3.proofs)
assert wallet3.balance == 2
@@ -348,9 +348,9 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value(
)
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(64, id=invoice.id)
mint_quote = await wallet3.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet3.mint(64, quote_id=mint_quote.quote)
box.add(wallet3.proofs)
assert wallet3.balance == 64

View File

@@ -44,10 +44,10 @@ async def test_wallet_subscription_mint(wallet: Wallet):
nonlocal triggered, msg_stack
triggered = True
msg_stack.append(msg)
asyncio.run(wallet.mint(int(invoice.amount), id=invoice.id))
asyncio.run(wallet.mint(int(mint_quote.amount), quote_id=mint_quote.quote))
invoice, sub = await wallet.request_mint_with_callback(128, callback=callback)
await pay_if_regtest(invoice.bolt11)
mint_quote, sub = await wallet.request_mint_with_callback(128, callback=callback)
await pay_if_regtest(mint_quote.request)
wait = settings.fakewallet_delay_incoming_payment or 2
await asyncio.sleep(wait + 2)
@@ -66,9 +66,9 @@ async def test_wallet_subscription_swap(wallet: Wallet):
if not wallet.mint_info.supports_nut(WEBSOCKETS_NUT):
pytest.skip("No websocket support")
invoice = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
mint_quote = await wallet.request_mint(64)
await pay_if_regtest(mint_quote.request)
await wallet.mint(64, quote_id=mint_quote.quote)
triggered = False
msg_stack: list[JSONRPCNotficationParams] = []