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 base64
import json import json
import math import math
import time
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum
@@ -260,20 +261,7 @@ class BlindedSignature(BaseModel):
) )
# ------- LIGHTNING INVOICE ------- # ------- Quotes -------
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] = ""
class MeltQuoteState(Enum): class MeltQuoteState(Enum):
@@ -297,9 +285,10 @@ class MeltQuote(LedgerEvent):
created_time: Union[int, None] = None created_time: Union[int, None] = None
paid_time: Union[int, None] = None paid_time: Union[int, None] = None
fee_paid: int = 0 fee_paid: int = 0
payment_preimage: str = "" payment_preimage: Optional[str] = None
expiry: Optional[int] = None expiry: Optional[int] = None
change: Optional[List[BlindedSignature]] = None change: Optional[List[BlindedSignature]] = None
mint: Optional[str] = None
@classmethod @classmethod
def from_row(cls, row: Row): 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 paid_time = int(row["paid_time"].timestamp()) if row["paid_time"] else None
expiry = int(row["expiry"].timestamp()) if row["expiry"] 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 # parse change from row as json
change = None change = None
if row["change"]: if row["change"]:
@@ -327,13 +318,30 @@ class MeltQuote(LedgerEvent):
unit=row["unit"], unit=row["unit"],
amount=row["amount"], amount=row["amount"],
fee_reserve=row["fee_reserve"], fee_reserve=row["fee_reserve"],
state=MeltQuoteState[row["state"]], state=MeltQuoteState(row["state"]),
created_time=created_time, created_time=created_time,
paid_time=paid_time, paid_time=paid_time,
fee_paid=row["fee_paid"], fee_paid=row["fee_paid"],
change=change, change=change,
expiry=expiry, 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 @property
@@ -397,6 +405,7 @@ class MintQuote(LedgerEvent):
created_time: Union[int, None] = None created_time: Union[int, None] = None
paid_time: Union[int, None] = None paid_time: Union[int, None] = None
expiry: Optional[int] = None expiry: Optional[int] = None
mint: Optional[str] = None
@classmethod @classmethod
def from_row(cls, row: Row): def from_row(cls, row: Row):
@@ -417,11 +426,26 @@ class MintQuote(LedgerEvent):
checking_id=row["checking_id"], checking_id=row["checking_id"],
unit=row["unit"], unit=row["unit"],
amount=row["amount"], amount=row["amount"],
state=MintQuoteState[row["state"]], state=MintQuoteState(row["state"]),
created_time=created_time, created_time=created_time,
paid_time=paid_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 @property
def identifier(self) -> str: def identifier(self) -> str:
"""Implementation of the abstract method from LedgerEventManager""" """Implementation of the abstract method from LedgerEventManager"""

View File

@@ -65,6 +65,7 @@ class Compat:
def table_with_schema(self, table: str): def table_with_schema(self, table: str):
return f"{self.references_schema if self.schema else ''}{table}" return f"{self.references_schema if self.schema else ''}{table}"
# https://docs.sqlalchemy.org/en/14/core/connections.html#sqlalchemy.engine.CursorResult # https://docs.sqlalchemy.org/en/14/core/connections.html#sqlalchemy.engine.CursorResult
class Connection(Compat): class Connection(Compat):
def __init__(self, conn: AsyncSession, txn, typ, name, schema): def __init__(self, conn: AsyncSession, txn, typ, name, schema):
@@ -82,7 +83,9 @@ class Connection(Compat):
async def fetchall(self, query: str, values: dict = {}): async def fetchall(self, query: str, values: dict = {}):
result = await self.conn.execute(self.rewrite_query(query), values) 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 = {}): async def fetchone(self, query: str, values: dict = {}):
result = await self.conn.execute(self.rewrite_query(query), values) result = await self.conn.execute(self.rewrite_query(query), values)
@@ -134,13 +137,13 @@ class Database(Compat):
if not settings.db_connection_pool: if not settings.db_connection_pool:
kwargs["poolclass"] = NullPool kwargs["poolclass"] = NullPool
elif self.type == POSTGRES: elif self.type == POSTGRES:
kwargs["poolclass"] = AsyncAdaptedQueuePool # type: ignore[assignment] kwargs["poolclass"] = AsyncAdaptedQueuePool # type: ignore[assignment]
kwargs["pool_size"] = 50 # type: ignore[assignment] kwargs["pool_size"] = 50 # type: ignore[assignment]
kwargs["max_overflow"] = 100 # type: ignore[assignment] kwargs["max_overflow"] = 100 # type: ignore[assignment]
self.engine = create_async_engine(database_uri, **kwargs) self.engine = create_async_engine(database_uri, **kwargs)
self.async_session = sessionmaker( self.async_session = sessionmaker(
self.engine, self.engine, # type: ignore
expire_on_commit=False, expire_on_commit=False,
class_=AsyncSession, # type: ignore class_=AsyncSession, # type: ignore
) )

View File

@@ -304,7 +304,7 @@ class LedgerCrudSqlite(LedgerCrud):
""", """,
{"b_": str(b_)}, {"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( async def get_promises(
self, self,
@@ -320,7 +320,7 @@ class LedgerCrudSqlite(LedgerCrud):
""", """,
{f"b_{i}": b_s[i] for i in range(len(b_s))}, {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( async def invalidate_proof(
self, self,
@@ -455,7 +455,7 @@ class LedgerCrudSqlite(LedgerCrud):
"amount": quote.amount, "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) "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) "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( "created_time": db.to_timestamp(
db.timestamp_from_seconds(quote.created_time) or "" db.timestamp_from_seconds(quote.created_time) or ""
), ),
@@ -497,7 +497,7 @@ class LedgerCrudSqlite(LedgerCrud):
) )
if row is None: if row is None:
return 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( async def get_mint_quote_by_request(
self, self,
@@ -513,7 +513,7 @@ class LedgerCrudSqlite(LedgerCrud):
""", """,
{"request": request}, {"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( async def update_mint_quote(
self, self,
@@ -525,7 +525,7 @@ class LedgerCrudSqlite(LedgerCrud):
await (conn or db).execute( await (conn or db).execute(
f"UPDATE {db.table_with_schema('mint_quotes')} SET state = :state, paid_time = :paid_time WHERE quote = :quote", 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( "paid_time": db.to_timestamp(
db.timestamp_from_seconds(quote.paid_time) or "" db.timestamp_from_seconds(quote.paid_time) or ""
), ),
@@ -554,7 +554,7 @@ class LedgerCrudSqlite(LedgerCrud):
"unit": quote.unit, "unit": quote.unit,
"amount": quote.amount, "amount": quote.amount,
"fee_reserve": quote.fee_reserve or 0, "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) "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( "created_time": db.to_timestamp(
db.timestamp_from_seconds(quote.created_time) or "" 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 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, "fee_paid": quote.fee_paid,
"paid_time": db.to_timestamp( "paid_time": db.to_timestamp(
db.timestamp_from_seconds(quote.paid_time) or "" db.timestamp_from_seconds(quote.paid_time) or ""

View File

@@ -1,7 +1,7 @@
import copy import copy
from typing import Dict, List 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.crypto.keys import derive_keyset_id, derive_keyset_id_deprecated
from ..core.db import Connection, Database from ..core.db import Connection, Database
from ..core.settings import settings from ..core.settings import settings
@@ -826,3 +826,15 @@ async def m021_add_change_and_expiry_to_melt_quotes(db: Database):
await conn.execute( await conn.execute(
f"ALTER TABLE {db.table_with_schema('melt_quotes')} ADD COLUMN expiry TIMESTAMP" 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 pydantic import BaseModel
from ...core.base import Invoice from ...core.base import MeltQuote, MintQuote
class PayResponse(BaseModel):
ok: Optional[bool] = None
class InvoiceResponse(BaseModel):
amount: Optional[int] = None
invoice: Optional[Invoice] = None
id: Optional[str] = None
class SwapResponse(BaseModel): class SwapResponse(BaseModel):
outgoing_mint: str outgoing_mint: str
incoming_mint: str incoming_mint: str
invoice: Invoice mint_quote: MintQuote
balances: Dict balances: Dict
@@ -56,7 +46,8 @@ class LocksResponse(BaseModel):
class InvoicesResponse(BaseModel): class InvoicesResponse(BaseModel):
invoices: List[Invoice] mint_quotes: List[MintQuote]
melt_quotes: List[MeltQuote]
class WalletsResponse(BaseModel): class WalletsResponse(BaseModel):

View File

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

View File

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

View File

@@ -2,7 +2,14 @@ import json
import time import time
from typing import Any, Dict, List, Optional, Tuple 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 from ..core.db import Connection, Database
@@ -217,7 +224,7 @@ async def get_keysets(
""", """,
values, 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( 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, db: Database,
invoice: Invoice, quote: MintQuote,
conn: Optional[Connection] = None, conn: Optional[Connection] = None,
) -> None: ) -> None:
await (conn or db).execute( await (conn or db).execute(
""" """
INSERT INTO invoices INSERT INTO bolt11_mint_quotes
(amount, bolt11, id, payment_hash, preimage, paid, time_created, time_paid, out) (quote, mint, method, request, checking_id, unit, amount, state, created_time, paid_time, expiry)
VALUES (:amount, :bolt11, :id, :payment_hash, :preimage, :paid, :time_created, :time_paid, :out) VALUES (:quote, :mint, :method, :request, :checking_id, :unit, :amount, :state, :created_time, :paid_time, :expiry)
""", """,
{ {
"amount": invoice.amount, "quote": quote.quote,
"bolt11": invoice.bolt11, "mint": quote.mint,
"id": invoice.id, "method": quote.method,
"payment_hash": invoice.payment_hash, "request": quote.request,
"preimage": invoice.preimage, "checking_id": quote.checking_id,
"paid": invoice.paid, "unit": quote.unit,
"time_created": invoice.time_created, "amount": quote.amount,
"time_paid": invoice.time_paid, "state": quote.state.value,
"out": invoice.out, "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, db: Database,
id: str = "", quote: str | None = None,
payment_hash: str = "", request: str | None = None,
out: Optional[bool] = None,
conn: Optional[Connection] = None, conn: Optional[Connection] = None,
) -> Optional[Invoice]: ) -> Optional[MintQuote]:
if not quote and not request:
raise ValueError("quote or request must be provided")
clauses = [] clauses = []
values: Dict[str, Any] = {} values: Dict[str, Any] = {}
if id: if quote:
clauses.append("id = :id") clauses.append("quote = :quote")
values["id"] = id values["quote"] = quote
if payment_hash: if request:
clauses.append("payment_hash = :payment_hash") clauses.append("request = :request")
values["payment_hash"] = payment_hash values["request"] = request
if out is not None:
clauses.append("out = :out")
values["out"] = out
where = "" where = ""
if clauses: if clauses:
where = f"WHERE {' AND '.join(clauses)}" where = f"WHERE {' AND '.join(clauses)}"
query = f"""
SELECT * from invoices
{where}
"""
row = await (conn or db).fetchone( row = await (conn or db).fetchone(
query, f"""
SELECT * from bolt11_mint_quotes
{where}
""",
values, 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, db: Database,
paid: Optional[bool] = None, mint: Optional[str] = None,
pending: Optional[bool] = None, state: Optional[MintQuoteState] = None,
conn: Optional[Connection] = None, conn: Optional[Connection] = None,
) -> List[Invoice]: ) -> List[MintQuote]:
clauses = [] clauses = []
values: Dict[str, Any] = {} values: Dict[str, Any] = {}
if mint:
if paid is not None and not pending: clauses.append("mint = :mint")
clauses.append("paid = :paid") values["mint"] = mint
values["paid"] = paid if state:
clauses.append("state = :state")
if pending: values["state"] = state.value
clauses.append("paid = :paid")
values["paid"] = False
clauses.append("out = :out")
values["out"] = False
where = "" where = ""
if clauses: if clauses:
@@ -322,37 +324,149 @@ async def get_lightning_invoices(
rows = await (conn or db).fetchall( rows = await (conn or db).fetchall(
f""" f"""
SELECT * from invoices SELECT * from bolt11_mint_quotes
{where} {where}
""", """,
values, 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, db: Database,
id: str, quote: str,
paid: bool, state: MintQuoteState,
time_paid: Optional[int] = None, paid_time: int,
preimage: Optional[str] = None,
conn: Optional[Connection] = None, conn: Optional[Connection] = None,
) -> 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 = [] clauses = []
values: Dict[str, Any] = {} values: Dict[str, Any] = {}
clauses.append("paid = :paid") if quote:
values["paid"] = paid clauses.append("quote = :quote")
values["quote"] = quote
if request:
clauses.append("request = :request")
values["request"] = request
if time_paid: where = ""
clauses.append("time_paid = :time_paid") if clauses:
values["time_paid"] = time_paid where = f"WHERE {' AND '.join(clauses)}"
if preimage: row = await (conn or db).fetchone(
clauses.append("preimage = :preimage") f"""
values["preimage"] = preimage 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( 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"}, {"type": "dm"},
) )
return row[0] if row else None return row[0] if row else None # type: ignore
async def get_seed_and_mnemonic( async def get_seed_and_mnemonic(

View File

@@ -12,7 +12,11 @@ from ...lightning.base import (
PaymentStatus, PaymentStatus,
StatusResponse, 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 from ..wallet import Wallet
@@ -47,21 +51,22 @@ class LightningWallet(Wallet):
Returns: Returns:
str: invoice str: invoice
""" """
invoice = await self.request_mint(amount, memo) mint_quote = await self.request_mint(amount, memo)
return InvoiceResponse( 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 """Pay lightning invoice
Args: Args:
pr (str): bolt11 payment request request (str): bolt11 payment request
Returns: Returns:
PaymentResponse: containing details of the operation 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 total_amount = quote.amount + quote.fee_reserve
assert total_amount > 0, "amount is not positive" assert total_amount > 0, "amount is not positive"
if self.available_balance < total_amount: if self.available_balance < total_amount:
@@ -69,13 +74,13 @@ class LightningWallet(Wallet):
return PaymentResponse(result=PaymentResult.FAILED) return PaymentResponse(result=PaymentResult.FAILED)
_, send_proofs = await self.swap_to_send(self.proofs, total_amount) _, send_proofs = await self.swap_to_send(self.proofs, total_amount)
try: 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: if resp.change:
fees_paid_sat = quote.fee_reserve - sum_promises(resp.change) fees_paid_sat = quote.fee_reserve - sum_promises(resp.change)
else: else:
fees_paid_sat = quote.fee_reserve fees_paid_sat = quote.fee_reserve
invoice_obj = bolt11.decode(pr) invoice_obj = bolt11.decode(request)
return PaymentResponse( return PaymentResponse(
result=PaymentResult.SETTLED, result=PaymentResult.SETTLED,
checking_id=invoice_obj.payment_hash, checking_id=invoice_obj.payment_hash,
@@ -86,55 +91,49 @@ class LightningWallet(Wallet):
print("Exception:", e) print("Exception:", e)
return PaymentResponse(result=PaymentResult.FAILED, error_message=str(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) """Get lightning invoice status (incoming)
Args: Args:
invoice (str): lightning invoice request (str): lightning invoice request
Returns: Returns:
str: status str: status
""" """
invoice = await get_lightning_invoice( mint_quote = await get_bolt11_mint_quote(db=self.db, request=request)
db=self.db, payment_hash=payment_hash, out=False if not mint_quote:
)
if not invoice:
return PaymentStatus(result=PaymentResult.UNKNOWN) return PaymentStatus(result=PaymentResult.UNKNOWN)
if invoice.paid: if mint_quote.paid:
return PaymentStatus(result=PaymentResult.SETTLED) return PaymentStatus(result=PaymentResult.SETTLED)
try: try:
# to check the invoice state, we try minting tokens # 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) return PaymentStatus(result=PaymentResult.SETTLED)
except Exception as e: except Exception as e:
print(e) print(e)
return PaymentStatus(result=PaymentResult.FAILED) 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) """Get lightning payment status (outgoing)
Args: Args:
payment_hash (str): lightning invoice payment_hash request (str): lightning invoice request
Returns: Returns:
str: status 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( if not melt_quote:
db=self.db, payment_hash=payment_hash, out=True
)
if not invoice:
return PaymentStatus( return PaymentStatus(
result=PaymentResult.FAILED result=PaymentResult.FAILED
) # "invoice not found (in db)" ) # "invoice not found (in db)"
if invoice.paid: if melt_quote.paid:
return PaymentStatus( return PaymentStatus(
result=PaymentResult.SETTLED, preimage=invoice.preimage result=PaymentResult.SETTLED, preimage=melt_quote.payment_preimage
) # "paid (in db)" ) # "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: if not proofs:
return PaymentStatus( return PaymentStatus(
result=PaymentResult.FAILED 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") await conn.execute("UPDATE keysets SET input_fee_ppk = 0")
# # async def m020_add_state_to_mint_and_melt_quotes(db: Database): async def m013_add_mint_and_melt_quote_tables(db: Database):
# # async with db.connect() as conn: async with db.connect() as conn:
# # await conn.execute( await conn.execute(
# # f"ALTER TABLE {db.table_with_schema('mint_quotes')} ADD COLUMN state TEXT" """
# # ) CREATE TABLE IF NOT EXISTS bolt11_mint_quotes (
# # await conn.execute( quote TEXT PRIMARY KEY,
# # f"ALTER TABLE {db.table_with_schema('melt_quotes')} ADD COLUMN state TEXT" 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 await conn.execute(
# # # and the `paid` and `issued` column respectively """
# # # mint quotes: CREATE TABLE IF NOT EXISTS bolt11_melt_quotes (
# # async with db.connect() as conn: quote TEXT PRIMARY KEY,
# # rows = await conn.fetchall( mint TEXT NOT NULL,
# # f"SELECT * FROM {db.table_with_schema('mint_quotes')}" method TEXT NOT NULL,
# # ) request TEXT NOT NULL,
# # for row in rows: checking_id TEXT NOT NULL,
# # if row["issued"]: unit TEXT NOT NULL,
# # state = "issued" amount INTEGER NOT NULL,
# # elif row["paid"]: fee_reserve INTEGER NOT NULL,
# # state = "paid" state TEXT NOT NULL,
# # else: created_time INTEGER,
# # state = "unpaid" paid_time INTEGER,
# # await conn.execute( fee_paid INTEGER,
# # f"UPDATE {db.table_with_schema('mint_quotes')} SET state = '{state}' WHERE quote = '{row['quote']}'" payment_preimage TEXT,
# # ) expiry INTEGER,
change TEXT
# # # 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']}'"
# )

View File

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

View File

@@ -4,7 +4,6 @@ import threading
import time import time
from typing import Callable, Dict, List, Optional, Tuple, Union from typing import Callable, Dict, List, Optional, Tuple, Union
import bolt11
from bip32 import BIP32 from bip32 import BIP32
from loguru import logger from loguru import logger
@@ -12,8 +11,10 @@ from ..core.base import (
BlindedMessage, BlindedMessage,
BlindedSignature, BlindedSignature,
DLEQWallet, DLEQWallet,
Invoice, MeltQuote,
MeltQuoteState, MeltQuoteState,
MintQuote,
MintQuoteState,
Proof, Proof,
Unit, Unit,
WalletKeyset, WalletKeyset,
@@ -26,6 +27,7 @@ from ..core.errors import KeysetNotFoundError
from ..core.helpers import ( from ..core.helpers import (
amount_summary, amount_summary,
calculate_number_of_blank_outputs, calculate_number_of_blank_outputs,
sum_promises,
sum_proofs, sum_proofs,
) )
from ..core.json_rpc.base import JSONRPCSubscriptionKinds from ..core.json_rpc.base import JSONRPCSubscriptionKinds
@@ -45,11 +47,13 @@ from .crud import (
invalidate_proof, invalidate_proof,
secret_used, secret_used,
set_secret_derivation, set_secret_derivation,
store_bolt11_melt_quote,
store_bolt11_mint_quote,
store_keyset, store_keyset,
store_lightning_invoice,
store_proof, store_proof,
update_bolt11_melt_quote,
update_bolt11_mint_quote,
update_keyset, update_keyset,
update_lightning_invoice,
update_proof, update_proof,
) )
from .htlc import WalletHTLC from .htlc import WalletHTLC
@@ -312,7 +316,9 @@ class Wallet(
self.keyset_id = chosen_keyset.id 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: 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( async def request_mint_with_callback(
self, amount: int, callback: Callable, memo: Optional[str] = None self, amount: int, callback: Callable, memo: Optional[str] = None
) -> Tuple[Invoice, SubscriptionManager]: ) -> Tuple[MintQuote, SubscriptionManager]:
"""Request a Lightning invoice for minting tokens. """Request a quote invoice for minting tokens.
Args: Args:
amount (int): Amount for Lightning invoice in satoshis amount (int): Amount for Lightning invoice in satoshis
@@ -390,7 +396,7 @@ class Wallet(
memo (Optional[str], optional): Memo for the Lightning invoice. Defaults memo (Optional[str], optional): Memo for the Lightning invoice. Defaults
Returns: Returns:
Invoice: Lightning invoice MintQuote: Mint Quote
""" """
mint_qoute = await super().mint_quote(amount, self.unit, memo) mint_qoute = await super().mint_quote(amount, self.unit, memo)
subscriptions = SubscriptionManager(self.url) subscriptions = SubscriptionManager(self.url)
@@ -402,21 +408,13 @@ class Wallet(
filters=[mint_qoute.quote], filters=[mint_qoute.quote],
callback=callback, callback=callback,
) )
# return the invoice quote = MintQuote.from_resp_wallet(mint_qoute, self.url, amount, self.unit.name)
decoded_invoice = bolt11.decode(mint_qoute.request) await store_bolt11_mint_quote(db=self.db, quote=quote)
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
async def request_mint(self, amount: int, memo: Optional[str] = None) -> Invoice: return quote, subscriptions
"""Request a Lightning invoice for minting tokens.
async def request_mint(self, amount: int, memo: Optional[str] = None) -> MintQuote:
"""Request a quote invoice for minting tokens.
Args: Args:
amount (int): Amount for Lightning invoice in satoshis 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. memo (Optional[str], optional): Memo for the Lightning invoice. Defaults to None.
Returns: Returns:
PostMintQuoteResponse: Mint Quote Response MintQuote: Mint Quote
""" """
mint_quote_response = await super().mint_quote(amount, self.unit, memo) mint_quote_response = await super().mint_quote(amount, self.unit, memo)
decoded_invoice = bolt11.decode(mint_quote_response.request) quote = MintQuote.from_resp_wallet(
invoice = Invoice( mint_quote_response, self.url, amount, self.unit.name
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) await store_bolt11_mint_quote(db=self.db, quote=quote)
return invoice return quote
def split_wallet_state(self, amount: int) -> List[int]: 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. """This function produces an amount split for outputs based on the current state of the wallet.
@@ -484,33 +476,10 @@ class Wallet(
return amounts 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( async def mint(
self, self,
amount: int, amount: int,
id: str, quote_id: str,
split: Optional[List[int]] = None, split: Optional[List[int]] = None,
) -> List[Proof]: ) -> List[Proof]:
"""Mint tokens of a specific amount after an invoice has been paid. """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) outputs, rs = self._construct_outputs(amounts, secrets, rs)
# will raise exception if mint is unsuccessful # 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 promises_keyset_id = promises[0].id
await bump_secret_derivation( await bump_secret_derivation(
@@ -561,15 +530,17 @@ class Wallet(
) )
proofs = await self._construct_proofs(promises, secrets, rs, derivation_paths) proofs = await self._construct_proofs(promises, secrets, rs, derivation_paths)
if id: await update_bolt11_mint_quote(
await update_lightning_invoice( db=self.db,
db=self.db, id=id, paid=True, time_paid=int(time.time()) quote=quote_id,
) state=MintQuoteState.paid,
# store the mint_id in proofs paid_time=int(time.time()),
async with self.db.connect() as conn: )
for p in proofs: # store the mint_id in proofs
p.mint_id = id async with self.db.connect() as conn:
await update_proof(p, mint_id=id, conn=conn) for p in proofs:
p.mint_id = quote_id
await update_proof(p, mint_id=quote_id, conn=conn)
return proofs return proofs
async def redeem( async def redeem(
@@ -725,11 +696,19 @@ class Wallet(
""" """
if amount and not self.mint_info.supports_mpp("bolt11", self.unit): if amount and not self.mint_info.supports_mpp("bolt11", self.unit):
raise Exception("Mint does not support MPP, cannot specify amount.") 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( 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( async def melt(
self, proofs: List[Proof], invoice: str, fee_reserve_sat: int, quote_id: str 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 # Make sure we're operating on an independent copy of proofs
proofs = copy.copy(proofs) proofs = copy.copy(proofs)
amount = sum_proofs(proofs)
# Generate a number of blank outputs for any overpaid fees. As described in # 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 # 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 p.melt_id = quote_id
await update_proof(p, melt_id=quote_id, conn=conn) 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 melt_quote_resp = await super().melt(quote_id, proofs, change_outputs)
melt_quote = MeltQuote.from_resp_wallet(
decoded_invoice = bolt11.decode(invoice) melt_quote_resp,
invoice_obj = Invoice( self.url,
amount=-sum_proofs(proofs), amount=amount,
bolt11=invoice, unit=self.unit.name,
payment_hash=decoded_invoice.payment_hash, request=invoice,
# preimage=status.preimage,
paid=False,
time_paid=int(time.time()),
id=quote_id, # store the same ID in the invoice
out=True, # outgoing 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 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 # remove the melt_id in proofs and set reserved to False
for p in proofs: for p in proofs:
p.melt_id = None p.melt_id = None
p.reserved = False p.reserved = False
await update_proof(p, melt_id="", db=self.db) await update_proof(p, melt_id="", db=self.db)
raise Exception("could not pay invoice.") raise Exception("could not pay invoice.")
elif MeltQuoteState(status.state) == MeltQuoteState.pending: elif melt_quote.state == MeltQuoteState.pending:
# payment is still pending # payment is still pending
return status logger.debug("Payment is still pending.")
return melt_quote_resp
# invoice was paid successfully # invoice was paid successfully
await self.invalidate(proofs) await self.invalidate(proofs)
# update paid status in db # update paid status in db
logger.trace(f"Settings invoice {quote_id} to paid.") 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, db=self.db,
id=quote_id, quote=quote_id,
paid=True, state=MeltQuoteState.paid,
time_paid=int(time.time()), paid_time=int(time.time()),
preimage=status.payment_preimage, payment_preimage=melt_quote.payment_preimage or "",
fee_paid=fee_paid,
) )
# handle change and produce proofs # handle change and produce proofs
if status.change: if melt_quote.change:
change_proofs = await self._construct_proofs( change_proofs = await self._construct_proofs(
status.change, melt_quote.change,
change_secrets[: len(status.change)], change_secrets[: len(melt_quote.change)],
change_rs[: len(status.change)], change_rs[: len(melt_quote.change)],
change_derivation_paths[: len(status.change)], change_derivation_paths[: len(melt_quote.change)],
) )
logger.debug(f"Received change: {self.unit.str(sum_proofs(change_proofs))}") 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: async def check_proof_state(self, proofs) -> PostCheckStateResponse:
return await super().check_proof_state(proofs) 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 =" "SELECT table_name FROM information_schema.tables WHERE table_schema ="
" 'public';" " '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 = [t[0] for t in tables_all]
tables_expected = [ tables_expected = [
"dbversions", "dbversions",
@@ -117,7 +117,7 @@ async def test_db_get_connection(ledger: Ledger):
# @pytest.mark.asyncio # @pytest.mark.asyncio
# async def test_db_get_connection_locked(wallet: Wallet, ledger: Ledger): # 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(): # 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)""" # """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: # ) as conn2:
# # write something with conn1, we never reach this point if the lock works # # write something with conn1, we never reach this point if the lock works
# await conn2.execute( # 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: # except Exception as exc:
# # this is expected to raise # # 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: if ledger.db.type == db.SQLITE:
pytest.skip("SQLite does not support row locking") 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(): 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)""" """This code makes sure that only the error of the second connection is raised (which we check in the assert_err)"""
try: try:
async with ledger.db.get_connection( async with ledger.db.get_connection(
lock_table="mint_quotes", lock_table="mint_quotes",
lock_select_statement=f"quote='{invoice.id}'", lock_select_statement=f"quote='{mint_quote.quote}'",
lock_timeout=0.1, lock_timeout=0.1,
) as conn1: ) as conn1:
await conn1.execute( 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: try:
async with ledger.db.get_connection( async with ledger.db.get_connection(
lock_table="mint_quotes", lock_table="mint_quotes",
lock_select_statement=f"quote='{invoice.id}'", lock_select_statement=f"quote='{mint_quote.quote}'",
lock_timeout=0.1, lock_timeout=0.1,
) as conn2: ) as conn2:
# write something with conn1, we never reach this point if the lock works # write something with conn1, we never reach this point if the lock works
await conn2.execute( 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: except Exception as exc:
# this is expected to raise # 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 wallet: Wallet, ledger: Ledger
): ):
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
await assert_err_multiple( 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 wallet: Wallet, ledger: Ledger
): ):
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
async def delayed_verify_spent_proofs_and_set_pending(): 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 wallet: Wallet, ledger: Ledger
): ):
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet.mint(64, id=invoice.id, split=[32, 32]) await wallet.mint(64, quote_id=mint_quote.quote, split=[32, 32])
assert wallet.balance == 64 assert wallet.balance == 64
assert len(wallet.proofs) == 2 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: if ledger.db.type == db.SQLITE:
pytest.skip("SQLite does not support row locking") pytest.skip("SQLite does not support row locking")
# this should work since we lock two different rows # this should work since we lock two different rows
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
invoice2 = await wallet.request_mint(64) mint_quote_2 = await wallet.request_mint(64)
async def get_connection2(): 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)""" """This code makes sure that only the error of the second connection is raised (which we check in the assert_err)"""
try: try:
async with ledger.db.get_connection( async with ledger.db.get_connection(
lock_table="mint_quotes", lock_table="mint_quotes",
lock_select_statement=f"quote='{invoice.id}'", lock_select_statement=f"quote='{mint_quote.quote}'",
lock_timeout=0.1, lock_timeout=0.1,
): ):
try: try:
async with ledger.db.get_connection( async with ledger.db.get_connection(
lock_table="mint_quotes", lock_table="mint_quotes",
lock_select_statement=f"quote='{invoice2.id}'", lock_select_statement=f"quote='{mint_quote_2.quote}'",
lock_timeout=0.1, lock_timeout=0.1,
) as conn2: ) as conn2:
# write something with conn1, this time we should reach this block with postgres # write something with conn1, this time we should reach this block with postgres
quote = await ledger.crud.get_mint_quote( 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 assert quote is not None
quote.amount = 100 quote.amount = 100
@@ -294,10 +294,10 @@ async def test_db_get_connection_lock_different_row(wallet: Wallet, ledger: Ledg
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_db_lock_table(wallet: Wallet, ledger: Ledger): async def test_db_lock_table(wallet: Wallet, ledger: Ledger):
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
async with ledger.db.connect(lock_table="proofs_pending", lock_timeout=0.1) as conn: 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", reason="settings.debug_mint_only_deprecated is set",
) )
async def test_split(ledger: Ledger, wallet: Wallet): async def test_split(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
secrets, rs, derivation_paths = await wallet.generate_n_secrets(2) secrets, rs, derivation_paths = await wallet.generate_n_secrets(2)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) 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", reason="settings.debug_mint_only_deprecated is set",
) )
async def test_mint(ledger: Ledger, wallet: Wallet): async def test_mint(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
quote_id = invoice.id
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001) secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
outputs_payload = [o.dict() for o in outputs] outputs_payload = [o.dict() for o in outputs]
response = httpx.post( response = httpx.post(
f"{BASE_URL}/v1/mint/bolt11", f"{BASE_URL}/v1/mint/bolt11",
json={"quote": quote_id, "outputs": outputs_payload}, json={"quote": mint_quote.quote, "outputs": outputs_payload},
timeout=None, timeout=None,
) )
assert response.status_code == 200, f"{response.url} {response.status_code}" 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): async def test_melt_quote_internal(ledger: Ledger, wallet: Wallet):
# internal invoice # internal invoice
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
request = invoice.bolt11 request = mint_quote.request
response = httpx.post( response = httpx.post(
f"{BASE_URL}/v1/melt/quote/bolt11", f"{BASE_URL}/v1/melt/quote/bolt11",
json={"unit": "sat", "request": request}, 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): async def test_melt_internal(ledger: Ledger, wallet: Wallet):
# internal invoice # internal invoice
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
# create invoice to melt to # 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) quote = await wallet.melt_quote(invoice_payment_request)
assert quote.amount == 64 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}" assert response.status_code == 200, f"{response.url} {response.status_code}"
result = response.json() result = response.json()
assert result.get("payment_preimage") is not None assert result.get("payment_preimage") is None
assert result["paid"] is True assert result["paid"] is True
# deserialize the response # deserialize the response
@@ -397,7 +396,7 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet):
assert resp_quote.quote == quote.quote assert resp_quote.quote == quote.quote
# internal invoice, no preimage, no change # 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.change == []
assert resp_quote.state == MeltQuoteState.paid.value 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): async def test_melt_external(ledger: Ledger, wallet: Wallet):
# internal invoice # internal invoice
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
invoice_dict = get_real_invoice(62) 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", reason="settings.debug_mint_only_deprecated is set",
) )
async def test_api_restore(ledger: Ledger, wallet: Wallet): async def test_api_restore(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
secret_counter = await bump_secret_derivation( secret_counter = await bump_secret_derivation(
db=wallet.db, keyset_id=wallet.keyset_id, by=0, skip=True 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 @pytest.mark.asyncio
async def test_split(ledger: Ledger, wallet: Wallet): async def test_split(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(20000, 20001) secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(20000, 20001)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
@@ -88,9 +88,9 @@ async def test_split(ledger: Ledger, wallet: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_split_deprecated_with_amount(ledger: Ledger, wallet: Wallet): async def test_split_deprecated_with_amount(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(80000, 80001) secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(80000, 80001)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
@@ -124,16 +124,15 @@ async def test_api_mint_validation(ledger):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_mint(ledger: Ledger, wallet: Wallet): async def test_mint(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
quote_id = invoice.id
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001) secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
outputs_payload = [o.dict() for o in outputs] outputs_payload = [o.dict() for o in outputs]
response = httpx.post( response = httpx.post(
f"{BASE_URL}/mint", f"{BASE_URL}/mint",
json={"outputs": outputs_payload}, json={"outputs": outputs_payload},
params={"hash": quote_id}, params={"hash": mint_quote.quote},
timeout=None, timeout=None,
) )
assert response.status_code == 200, f"{response.url} {response.status_code}" 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 @pytest.mark.asyncio
async def test_melt_internal(ledger: Ledger, wallet: Wallet): async def test_melt_internal(ledger: Ledger, wallet: Wallet):
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
# create invoice to melt to # 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) quote = await wallet.melt_quote(invoice_payment_request)
assert quote.amount == 64 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}" assert response.status_code == 200, f"{response.url} {response.status_code}"
result = response.json() result = response.json()
assert result.get("preimage") is not None assert result.get("preimage") is None
assert result["paid"] is True 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): async def test_melt_internal_no_change_outputs(ledger: Ledger, wallet: Wallet):
# Clients without NUT-08 will not send change outputs # Clients without NUT-08 will not send change outputs
# internal invoice # internal invoice
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
# create invoice to melt to # 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) quote = await wallet.melt_quote(invoice_payment_request)
assert quote.amount == 64 assert quote.amount == 64
assert quote.fee_reserve == 0 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}" assert response.status_code == 200, f"{response.url} {response.status_code}"
result = response.json() result = response.json()
assert result.get("preimage") is not None assert result.get("preimage") is None
assert result["paid"] is True 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): async def test_melt_external(ledger: Ledger, wallet: Wallet):
# internal invoice # internal invoice
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
# create invoice to melt to # create invoice to melt to
@@ -271,11 +270,11 @@ async def test_melt_external(ledger: Ledger, wallet: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_checkfees(ledger: Ledger, wallet: Wallet): async def test_checkfees(ledger: Ledger, wallet: Wallet):
# internal invoice # internal invoice
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
response = httpx.post( response = httpx.post(
f"{BASE_URL}/checkfees", f"{BASE_URL}/checkfees",
json={ json={
"pr": invoice.bolt11, "pr": mint_quote.request,
}, },
timeout=None, timeout=None,
) )
@@ -323,9 +322,9 @@ async def test_api_check_state(ledger: Ledger):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_api_restore(ledger: Ledger, wallet: Wallet): async def test_api_restore(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
secret_counter = await bump_secret_derivation( secret_counter = await bump_secret_derivation(
db=wallet.db, keyset_id=wallet.keyset_id, by=0, skip=True 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.asyncio
@pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS") @pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS")
async def test_mint_proofs_pending(wallet: Wallet, ledger: Ledger): async def test_mint_proofs_pending(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet.mint(64, id=invoice.id) await wallet.mint(64, quote_id=mint_quote.quote)
proofs = wallet.proofs.copy() proofs = wallet.proofs.copy()
proofs_states_before_split = await wallet.check_proof_state(proofs) 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 @pytest.mark.asyncio
async def test_mint_quote(wallet: Wallet, ledger: Ledger): async def test_mint_quote(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128) mint_quote = await wallet.request_mint(128)
assert invoice is not None quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
assert quote is not None assert quote is not None
assert quote.quote == invoice.id
assert quote.amount == 128 assert quote.amount == 128
assert quote.unit == "sat" assert quote.unit == "sat"
assert not quote.paid assert not quote.paid
assert quote.checking_id == invoice.payment_hash
# assert quote.paid_time is None # assert quote.paid_time is None
assert quote.created_time assert quote.created_time
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_mint_quote_state_transitions(wallet: Wallet, ledger: Ledger): async def test_mint_quote_state_transitions(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128) mint_quote = await wallet.request_mint(128)
assert invoice is not None quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
assert quote is not None assert quote is not None
assert quote.quote == invoice.id
assert quote.unpaid assert quote.unpaid
# set pending again # set pending again
@@ -129,11 +124,9 @@ async def test_mint_quote_state_transitions(wallet: Wallet, ledger: Ledger):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_get_mint_quote_by_request(wallet: Wallet, ledger: Ledger): async def test_get_mint_quote_by_request(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128) mint_quote = await wallet.request_mint(128)
assert invoice is not None quote = await ledger.crud.get_mint_quote(request=mint_quote.request, db=ledger.db)
quote = await ledger.crud.get_mint_quote(request=invoice.bolt11, db=ledger.db)
assert quote is not None assert quote is not None
assert quote.quote == invoice.id
assert quote.amount == 128 assert quote.amount == 128
assert quote.unit == "sat" assert quote.unit == "sat"
assert not quote.paid assert not quote.paid
@@ -143,10 +136,9 @@ async def test_get_mint_quote_by_request(wallet: Wallet, ledger: Ledger):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_melt_quote(wallet: Wallet, ledger: Ledger): async def test_melt_quote(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128) mint_quote = await wallet.request_mint(128)
assert invoice is not None
melt_quote = await ledger.melt_quote( 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) quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db)
assert quote is not None assert quote is not None
@@ -154,17 +146,15 @@ async def test_melt_quote(wallet: Wallet, ledger: Ledger):
assert quote.amount == 128 assert quote.amount == 128
assert quote.unit == "sat" assert quote.unit == "sat"
assert not quote.paid assert not quote.paid
assert quote.checking_id == invoice.payment_hash
# assert quote.paid_time is None # assert quote.paid_time is None
assert quote.created_time assert quote.created_time
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_melt_quote_set_pending(wallet: Wallet, ledger: Ledger): async def test_melt_quote_set_pending(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128) mint_quote = await wallet.request_mint(128)
assert invoice is not None
melt_quote = await ledger.melt_quote( 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 is not None
assert melt_quote.state == MeltQuoteState.unpaid.value 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 @pytest.mark.asyncio
async def test_melt_quote_state_transitions(wallet: Wallet, ledger: Ledger): async def test_melt_quote_state_transitions(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128) mint_quote = await wallet.request_mint(128)
assert invoice is not None
melt_quote = await ledger.melt_quote( 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) quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db)
assert quote is not None assert quote is not None
@@ -218,33 +207,36 @@ async def test_melt_quote_state_transitions(wallet: Wallet, ledger: Ledger):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_mint_quote_set_pending(wallet: Wallet, ledger: Ledger): async def test_mint_quote_set_pending(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128) mint_quote = await wallet.request_mint(128)
assert invoice is not None mint_quote = await ledger.crud.get_mint_quote(
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db) quote_id=mint_quote.quote, db=ledger.db
assert quote is not None )
assert quote.unpaid assert mint_quote is not None
assert mint_quote.unpaid
# pay_if_regtest pays on regtest, get_mint_quote pays on FakeWallet # pay_if_regtest pays on regtest, get_mint_quote pays on FakeWallet
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
_ = await ledger.get_mint_quote(invoice.id) _ = 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 is not None
assert quote.paid assert quote.paid
previous_state = MintQuoteState.paid previous_state = MintQuoteState.paid
await ledger.db_write._set_mint_quote_pending(quote.quote) 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 is not None
assert quote.pending assert quote.pending
# try to mint while 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 # set unpending
await ledger.db_write._unset_mint_quote_pending(quote.quote, previous_state) 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 is not None
assert quote.state == previous_state assert quote.state == previous_state
assert quote.paid assert quote.paid
@@ -253,20 +245,19 @@ async def test_mint_quote_set_pending(wallet: Wallet, ledger: Ledger):
# quote.state = MintQuoteState.paid # quote.state = MintQuoteState.paid
# await ledger.crud.update_mint_quote(quote=quote, db=ledger.db) # 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 # 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 is not None
assert quote.issued assert quote.issued
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_db_events_add_client(wallet: Wallet, ledger: Ledger): async def test_db_events_add_client(wallet: Wallet, ledger: Ledger):
invoice = await wallet.request_mint(128) mint_quote = await wallet.request_mint(128)
assert invoice is not None
melt_quote = await ledger.melt_quote( 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 is not None
assert melt_quote.state == MeltQuoteState.unpaid.value assert melt_quote.state == MeltQuoteState.unpaid.value

View File

@@ -48,9 +48,9 @@ def set_ledger_keyset_fees(
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_get_fees_for_proofs(wallet1: Wallet, ledger: Ledger): async def test_get_fees_for_proofs(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, split=[1] * 64, id=invoice.id) await wallet1.mint(64, split=[1] * 64, quote_id=mint_quote.quote)
# two proofs # two proofs
@@ -105,9 +105,9 @@ async def test_wallet_selection_with_fee(wallet1: Wallet, ledger: Ledger):
for keyset in wallet1.keysets.values(): for keyset in wallet1.keysets.values():
assert keyset.input_fee_ppk == 100 assert keyset.input_fee_ppk == 100
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10) send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
assert sum_proofs(send_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): async def test_wallet_swap_to_send_with_fee(wallet1: Wallet, ledger: Ledger):
# set fees to 100 ppk # set fees to 100 ppk
set_ledger_keyset_fees(100, ledger, wallet1) set_ledger_keyset_fees(100, ledger, wallet1)
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id, split=[32, 32]) # make sure we need to swap 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 # 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 # 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): async def test_split_with_fees(wallet1: Wallet, ledger: Ledger):
# set fees to 100 ppk # set fees to 100 ppk
set_ledger_keyset_fees(100, ledger) set_ledger_keyset_fees(100, ledger)
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10) send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
fees = ledger.get_fees_for_proofs(send_proofs) 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): async def test_split_with_high_fees(wallet1: Wallet, ledger: Ledger):
# set fees to 100 ppk # set fees to 100 ppk
set_ledger_keyset_fees(1234, ledger) set_ledger_keyset_fees(1234, ledger)
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10) send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
fees = ledger.get_fees_for_proofs(send_proofs) 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): async def test_split_not_enough_fees(wallet1: Wallet, ledger: Ledger):
# set fees to 100 ppk # set fees to 100 ppk
set_ledger_keyset_fees(100, ledger) set_ledger_keyset_fees(100, ledger)
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10) send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
fees = ledger.get_fees_for_proofs(send_proofs) 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) set_ledger_keyset_fees(100, ledger, wallet1)
# mint twice so we have enough to pay the second invoice back # mint twice so we have enough to pay the second invoice back
invoice = await wallet1.request_mint(128) mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(128, id=invoice.id) await wallet1.mint(128, quote_id=mint_quote.quote)
assert wallet1.balance == 128 assert wallet1.balance == 128
# create a mint quote so that we can melt to it internally # create a mint quote so that we can melt to it internally
invoice_to_pay = await wallet1.request_mint(64) 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( melt_quote = await ledger.melt_quote(
PostMeltQuoteRequest(request=invoice_payment_request, unit="sat") 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) set_ledger_keyset_fees(100, ledger, wallet1)
# mint twice so we have enough to pay the second invoice back # mint twice so we have enough to pay the second invoice back
invoice = await wallet1.request_mint(128) mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(128, id=invoice.id) await wallet1.mint(128, quote_id=mint_quote.quote)
assert wallet1.balance == 128 assert wallet1.balance == 128
invoice_dict = get_real_invoice(64) 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") @pytest.mark.skipif(is_fake, reason="only regtest")
async def test_startup_regtest_pending_quote_pending(wallet: Wallet, ledger: Ledger): async def test_startup_regtest_pending_quote_pending(wallet: Wallet, ledger: Ledger):
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
# create hodl invoice # 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") @pytest.mark.skipif(is_fake, reason="only regtest")
async def test_startup_regtest_pending_quote_success(wallet: Wallet, ledger: Ledger): async def test_startup_regtest_pending_quote_success(wallet: Wallet, ledger: Ledger):
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
# create hodl invoice # 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): async def test_startup_regtest_pending_quote_failure(wallet: Wallet, ledger: Ledger):
"""Simulate a failure to pay the hodl invoice by canceling it.""" """Simulate a failure to pay the hodl invoice by canceling it."""
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
# create hodl invoice # create hodl invoice
@@ -407,9 +407,9 @@ async def test_startup_regtest_pending_quote_unknown(wallet: Wallet, ledger: Led
points to an unknown payment.""" points to an unknown payment."""
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
# create hodl invoice # 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.asyncio
@pytest.mark.skipif(is_regtest, reason="only fake wallet") @pytest.mark.skipif(is_regtest, reason="only fake wallet")
async def test_melt_lightning_pay_invoice_settled(ledger: Ledger, wallet: Wallet): async def test_melt_lightning_pay_invoice_settled(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
await wallet.mint(64, id=invoice.id) await wallet.mint(64, quote_id=mint_quote.quote)
# invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0" # invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8" invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
quote_id = ( quote_id = (
@@ -205,9 +205,9 @@ async def test_melt_lightning_pay_invoice_settled(ledger: Ledger, wallet: Wallet
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.skipif(is_regtest, reason="only fake wallet") @pytest.mark.skipif(is_regtest, reason="only fake wallet")
async def test_melt_lightning_pay_invoice_failed_failed(ledger: Ledger, wallet: Wallet): async def test_melt_lightning_pay_invoice_failed_failed(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
await wallet.mint(64, id=invoice.id) await wallet.mint(64, quote_id=mint_quote.quote)
# invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0" # invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8" invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
quote_id = ( 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( async def test_melt_lightning_pay_invoice_failed_settled(
ledger: Ledger, wallet: Wallet ledger: Ledger, wallet: Wallet
): ):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
await wallet.mint(64, id=invoice.id) await wallet.mint(64, quote_id=mint_quote.quote)
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8" invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
quote_id = ( quote_id = (
await ledger.melt_quote( 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( async def test_melt_lightning_pay_invoice_failed_pending(
ledger: Ledger, wallet: Wallet ledger: Ledger, wallet: Wallet
): ):
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
await wallet.mint(64, id=invoice.id) await wallet.mint(64, quote_id=mint_quote.quote)
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8" invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
quote_id = ( quote_id = (
await ledger.melt_quote( await ledger.melt_quote(
@@ -303,9 +303,9 @@ async def test_melt_lightning_pay_invoice_exception_exception(
ledger: Ledger, wallet: Wallet ledger: Ledger, wallet: Wallet
): ):
"""Simulates the case where pay_invoice and get_payment_status raise an exception (due to network issues for example).""" """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) mint_quote = await wallet.request_mint(64)
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
await wallet.mint(64, id=invoice.id) await wallet.mint(64, quote_id=mint_quote.quote)
# invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0" # invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8" invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
quote_id = ( 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): async def test_mint_melt_different_units(ledger: Ledger, wallet: Wallet):
"""Mint and melt different units.""" """Mint and melt different units."""
# load the wallet # load the wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await wallet.mint(64, id=invoice.id) await wallet.mint(64, quote_id=mint_quote.quote)
amount = 32 amount = 32

View File

@@ -38,14 +38,14 @@ async def wallet1(ledger: Ledger):
@pytest.mark.skipif(is_regtest, reason="only works with FakeWallet") @pytest.mark.skipif(is_regtest, reason="only works with FakeWallet")
async def test_melt_internal(wallet1: Wallet, ledger: Ledger): async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
# mint twice so we have enough to pay the second invoice back # mint twice so we have enough to pay the second invoice back
invoice = await wallet1.request_mint(128) mint_quote = await wallet1.request_mint(128)
await ledger.get_mint_quote(invoice.id) await ledger.get_mint_quote(mint_quote.quote)
await wallet1.mint(128, id=invoice.id) await wallet1.mint(128, quote_id=mint_quote.quote)
assert wallet1.balance == 128 assert wallet1.balance == 128
# create a mint quote so that we can melt to it internally # create a mint quote so that we can melt to it internally
invoice_to_pay = await wallet1.request_mint(64) mint_quote_to_pay = await wallet1.request_mint(64)
invoice_payment_request = invoice_to_pay.bolt11 invoice_payment_request = mint_quote_to_pay.request
melt_quote = await ledger.melt_quote( melt_quote = await ledger.melt_quote(
PostMeltQuoteRequest(request=invoice_payment_request, unit="sat") 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") @pytest.mark.skipif(is_fake, reason="only works with Regtest")
async def test_melt_external(wallet1: Wallet, ledger: Ledger): async def test_melt_external(wallet1: Wallet, ledger: Ledger):
# mint twice so we have enough to pay the second invoice back # mint twice so we have enough to pay the second invoice back
invoice = await wallet1.request_mint(128) mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(128, id=invoice.id) await wallet1.mint(128, quote_id=mint_quote.quote)
assert wallet1.balance == 128 assert wallet1.balance == 128
invoice_dict = get_real_invoice(64) invoice_dict = get_real_invoice(64)
@@ -119,14 +119,14 @@ async def test_melt_external(wallet1: Wallet, ledger: Ledger):
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.skipif(is_regtest, reason="only works with FakeWallet") @pytest.mark.skipif(is_regtest, reason="only works with FakeWallet")
async def test_mint_internal(wallet1: Wallet, ledger: Ledger): async def test_mint_internal(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128) mint_quote = await wallet1.request_mint(128)
await ledger.get_mint_quote(invoice.id) await ledger.get_mint_quote(mint_quote.quote)
mint_quote = await ledger.get_mint_quote(invoice.id) mint_quote = await ledger.get_mint_quote(mint_quote.quote)
assert mint_quote.paid, "mint quote should be paid" assert mint_quote.paid, "mint quote should be paid"
if not settings.debug_mint_only_deprecated: 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 ( assert (
mint_quote_resp.state == MeltQuoteState.paid.value mint_quote_resp.state == MeltQuoteState.paid.value
), "mint quote should be paid" ), "mint quote should be paid"
@@ -136,14 +136,14 @@ async def test_mint_internal(wallet1: Wallet, ledger: Ledger):
len(output_amounts) len(output_amounts)
) )
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs) 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( 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.", "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, "mint quote should be issued"
assert mint_quote_after_payment.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" assert not mint_quote_resp.paid, "mint quote should not be paid"
await assert_err( await assert_err(
wallet1.mint(128, id=quote.quote), wallet1.mint(128, quote_id=quote.quote),
"quote not paid", "quote not paid",
) )
@@ -187,9 +187,9 @@ async def test_mint_external(wallet1: Wallet, ledger: Ledger):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_split(wallet1: Wallet, ledger: Ledger): async def test_split(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10) keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10)
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(len(send_proofs)) 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 @pytest.mark.asyncio
async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger): async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10, set_reserved=False) _, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10, set_reserved=False)
await assert_err( await assert_err(
ledger.swap(proofs=send_proofs, outputs=[]), ledger.swap(proofs=send_proofs, outputs=[]),
@@ -216,9 +216,9 @@ async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledger): async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
keep_proofs, send_proofs = await wallet1.swap_to_send( keep_proofs, send_proofs = await wallet1.swap_to_send(
wallet1.proofs, 10, set_reserved=False 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 @pytest.mark.asyncio
async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledger): async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128) mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(128, id=invoice.id) await wallet1.mint(128, quote_id=mint_quote.quote)
inputs = wallet1.proofs inputs = wallet1.proofs
@@ -269,9 +269,9 @@ async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledge
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger): async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128) mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(128, split=[64, 64], id=invoice.id) await wallet1.mint(128, split=[64, 64], quote_id=mint_quote.quote)
inputs1 = wallet1.proofs[:1] inputs1 = wallet1.proofs[:1]
inputs2 = 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 @pytest.mark.asyncio
async def test_mint_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger): async def test_mint_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128) mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
output_amounts = [128] output_amounts = [128]
secrets, rs, derivation_paths = await wallet1.generate_n_secrets( secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
len(output_amounts) len(output_amounts)
) )
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs) 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 # now try to mint with the same outputs again
invoice2 = await wallet1.request_mint(128) mint_quote_2 = await wallet1.request_mint(128)
await pay_if_regtest(invoice2.bolt11) await pay_if_regtest(mint_quote_2.request)
await assert_err( 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.", "outputs have already been signed before.",
) )
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger): async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(130) mint_quote = await wallet1.request_mint(130)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(130, id=invoice.id) await wallet1.mint(130, quote_id=mint_quote.quote)
output_amounts = [128] output_amounts = [128]
secrets, rs, derivation_paths = await wallet1.generate_n_secrets( 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) outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
# we use the outputs once for minting # we use the outputs once for minting
invoice2 = await wallet1.request_mint(128) mint_quote_2 = await wallet1.request_mint(128)
await pay_if_regtest(invoice2.bolt11) await pay_if_regtest(mint_quote_2.request)
await ledger.mint(outputs=outputs, quote_id=invoice2.id) await ledger.mint(outputs=outputs, quote_id=mint_quote_2.quote)
# use the same outputs for melting # use the same outputs for melting
mint_quote = await ledger.mint_quote(PostMintQuoteRequest(unit="sat", amount=128)) 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 @pytest.mark.asyncio
async def test_melt_with_less_inputs_than_invoice(wallet1: Wallet, ledger: Ledger): async def test_melt_with_less_inputs_than_invoice(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(32) mint_quote = await wallet1.request_mint(32)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(32, id=invoice.id) await wallet1.mint(32, quote_id=mint_quote.quote)
# outputs for fee return # outputs for fee return
output_amounts = [1, 1, 1, 1] 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 @pytest.mark.asyncio
async def test_melt_with_more_inputs_than_invoice(wallet1: Wallet, ledger: Ledger): async def test_melt_with_more_inputs_than_invoice(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(130) mint_quote = await wallet1.request_mint(130)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(130, split=[64, 64, 2], id=invoice.id) await wallet1.mint(130, split=[64, 64, 2], quote_id=mint_quote.quote)
# outputs for fee return # outputs for fee return
output_amounts = [1, 1, 1, 1] 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 @pytest.mark.asyncio
async def test_check_proof_state(wallet1: Wallet, ledger: Ledger): async def test_check_proof_state(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10) 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 # TODO: test keeps running forever, needs to be fixed
# @pytest.mark.asyncio # @pytest.mark.asyncio
# async def test_websocket_quote_updates(wallet1: Wallet, ledger: Ledger): # 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( # ws = websocket.create_connection(
# f"ws://localhost:{SERVER_PORT}/v1/quote/{invoice.id}" # f"ws://localhost:{SERVER_PORT}/v1/quote/{invoice.id}"
# ) # )
# await asyncio.sleep(0.1) # await asyncio.sleep(0.1)
# await pay_if_regtest(invoice.bolt11) # await pay_if_regtest(mint_quote.request)
# await wallet1.mint(64, id=invoice.id) # await wallet1.mint(64, quote_id=mint_quote.quote)
# await asyncio.sleep(0.1) # await asyncio.sleep(0.1)
# data = str(ws.recv()) # data = str(ws.recv())
# ws.close() # 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") @pytest.mark.skipif(is_fake, reason="only regtest")
async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger): async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
# create hodl invoice # 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.errors import CashuError, KeysetNotFoundError
from cashu.core.helpers import sum_proofs from cashu.core.helpers import sum_proofs
from cashu.core.settings import settings 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
from cashu.wallet.wallet import Wallet as Wallet1 from cashu.wallet.wallet import Wallet as Wallet1
from cashu.wallet.wallet import Wallet as Wallet2 from cashu.wallet.wallet import Wallet as Wallet2
@@ -160,44 +165,41 @@ async def test_get_keysets(wallet1: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_request_mint(wallet1: Wallet): async def test_request_mint(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
assert invoice.payment_hash assert mint_quote.request
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_mint(wallet1: Wallet): async def test_mint(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
if not settings.debug_mint_only_deprecated: if not settings.debug_mint_only_deprecated:
quote_resp = await wallet1.get_mint_quote(invoice.id) quote_resp = await wallet1.get_mint_quote(mint_quote.quote)
assert quote_resp.request == invoice.bolt11 assert quote_resp.request == mint_quote.request
assert quote_resp.state == MintQuoteState.paid.value assert quote_resp.state == MintQuoteState.paid.value
expected_proof_amounts = wallet1.split_wallet_state(64) 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 assert wallet1.balance == 64
# verify that proofs in proofs_used db have the same mint_id as the invoice in the db # verify that proofs in proofs_used db have the same mint_id as the invoice in the db
assert invoice.payment_hash mint_quote = await get_bolt11_mint_quote(db=wallet1.db, quote=mint_quote.quote)
invoice_db = await get_lightning_invoice( assert mint_quote
db=wallet1.db, payment_hash=invoice.payment_hash, out=False
)
assert invoice_db
proofs_minted = await get_proofs( 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 len(proofs_minted) == len(expected_proof_amounts)
assert all([p.amount in expected_proof_amounts for p in proofs_minted]) 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 @pytest.mark.asyncio
async def test_mint_amounts(wallet1: Wallet): async def test_mint_amounts(wallet1: Wallet):
"""Mint predefined amounts""" """Mint predefined amounts"""
amts = [1, 1, 1, 2, 2, 4, 16] amts = [1, 1, 1, 2, 2, 4, 16]
invoice = await wallet1.request_mint(sum(amts)) mint_quote = await wallet1.request_mint(sum(amts))
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(amount=sum(amts), split=amts, id=invoice.id) await wallet1.mint(amount=sum(amts), split=amts, quote_id=mint_quote.quote)
assert wallet1.balance == 27 assert wallet1.balance == 27
assert wallet1.proof_amounts == amts assert wallet1.proof_amounts == amts
@@ -207,9 +209,9 @@ async def test_mint_amounts_wrong_sum(wallet1: Wallet):
"""Mint predefined amounts""" """Mint predefined amounts"""
amts = [1, 1, 1, 2, 2, 4, 16] 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( 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", "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): async def test_mint_amounts_wrong_order(wallet1: Wallet):
"""Mint amount that is not part in 2^n""" """Mint amount that is not part in 2^n"""
amts = [1, 2, 3] amts = [1, 2, 3]
invoice = await wallet1.request_mint(sum(amts)) mint_quote = await wallet1.request_mint(sum(amts))
await assert_err( 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}.", f"Can only mint amounts with 2^n up to {2**settings.max_order}.",
) )
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_split(wallet1: Wallet): async def test_split(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
assert wallet1.balance == 64 assert wallet1.balance == 64
# the outputs we keep that we expect after the split # the outputs we keep that we expect after the split
expected_proof_amounts = wallet1.split_wallet_state(44) expected_proof_amounts = wallet1.split_wallet_state(44)
@@ -247,9 +249,9 @@ async def test_split(wallet1: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_swap_to_send(wallet1: Wallet): async def test_swap_to_send(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
assert wallet1.balance == 64 assert wallet1.balance == 64
# this will select 32 sats and them (nothing to keep) # 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 @pytest.mark.asyncio
async def test_split_more_than_balance(wallet1: Wallet): async def test_split_more_than_balance(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
await assert_err( await assert_err(
wallet1.split(wallet1.proofs, 128), wallet1.split(wallet1.proofs, 128),
# "Mint Error: inputs do not have same amount as outputs", # "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 @pytest.mark.asyncio
async def test_melt(wallet1: Wallet): async def test_melt(wallet1: Wallet):
# mint twice so we have enough to pay the second invoice back # mint twice so we have enough to pay the second invoice back
topup_invoice = await wallet1.request_mint(128) topup_mint_quote = await wallet1.request_mint(128)
await pay_if_regtest(topup_invoice.bolt11) await pay_if_regtest(topup_mint_quote.request)
await wallet1.mint(128, id=topup_invoice.id) await wallet1.mint(128, quote_id=topup_mint_quote.quote)
assert wallet1.balance == 128 assert wallet1.balance == 128
invoice_payment_request = "" invoice_payment_request = ""
invoice_payment_hash = ""
if is_regtest: if is_regtest:
invoice_dict = get_real_invoice(64) invoice_dict = get_real_invoice(64)
invoice_payment_hash = str(invoice_dict["r_hash"])
invoice_payment_request = invoice_dict["payment_request"] invoice_payment_request = invoice_dict["payment_request"]
if is_fake: if is_fake:
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
invoice_payment_hash = str(invoice.payment_hash) invoice_payment_request = mint_quote.request
invoice_payment_request = invoice.bolt11
quote = await wallet1.melt_quote(invoice_payment_request) quote = await wallet1.melt_quote(invoice_payment_request)
total_amount = quote.amount + quote.fee_reserve 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" 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 # 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" melt_quote_db = await get_bolt11_melt_quote(
invoice_db = await get_lightning_invoice( db=wallet1.db, request=invoice_payment_request
db=wallet1.db, payment_hash=invoice_payment_hash, out=True
) )
assert invoice_db, "No invoice in db" assert melt_quote_db, "No invoice in db"
proofs_used = await get_proofs( 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 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 # 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" assert wallet1.balance == 128 - (total_amount - quote.fee_reserve), "Wrong balance"
@@ -353,9 +351,9 @@ async def test_melt(wallet1: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_swap_to_send_more_than_balance(wallet1: Wallet): async def test_swap_to_send_more_than_balance(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
await assert_err( await assert_err(
wallet1.swap_to_send(wallet1.proofs, 128, set_reserved=True), wallet1.swap_to_send(wallet1.proofs, 128, set_reserved=True),
"balance too low.", "balance too low.",
@@ -366,9 +364,9 @@ async def test_swap_to_send_more_than_balance(wallet1: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_double_spend(wallet1: Wallet): async def test_double_spend(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
doublespend = await wallet1.mint(64, id=invoice.id) doublespend = await wallet1.mint(64, quote_id=mint_quote.quote)
await wallet1.split(wallet1.proofs, 20) await wallet1.split(wallet1.proofs, 20)
await assert_err( await assert_err(
wallet1.split(doublespend, 20), wallet1.split(doublespend, 20),
@@ -380,9 +378,9 @@ async def test_double_spend(wallet1: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_duplicate_proofs_double_spent(wallet1: Wallet): async def test_duplicate_proofs_double_spent(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
doublespend = await wallet1.mint(64, id=invoice.id) doublespend = await wallet1.mint(64, quote_id=mint_quote.quote)
await assert_err( await assert_err(
wallet1.split(wallet1.proofs + doublespend, 20), wallet1.split(wallet1.proofs + doublespend, 20),
"Mint Error: duplicate proofs.", "Mint Error: duplicate proofs.",
@@ -394,9 +392,9 @@ async def test_duplicate_proofs_double_spent(wallet1: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS") @pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS")
async def test_split_race_condition(wallet1: Wallet): async def test_split_race_condition(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
# run two splits in parallel # run two splits in parallel
import asyncio import asyncio
@@ -411,9 +409,9 @@ async def test_split_race_condition(wallet1: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet): async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
_, spendable_proofs = await wallet1.swap_to_send( _, spendable_proofs = await wallet1.swap_to_send(
wallet1.proofs, 32, set_reserved=True wallet1.proofs, 32, set_reserved=True
) )
@@ -430,9 +428,9 @@ async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_invalidate_all_proofs(wallet1: Wallet): async def test_invalidate_all_proofs(wallet1: Wallet):
"""Try to invalidate proofs that have not been spent yet. Should not work!""" """Try to invalidate proofs that have not been spent yet. Should not work!"""
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
await wallet1.invalidate(wallet1.proofs) await wallet1.invalidate(wallet1.proofs)
assert wallet1.balance == 0 assert wallet1.balance == 0
@@ -440,18 +438,18 @@ async def test_invalidate_all_proofs(wallet1: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_invalidate_unspent_proofs_with_checking(wallet1: Wallet): async def test_invalidate_unspent_proofs_with_checking(wallet1: Wallet):
"""Try to invalidate proofs that have not been spent yet but force no check.""" """Try to invalidate proofs that have not been spent yet but force no check."""
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
await wallet1.invalidate(wallet1.proofs, check_spendable=True) await wallet1.invalidate(wallet1.proofs, check_spendable=True)
assert wallet1.balance == 64 assert wallet1.balance == 64
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_split_invalid_amount(wallet1: Wallet): async def test_split_invalid_amount(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
await assert_err( await assert_err(
wallet1.split(wallet1.proofs, -1), wallet1.split(wallet1.proofs, -1),
"amount can't be negative", "amount can't be negative",
@@ -460,9 +458,9 @@ async def test_split_invalid_amount(wallet1: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_token_state(wallet1: Wallet): async def test_token_state(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
assert wallet1.balance == 64 assert wallet1.balance == 64
resp = await wallet1.check_proof_state(wallet1.proofs) resp = await wallet1.check_proof_state(wallet1.proofs)
assert resp.states[0].state.value == "UNSPENT" assert resp.states[0].state.value == "UNSPENT"

View File

@@ -33,12 +33,14 @@ async def test_invoice(wallet: Wallet):
while state.pending: while state.pending:
print("checking invoice state") print("checking invoice state")
response2 = client.get( 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()) state = PaymentStatus.parse_obj(response2.json())
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
print("state:", state) print("state:", state)
print("paid") print("paid")
await wallet.load_proofs()
assert wallet.available_balance >= 100
@pytest.mark.skipif(is_regtest, reason="regtest") @pytest.mark.skipif(is_regtest, reason="regtest")
@@ -175,7 +177,7 @@ async def test_flow(wallet: Wallet):
while state.pending: while state.pending:
print("checking invoice state") print("checking invoice state")
response2 = client.get( 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()) state = PaymentStatus.parse_obj(response2.json())
await asyncio.sleep(0.1) 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 = [ removed_empty_and_hiphens = [
value for value in splitted if value and not value.startswith("-----") 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 = { dict_output = {
f"{value.split(': ')[0]}": value.split(": ")[1] f"{value.split(': ')[0]}": value.split(": ")[1]
for value in removed_empty_and_hiphens 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): 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(): async def init_wallet():
@@ -204,8 +209,8 @@ def test_invoices_with_minting(cli_prefix):
# arrange # arrange
wallet1 = asyncio.run(init_wallet()) wallet1 = asyncio.run(init_wallet())
asyncio.run(reset_invoices(wallet=wallet1)) asyncio.run(reset_invoices(wallet=wallet1))
invoice = asyncio.run(wallet1.request_mint(64)) mint_quote = asyncio.run(wallet1.request_mint(64))
asyncio.run(pay_if_regtest(invoice.bolt11)) asyncio.run(pay_if_regtest(mint_quote.request))
# act # act
runner = CliRunner() runner = CliRunner()
result = runner.invoke( result = runner.invoke(
@@ -217,18 +222,14 @@ def test_invoices_with_minting(cli_prefix):
print("INVOICES --mint") print("INVOICES --mint")
assert result.exception is None assert result.exception is None
assert result.exit_code == 0 assert result.exit_code == 0
assert "No invoices found." not in result.output assert "Received 64 sat" 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"
def test_invoices_without_minting(cli_prefix): def test_invoices_without_minting(cli_prefix):
# arrange # arrange
wallet1 = asyncio.run(init_wallet()) wallet1 = asyncio.run(init_wallet())
asyncio.run(reset_invoices(wallet=wallet1)) asyncio.run(reset_invoices(wallet=wallet1))
invoice = asyncio.run(wallet1.request_mint(64)) mint_quote = asyncio.run(wallet1.request_mint(64))
# act # act
runner = CliRunner() runner = CliRunner()
@@ -243,9 +244,11 @@ def test_invoices_without_minting(cli_prefix):
assert result.exit_code == 0 assert result.exit_code == 0
assert "No invoices found." not in result.output assert "No invoices found." not in result.output
assert "ID" in result.output assert "ID" in result.output
assert "Paid" in result.output assert "State" in result.output
assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote
assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid) assert get_invoice_from_invoices_command(result.output)["State"] == str(
mint_quote.state
)
@pytest.mark.skipif(not is_fake, reason="only on fakewallet") @pytest.mark.skipif(not is_fake, reason="only on fakewallet")
@@ -259,11 +262,11 @@ def test_invoices_with_onlypaid_option(cli_prefix):
runner = CliRunner() runner = CliRunner()
result = runner.invoke( result = runner.invoke(
cli, cli,
[*cli_prefix, "invoices", "--only-paid", "--mint"], [*cli_prefix, "invoices", "--only-paid"],
) )
# assert # assert
print("INVOICES --only-paid --mint") print("INVOICES --only-paid")
assert result.exception is None assert result.exception is None
assert result.exit_code == 0 assert result.exit_code == 0
assert "No invoices found." in result.output assert "No invoices found." in result.output
@@ -314,7 +317,7 @@ def test_invoices_with_onlyunpaid_option_without_minting(cli_prefix):
# arrange # arrange
wallet1 = asyncio.run(init_wallet()) wallet1 = asyncio.run(init_wallet())
asyncio.run(reset_invoices(wallet=wallet1)) asyncio.run(reset_invoices(wallet=wallet1))
invoice = asyncio.run(wallet1.request_mint(64)) mint_quote = asyncio.run(wallet1.request_mint(64))
# act # act
runner = CliRunner() runner = CliRunner()
@@ -329,9 +332,11 @@ def test_invoices_with_onlyunpaid_option_without_minting(cli_prefix):
assert result.exit_code == 0 assert result.exit_code == 0
assert "No invoices found." not in result.output assert "No invoices found." not in result.output
assert "ID" in result.output assert "ID" in result.output
assert "Paid" in result.output assert "State" in result.output
assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote
assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid) assert get_invoice_from_invoices_command(result.output)["State"] == str(
mint_quote.state
)
def test_invoices_with_both_onlypaid_and_onlyunpaid_options(cli_prefix): 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 # arrange
wallet1 = asyncio.run(init_wallet()) wallet1 = asyncio.run(init_wallet())
asyncio.run(reset_invoices(wallet=wallet1)) asyncio.run(reset_invoices(wallet=wallet1))
invoice = asyncio.run(wallet1.request_mint(64)) mint_quote = asyncio.run(wallet1.request_mint(64))
# act # act
runner = CliRunner() runner = CliRunner()
@@ -389,9 +394,11 @@ def test_invoices_with_pending_option_without_minting(cli_prefix):
assert result.exit_code == 0 assert result.exit_code == 0
assert "No invoices found." not in result.output assert "No invoices found." not in result.output
assert "ID" in result.output assert "ID" in result.output
assert "Paid" in result.output assert "State" in result.output
assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote
assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid) assert get_invoice_from_invoices_command(result.output)["State"] == str(
mint_quote.state
)
def test_wallets(cli_prefix): def test_wallets(cli_prefix):

View File

@@ -57,9 +57,9 @@ async def wallet2():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_create_htlc_secret(wallet1: Wallet): async def test_create_htlc_secret(wallet1: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
secret = await wallet1.create_htlc_lock(preimage=preimage) secret = await wallet1.create_htlc_lock(preimage=preimage)
@@ -68,9 +68,9 @@ async def test_create_htlc_secret(wallet1: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_htlc_split(wallet1: Wallet, wallet2: Wallet): async def test_htlc_split(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
secret = await wallet1.create_htlc_lock(preimage=preimage) secret = await wallet1.create_htlc_lock(preimage=preimage)
@@ -81,9 +81,9 @@ async def test_htlc_split(wallet1: Wallet, wallet2: Wallet):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_htlc_redeem_with_preimage(wallet1: Wallet, wallet2: Wallet): async def test_htlc_redeem_with_preimage(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() # preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
secret = await wallet1.create_htlc_lock(preimage=preimage) 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 @pytest.mark.asyncio
async def test_htlc_redeem_with_wrong_preimage(wallet1: Wallet, wallet2: Wallet): async def test_htlc_redeem_with_wrong_preimage(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() # preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
secret = await wallet1.create_htlc_lock( 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 @pytest.mark.asyncio
async def test_htlc_redeem_with_no_signature(wallet1: Wallet, wallet2: Wallet): async def test_htlc_redeem_with_no_signature(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() # 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 @pytest.mark.asyncio
async def test_htlc_redeem_with_wrong_signature(wallet1: Wallet, wallet2: Wallet): async def test_htlc_redeem_with_wrong_signature(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() # 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 @pytest.mark.asyncio
async def test_htlc_redeem_with_correct_signature(wallet1: Wallet, wallet2: Wallet): async def test_htlc_redeem_with_correct_signature(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() # 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 @pytest.mark.asyncio
async def test_htlc_redeem_with_2_of_1_signatures(wallet1: Wallet, wallet2: Wallet): async def test_htlc_redeem_with_2_of_1_signatures(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.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 @pytest.mark.asyncio
async def test_htlc_redeem_with_2_of_2_signatures(wallet1: Wallet, wallet2: Wallet): async def test_htlc_redeem_with_2_of_2_signatures(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.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( async def test_htlc_redeem_with_2_of_2_signatures_with_duplicate_pubkeys(
wallet1: Wallet, wallet2: Wallet wallet1: Wallet, wallet2: Wallet
): ):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = pubkey_wallet1 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( async def test_htlc_redeem_with_3_of_3_signatures_but_only_2_provided(
wallet1: Wallet, wallet2: Wallet wallet1: Wallet, wallet2: Wallet
): ):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.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( async def test_htlc_redeem_with_2_of_3_signatures_with_2_valid_and_1_invalid_provided(
wallet1: Wallet, wallet2: Wallet wallet1: Wallet, wallet2: Wallet
): ):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.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( async def test_htlc_redeem_with_3_of_3_signatures_with_2_valid_and_1_invalid_provided(
wallet1: Wallet, wallet2: Wallet wallet1: Wallet, wallet2: Wallet
): ):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.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( async def test_htlc_redeem_hashlock_wrong_signature_timelock_correct_signature(
wallet1: Wallet, wallet2: Wallet wallet1: Wallet, wallet2: Wallet
): ):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.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( async def test_htlc_redeem_hashlock_wrong_signature_timelock_wrong_signature(
wallet1: Wallet, wallet2: Wallet wallet1: Wallet, wallet2: Wallet
): ):
invoice = await wallet1.request_mint(64) mint_quote = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, quote_id=mint_quote.quote)
preimage = "00000000000000000000000000000000" preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.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 # fill wallet
invoice = await wallet.create_invoice(64) invoice = await wallet.create_invoice(64)
assert invoice.payment_request assert invoice.payment_request
assert invoice.checking_id status = await wallet.get_invoice_status(invoice.payment_request)
status = await wallet.get_invoice_status(invoice.checking_id)
assert status.settled assert status.settled
@@ -92,11 +91,10 @@ async def test_check_invoice_external(wallet: LightningWallet):
# fill wallet # fill wallet
invoice = await wallet.create_invoice(64) invoice = await wallet.create_invoice(64)
assert invoice.payment_request assert invoice.payment_request
assert invoice.checking_id status = await wallet.get_invoice_status(invoice.payment_request)
status = await wallet.get_invoice_status(invoice.checking_id)
assert not status.settled assert not status.settled
await pay_if_regtest(invoice.payment_request) 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 status.settled
@@ -106,8 +104,7 @@ async def test_pay_invoice_internal(wallet: LightningWallet):
# fill wallet # fill wallet
invoice = await wallet.create_invoice(64) invoice = await wallet.create_invoice(64)
assert invoice.payment_request assert invoice.payment_request
assert invoice.checking_id await wallet.get_invoice_status(invoice.payment_request)
await wallet.get_invoice_status(invoice.checking_id)
assert wallet.available_balance >= 64 assert wallet.available_balance >= 64
# pay invoice # pay invoice
@@ -118,8 +115,7 @@ async def test_pay_invoice_internal(wallet: LightningWallet):
assert status.settled assert status.settled
# check payment # check payment
assert invoice2.checking_id status = await wallet.get_payment_status(invoice2.payment_request)
status = await wallet.get_payment_status(invoice2.checking_id)
assert status.settled assert status.settled
@@ -129,9 +125,8 @@ async def test_pay_invoice_external(wallet: LightningWallet):
# fill wallet # fill wallet
invoice = await wallet.create_invoice(64) invoice = await wallet.create_invoice(64)
assert invoice.payment_request assert invoice.payment_request
assert invoice.checking_id
await pay_if_regtest(invoice.payment_request) 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 status.settled
assert wallet.available_balance >= 64 assert wallet.available_balance >= 64
@@ -141,7 +136,5 @@ async def test_pay_invoice_external(wallet: LightningWallet):
assert status.settled assert status.settled
# check payment # check payment)
assert status.checking_id
status = await wallet.get_payment_status(status.checking_id)
assert status.settled assert status.settled

View File

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

View File

@@ -32,9 +32,9 @@ async def wallet():
@pytest.mark.skipif(is_fake, reason="only regtest") @pytest.mark.skipif(is_fake, reason="only regtest")
async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger): async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
# create hodl invoice # 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") @pytest.mark.skipif(is_fake, reason="only regtest")
async def test_regtest_failed_quote(wallet: Wallet, ledger: Ledger): async def test_regtest_failed_quote(wallet: Wallet, ledger: Ledger):
# fill wallet # fill wallet
invoice = await wallet.request_mint(64) mint_quote = await wallet.request_mint(64)
await pay_if_regtest(invoice.bolt11) 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 assert wallet.balance == 64
# create hodl invoice # 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) assert wallet.mint_info.supports_mpp("bolt11", wallet.unit)
# top up wallet twice so we have enough for two payments # top up wallet twice so we have enough for two payments
topup_invoice = await wallet.request_mint(128) topup_mint_quote = await wallet.request_mint(128)
await pay_if_regtest(topup_invoice.bolt11) await pay_if_regtest(topup_mint_quote.request)
proofs1 = await wallet.mint(128, id=topup_invoice.id) proofs1 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
assert wallet.balance == 128 assert wallet.balance == 128
# this is the invoice we want to pay in two parts # 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) assert wallet.mint_info.supports_mpp("bolt11", wallet.unit)
# top up wallet twice so we have enough for three payments # top up wallet twice so we have enough for three payments
topup_invoice = await wallet.request_mint(128) topup_mint_quote = await wallet.request_mint(128)
await pay_if_regtest(topup_invoice.bolt11) await pay_if_regtest(topup_mint_quote.request)
proofs1 = await wallet.mint(128, id=topup_invoice.id) proofs1 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
assert wallet.balance == 128 assert wallet.balance == 128
topup_invoice = await wallet.request_mint(128) topup_mint_quote = await wallet.request_mint(128)
await pay_if_regtest(topup_invoice.bolt11) await pay_if_regtest(topup_mint_quote.request)
proofs2 = await wallet.mint(128, id=topup_invoice.id) proofs2 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
assert wallet.balance == 256 assert wallet.balance == 256
topup_invoice = await wallet.request_mint(128) topup_mint_quote = await wallet.request_mint(128)
await pay_if_regtest(topup_invoice.bolt11) await pay_if_regtest(topup_mint_quote.request)
proofs3 = await wallet.mint(128, id=topup_invoice.id) proofs3 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
assert wallet.balance == 384 assert wallet.balance == 384
# this is the invoice we want to pay in two parts # 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 @pytest.mark.asyncio
async def test_restore_wallet_after_mint(wallet3: Wallet): async def test_restore_wallet_after_mint(wallet3: Wallet):
await reset_wallet_db(wallet3) await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64) mint_quote = await wallet3.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet3.mint(64, id=invoice.id) await wallet3.mint(64, quote_id=mint_quote.quote)
assert wallet3.balance == 64 assert wallet3.balance == 64
await reset_wallet_db(wallet3) await reset_wallet_db(wallet3)
await wallet3.load_proofs() await wallet3.load_proofs()
@@ -192,9 +192,9 @@ async def test_restore_wallet_after_swap_to_send(wallet3: Wallet):
) )
await reset_wallet_db(wallet3) await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64) mint_quote = await wallet3.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet3.mint(64, id=invoice.id) await wallet3.mint(64, quote_id=mint_quote.quote)
assert wallet3.balance == 64 assert wallet3.balance == 64
_, spendable_proofs = await wallet3.swap_to_send( _, 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" "hello rug want adapt talent together lunar method bean expose beef position"
) )
await reset_wallet_db(wallet3) await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64) mint_quote = await wallet3.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet3.mint(64, id=invoice.id) await wallet3.mint(64, quote_id=mint_quote.quote)
assert wallet3.balance == 64 assert wallet3.balance == 64
_, spendable_proofs = await wallet3.swap_to_send( _, 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) await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64) mint_quote = await wallet3.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet3.mint(64, id=invoice.id) await wallet3.mint(64, quote_id=mint_quote.quote)
assert wallet3.balance == 64 assert wallet3.balance == 64
_, spendable_proofs = await wallet3.swap_to_send( _, spendable_proofs = await wallet3.swap_to_send(
@@ -289,9 +289,9 @@ async def test_restore_wallet_after_send_twice(
wallet3.private_key = PrivateKey() wallet3.private_key = PrivateKey()
await reset_wallet_db(wallet3) await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(2) mint_quote = await wallet3.request_mint(2)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet3.mint(2, id=invoice.id) await wallet3.mint(2, quote_id=mint_quote.quote)
box.add(wallet3.proofs) box.add(wallet3.proofs)
assert wallet3.balance == 2 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) await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64) mint_quote = await wallet3.request_mint(64)
await pay_if_regtest(invoice.bolt11) await pay_if_regtest(mint_quote.request)
await wallet3.mint(64, id=invoice.id) await wallet3.mint(64, quote_id=mint_quote.quote)
box.add(wallet3.proofs) box.add(wallet3.proofs)
assert wallet3.balance == 64 assert wallet3.balance == 64

View File

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